CWE-839: Numeric Range Comparison Without Minimum Check(無最小檢查的數值範圍比較)

 ID: 839

類型:基礎
結構:簡單

狀態:未完成

描述

The program checks a value to ensure that it is less than or equal to a maximum, but it does not also verify that the value is greater than or equal to the minimum.

擴展描述

有些程序使用有符號整數或浮點數,即使它們的值只預期爲正或0。驗證輸入檢查可能假定值爲正值,並且僅檢查最大值。如果值爲負數,但代碼假定值爲正數,則可能會產生錯誤。如果負值用於內存分配、數組訪問、緩衝區訪問等,則該錯誤可能會產生安全後果。最終,該錯誤可能導致緩衝區溢出或其他類型的內存損壞。

在僅爲正數的上下文中使用負數可能會對其他類型的資源產生安全影響。例如,購物車可能會檢查用戶請求的項目不超過10個,但對-3個項目的請求可能會導致應用程序計算負值並將攻擊者的帳戶記入貸方。

相關視圖

 "研究概念"視圖 (CWE-1000)

Nature

Type

ID

Name

ChildOf

1023

Incomplete Comparison with Missing Factors

CanPrecede

119

Improper Restriction of Operations within the Bounds of a Memory Buffer

CanPrecede

124

Buffer Underwrite ('Buffer Underflow')

CanPrecede

195

Signed to Unsigned Conversion Error

CanPrecede

682

Incorrect Calculation

 "開發概念"視圖 (CWE-699)

Nature

Type

ID

Name

MemberOf

189

Numeric Errors

應用平臺

語言

C (經常出現)

C++ (經常出現)

後果

範圍

衝擊

可能性

完整性
保密性
可利用性

技術衝擊: 修改應用數據; 執行未獲授權的代碼或命令

攻擊者可以修改發送到下游組件的消息或數據的結構,可能會注入命令。

 

可利用性

技術衝擊: DoS: 資源小號 (其它)

在某些情況下,負值可能導致資源消耗。

 

保密性
完整性

技術衝擊: 修改內存; 讀內存

如果使用負值訪問內存、緩衝區或其他可索引結構,則可以在緩衝區邊界之外訪問內存。

 

示例

例1

以下代碼用於從套接字讀取傳入數據包並提取一個或多個頭。

(問題代碼)

Example Language:

DataPacket *packet;
int numHeaders;
PacketHeader *headers;

sock=AcceptSocketConnection();
ReadPacket(packet, sock);
numHeaders =packet->headers;

if (numHeaders > 100) {

ExitError("too many headers!");

}
headers = malloc(numHeaders * sizeof(PacketHeader);
ParsePacketHeaders(packet, headers);

代碼執行檢查以確保數據包不包含太多的頭。但是,numHeaders被定義爲帶符號的int,因此它可能是負數。如果傳入數據包指定了一個值,例如-3,那麼malloc計算將生成一個負數(如果每個頭最多可以有100個字節,則爲-300)。當將此結果提供給malloc()時,首先將其轉換爲大小類型。然後,該轉換會產生一個較大的值,如4294966996,這可能會導致malloc()失敗或分配非常大的內存量(CWE-195)。有了適當的負數,攻擊者可以誘騙malloc()使用非常小的正數,然後分配比預期小得多的緩衝區,這可能導致緩衝區溢出。

例2

以下代碼讀取最大大小,並對該大小執行健全性檢查。然後它執行strncpy,假設它不會超過數組的邊界。在這個特定的示例中,雖然強制使用“short s”,但short int經常用於實際代碼中,例如處理結構化數據的代碼。

(問題代碼)

Example Language:

int GetUntrustedInt () {

return(0x0000FFFF);

}

void main (int argc, char **argv) {

char path[256];
char *input;
int i;
short s;
unsigned int sz;

i = GetUntrustedInt();
s = i;
/* s is -1 so it passes the safety check - CWE-697 */
if (s > 256) {

DiePainfully("go away!\n");

}

/* s is sign-extended and saved in sz */
sz = s;

/* output: i=65535, s=-1, sz=4294967295 - your mileage may vary */
printf("i=%d, s=%d, sz=%u\n", i, s, sz);

input = GetUserInput("Enter pathname:");

/* strncpy interprets s as unsigned int, so it's treated as MAX_INT
(CWE-195), enabling buffer overflow (CWE-119) */
strncpy(path, input, s);
path[255] = '\0'; /* don't want CWE-170 */
printf("Path is: %s\n", path);

}

此代碼首先展示了CWE-839的一個示例,允許“s”爲負數。當負短“s”轉換爲無符號整數時,它將成爲一個非常大的正整數。當strncpy()使用此轉換後的整數時,將導致緩衝區溢出(cwe-119)。

例3

在下面的代碼中,該方法從特定數組索引位置的數組中檢索一個值,該值作爲該方法的輸入參數給定。

(問題代碼)

Example Language:

int getValueFromArray(int *array, int len, int index) {


int value;

// check that the array index is less than the maximum

// length of the array
if (index < len) {


// get the value at the specified index of the array
value = array[index];

}
// if array index is invalid then output error message

// and return value indicating error
else {

printf("Value is: %d\n", array[index]);
value = -1;

}

return value;

}

但是,此方法只驗證給定的數組索引是否小於數組的最大長度,但不檢查最小值(CWE-839)。這將允許接受負值作爲輸入數組索引,這將導致越界讀取(CWE-125),並允許訪問敏感內存。應檢查輸入數組索引,以驗證是否在數組所需的最大和最小範圍內(CWE-129)。在這個例子中,if語句應該修改爲包含一個最小範圍檢查,如下所示。

(正確代碼)

Example Language:


...

// check that the array index is within the correct

// range of values for the array
if (index >= 0 && index < len) {

...

例4

下面的代碼顯示了一個簡單的銀行帳戶類,其中包含存款和取款方法。

(問題代碼)

Example Language: Java 

public class BankAccount {


public final int MAXIMUM_WITHDRAWAL_LIMIT = 350;

// variable for bank account balance
private double accountBalance;

// constructor for BankAccount
public BankAccount() {

accountBalance = 0;

}

// method to deposit amount into BankAccount
public void deposit(double depositAmount) {...}

// method to withdraw amount from BankAccount
public void withdraw(double withdrawAmount) {


if (withdrawAmount < MAXIMUM_WITHDRAWAL_LIMIT) {


double newBalance = accountBalance - withdrawAmount;
accountBalance = newBalance;

}
else {

System.err.println("Withdrawal amount exceeds the maximum limit allowed, please try again...");
...

}

}

// other methods for accessing the BankAccount object
...

}

提取方法包括檢查以確保提取金額不超過允許的最大限額,但該方法不檢查以確保提取金額大於最小值(CWE-129)。對不包括最小檢查的值執行範圍檢查可能會產生重大的安全影響,在這種情況下,不包括最小範圍檢查可能會允許使用負值,這將導致使用此類的財務應用程序將錢存入用戶帳戶而不是提現。在這個例子中,if語句應該修改爲包含最小範圍檢查,如下所示。

(正確代碼)

Example Language: Java 

public class BankAccount {


public final int MINIMUM_WITHDRAWAL_LIMIT = 0;
public final int MAXIMUM_WITHDRAWAL_LIMIT = 350;

...

// method to withdraw amount from BankAccount
public void withdraw(double withdrawAmount) {


if (withdrawAmount < MAXIMUM_WITHDRAWAL_LIMIT &&
withdrawAmount > MINIMUM_WITHDRAWAL_LIMIT) {


...

請注意,此示例不會防止併發訪問BANKACCOUNT BALANCE變量,請參閱CWE-413和CWE-362。             

雖然它超出了本例的範圍,但請注意,在財務計算中使用double或float可能會受到某些類型的攻擊,攻擊者使用舍入錯誤來竊取資金。

應對措施

階段: 實現

策略: 通過轉換強化

如果要使用的數字總是正數,請將變量類型從有符號更改爲無符號或大小。

階段: 實現

策略: 驗證輸入

如果要使用的數字根據規範可能具有負值(因此需要有符號的值),但該數字只能是正數以保持代碼的正確性,則包括一個檢查以確保該值是正數。

種屬

關係

類型

ID

名稱

屬於

884

CWE Cross-section

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章