天天看點

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: C 

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: C 

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;

if (s > 256) {

DiePainfully("go away!\n");

}

sz = s;

printf("i=%d, s=%d, sz=%u\n", i, s, sz);

input = GetUserInput("Enter pathname:");

strncpy(path, input, s);

path[255] = '\0';

printf("Path is: %s\n", path);

}

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

例3

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

(問題代碼)

Example Language: C 

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: C 

...

// 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

繼續閱讀