当整数运算的结果不适合分配的内存空间时,整数溢出是一种算术溢出错误。它通常导致结果意外,而不是程序中的错误。整数溢出已被列为最近8个最危险的软件错误 CWE 2019 列出,主要是因为它们经常导致 缓冲区溢出,根据该列表,它们是目前最危险的软件错误第一名。

整数溢出如何发生

在大多数编程语言中,整数值通常在内存中分配一定数量的位。例如,为32位整数数据类型保留的空间可以存储0到4,294,967,295之间的无符号整数或-2,147,483,648和2,147,483,647之间的有符号整数。对于带符号整数,最高有效(第一)位通常表示整数是正值还是负值。

但是,执行计算时会发生什么 4,294,967,295 + 1 并尝试存储大于整数类型最大值的结果?它完全取决于语言和编译器。而且,不幸的是, 大多数语言和大多数编译器完全不会出错 并仅执行模运算,环绕或截断,或者它们具有其他未定义的行为。对于上面的示例,结果通常为0。

对于带符号整数,结果可能更加出乎意料。当您超过有符号整数的最大值时,结果通常变为负数。例如, 2,147,483,647 +1 is usually −2,147,483,648。当您低于最小值(下溢)时,结果通常为正数。例如, −2,147,483,648 − 1 is usually 2,147,483,647。

除了典型的操作(例如加法,减法或乘法)外,由于类型转换,整数溢出也可能发生。例如,一个操作可能会将整数视为无符号的整数,而另一操作可能会将完全相同的整数视为有符号的整数,因此会错误地解释该值。

整数溢出风险

大多数整数溢出条件仅会导致错误的程序行为,但不会引起任何漏洞。但是,在某些情况下,整数溢出可能会带来严重的后果:

  • 如果在计算缓冲区长度时发生整数溢出,则可能会导致缓冲区溢出。缓冲区溢出使攻击者可以获得外壳程序访问权并进一步尝试 特权升级.
  • 如果在财务计算过程中发生整数溢出,则可能例如导致客户获得信贷而不是购买货款,或者可能导致负帐户余额变为正数。

在较旧版本的OpenSSH(3.3)中可以找到导致缓冲区溢出的整数溢出的一个很好的例子:

nresp = packet_get_int();
if (nresp > 0) {
 response = xmalloc(nresp*sizeof(char*));
 for (i = 0; i < nresp; i++)
  response[i] = packet_get_string(NULL);
} 

If nresp is 1073741824 and sizeof(char*) is 4 (通常),然后 nresp*sizeof(char*) 导致溢出。所以, xmalloc() 接收并分配一个0字节的缓冲区。随后的循环会导致堆缓冲区溢出,攻击者随后可能会使用该缓冲区溢出来执行任意代码。

防止整数溢出

即使是最基本的整数溢出,最大的问题是很难发现和防止它们。没有错误,没有警告,您只是得到错误的操作结果。发现它们的唯一方法是在操作之前检查操作数或在操作之后检查结果(例如,检查两个正数的加法结果是否小于操作数)。

根据语言的不同,您也许可以遇到有助于防止和发现整数溢出的库或机制。对于GCC编译器,有 内置功能 检查整数溢出。对于C ++程序,有一个名为 安全情报 执行安全操作。不幸的是,在所有代码中对所有算术运算强制使用此库可能并不容易。

如果您想了解有关整数溢出的更多信息,建议您仔细阅读 blexim的文章.

来源: //www.acunetix.com/blog/web-security-zone/what-is-integer-overflow/