1、有符号整数溢出
C/C++中的整数类型分为有符号整数和无符号整数,其中有符号整数的最高位表示符号(正或负),其余位表示数值大小,而无符号整数则所有位都用于表示数值大小。有符号整数的取值范围为[−2n−1, 2n−1−1],当有符号整数的值超出了有符号整数的取值范围时就会出现整数溢出,导致有符号整数溢出的重要原因之一是有符号整数的运算操作不当,常见运算 “+”、”-“、 “*”、 “/”、 “%”、 “++”、 “–” 等等,如果没有对值的范围进行判断和限制,很容易导致有符号整数溢出问题。
2、 有符号整数溢出的危害
有符号整数溢出将会产生数值错误,依据对错误的数值使用的位置不同(如错误的数据用于内存操作、又或者错误的数值导致循环恒为真等),将可能导致不同的安全问题,包括拒绝服务攻击、内存破坏等。
CVE中有大量与之相关的漏洞信息,仅2018年1月至12月,CVE中就有605条相关漏洞信息。部分漏洞如下:
CVE 编号 | 概述 |
---|---|
CVE-2018-1000876 | binutils 在 2.32 及更早版本中包含一个整数溢出漏洞,攻击成功后导致任意代码执行,这个漏洞在 3a551c7a1b80fca579461774860574eabfd7f18f 修复。 |
CVE-2018-1000098 | teluu pjsip 2.7.1 及更低版本在 pjmedia sdp 解析中包含一个可能导致崩溃的整数溢出漏洞。这种攻击可以通过发送一条精心设计的消息来加以利用。该漏洞似乎已在 2.7.2 中修复。 |
CVE-2018-1000524 | miniSphere 5.2.9 版本及更早版本中,mapengine.c 文件中的 layerresize() 函数包含一个整数溢出漏洞,该漏洞会导致拒绝服务攻击。该漏洞在5.0.3、5.1.5、5.2.10 及更高版本中修复。 |
CVE-2018-1000127 | memcached 1.4.37 以前的版本 items.c:item_free() 包含整数溢出漏洞,这可能导致数据损坏和死锁。此漏洞在 1.4.37 及更高版本中修复。 |
3、示例代码
本章节中所使用的示例代码来源于 Samate Juliet Test Suite for C/C++ v1.3 (https://samate.nist.gov/SARD/testsuite.php),源文件名:CWE190_Integer_Overflow__int64_t_max_multiply_01.c。
3.1缺陷代码
在上述示例代码中,虽然在第28行通过 if() 语句保证了 data 的值不能小于等于0,但并没有对 data 值的上限进行限制,当第31行进行 data*2 运算后赋值给 result,超出 result 类型的最大值,从而导致有符号整数溢出问题。
使用360代码卫士对上述示例代码进行检测,可以检出“有符号整数溢出”缺陷,显示等级为高。如图1所示:
图1:有符号整数溢出的检测示例
3.2 修复代码
在上述修复代码中,Samate 给出的修复方式为: 在第31行通过 if() 语句对 data 的最大值进行限制,从而避免了在第33行进行 data*2 操作时产生有符号整数溢出。
使用360代码卫士对修复后的代码进行检测,可以看到已不存在“有符号整数溢出”缺陷。如图2:
图2:修复后检测结果
4 、如何避免有符号整数溢出
要避免有符号整数溢出,需要注意以下几点:
(1)在进行有符号整数操作时,需对有符号数整数的取值范围进行有效判断;
(2)对来自不可信源的有符号整数进行运算操作时,需要额外注意。
(3)使用源代码静态分析工具进行自动化的检测,可以有效的发现源代码中的有符号整数溢出问题。