CWE-195: Signed to Unsigned Conversion Error(有符号到无符号转换错误)

 ID: 195

类型:变量
结构:简单

状态:草稿

描述

软件使用有符号数据将其强制转换到无符号数据,如果有符号数据的值不能用无符号数据表示,则会产生意外的值

扩展描述

依赖有符号数和无符号数之间的隐式强制转换是很危险的,因为结果可能具有意外的值,并且违反了程序所做的假设。

通常,函数会返回负值来表示失败。当函数的结果用作大小参数时,使用这些负返回值可能会产生意外的结果。例如,如果将负的大小值传递给标准内存复制或分配函数,它们将隐式转换为一个大的无符号值。这可能导致可利用的缓冲区溢出或下溢情况。

相关视图

与“研究层面”视图(CWE-1000)相关

与“开发层面”视图(CWE-699)相关

引入模式

阶段

说明

实现

 

应用平台

语言

C (出现的可能性不确定)

C++ (出现的可能性不确定)

后果

范围

冲击

可能性

完整性

技术冲击: 未知状态

有符号和无符号值之间的转换可以导致各种错误,但从安全角度来说,最常见的是同整数溢出和缓冲区溢出漏洞相关联。

 

示例

例1

在本例中,变量金额在返回时可以保留负值。因为函数声明为返回无符号int,所以金额将隐式转换为无符号。

(问题代码)

Example Language:

unsigned int readdata () {

int amount = 0;
...
if (result == ERROR)
amount = -1;
...
return amount;

}

如果满足上述代码中的错误条件,则在使用32位整数的系统上,readdata()的返回值将为4294967295。

例2

在本例中,根据accecssMainframe()的返回值,变量量在返回时可以保持负值。因为函数被声明为返回无符号值,所以金额将隐式转换为无符号数字。

(问题代码)

Example Language:

unsigned int readdata () {

int amount = 0;
...
amount = accessmainframe();
...
return amount;

}

如果accessMainframe()的返回值为-1,那么在使用32位整数的系统上,readData()的返回值将为4294967295。

例3

以下代码用于从套接字读取传入数据包并提取一个或多个头。

(问题代码)

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()使用非常小的正数,然后分配比预期小得多的缓冲区,这可能导致缓冲区溢出。

例4

此示例处理由一系列可变长度结构组成的用户输入。输入的前2个字节指示要处理的结构的大小。

(问题代码)

Example Language:

char* processNext(char* strm) {

char buf[512];
short len = *(short*) strm;
strm += sizeof(len);
if (len <= 512) {

memcpy(buf, strm, len);
process(buf);
return strm + len;

}
else {

return -1;

}

}

程序员在结构大小上设置了一个上限:如果大于512,则不会处理输入。问题是len是有符号短,因此对最大结构长度的检查是用有符号值完成的,但是len被转换为无符号整数以调用memcpy(),负位将被扩展,从而为无符号整数生成一个巨大的值。如果len为负,那么结构似乎有一个适当的大小(将采用if分支),但是memcpy()复制的内存量将非常大,攻击者将能够用strm中的数据溢出堆栈。

例5

在下面的示例中,可以请求memcpy移动比假定的内存段大得多的内存段:

(问题代码)

Example Language:

int returnChunkSize(void *) {


/* if chunk info is valid, return the size of usable memory,

* else, return -1 to indicate an error

*/
...

}
int main() {

...
memcpy(destBuf, srcBuf, (returnChunkSize(destBuf)-1));
...

}

如果returnChunkSize()遇到错误,它将返回-1。请注意,在memcpy操作(cwe-252)之前不会检查返回值,因此-1可以作为size参数传递给memcpy()(cwe-805)。因为memcpy()假定该值是无符号的,所以它将被解释为maxint-1(cwe-195),因此将复制比目标缓冲区(cwe-787、cwe-788)可能可用的内存多得多的内存。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值