为了避免 C 或 C++ 中的整数溢出问题,有人建议使用无符号整数。这如何防止可能的溢出攻击?当增加超过其最大值时,无符号整数是否最终仍会溢出?
使用无符号整数如何防止整数溢出攻击?
使用无符号整数并不能防止溢出。一个k位变量只能表示 2 k个不同的值。无论您如何解释这些位。
您可能指的是C 和 C++ 中的有符号整数溢出是未定义行为这一事实。这意味着 C 或 C++ 国际标准没有指定触发此类溢出的程序的任何行为。将值包装起来或导致运行时异常是有效的选项,就像打开漏洞利用 shell 一样。(当然,没有理智的实现会选择后一种选择。但是通过进一步的后果可能会利用漏洞。)此外,允许编译器基于不会发生带符号溢出的假设进行优化,例如,可能优化远离误导性的溢出检查,例如if (x + 3 < x).
另一方面,对于无符号整数,C 和 C++ 国际标准要求该值环绕,就好像对k位无符号整数的算术是以 2 k为模完成的。这意味着您的程序可以依赖环绕并将其用于自身利益。(或者把自己射到脚上。)
Java 等其他语言也要求有符号整数的可靠环绕。(Java 甚至没有无符号整数类型。)
然而,说到安全性,溢出带来的最大威胁是您的应用程序逻辑没有预料到环绕。无论您使用的是有符号整数类型还是无符号整数类型,这都是一个问题。如果您的应用程序逻辑假设对于n字节的请求,它需要分配一个n + m字节的缓冲区(对于用于记账的小常数m )并且n恰好小于您的最大值以下的m整数可以保持,环绕将导致您的程序分配一个太小的缓冲区,这反过来又会溢出。漏洞利用就来了。
如果您想要安全,而不是始终使用无符号整数算术,我建议您完全相反:使用有符号整数算术并使用UbSan编译。除非您的应用程序计算量很大,否则它只会有很小的运行时开销,但如果发生意外事件并且您的应用程序溢出一个整数,则清理程序添加的额外代码将在攻击者利用它之前杀死您的应用程序。无法编写用于溢出无符号整数类型的类似清理程序,因为标准需要明确定义的行为来执行此操作,并且程序合法地依赖它。这实际上是语言中未定义的行为可以帮助您的应用程序更安全的一种情况。