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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值