【问题标题】:How is integer overflow exploitable?整数溢出如何被利用?
【发布时间】:2023-03-17 18:49:01
【问题描述】:

有人对如何利用整数有详细的解释吗?我已经阅读了很多关于这个概念的内容,我理解它是什么,我理解缓冲区溢出,但我不明白如何通过使整数大于它定义的内存....

【问题讨论】:

标签: security integer-overflow exploit


【解决方案1】:

绝对是可以利用的,但当然要视情况而定。

旧版本的 ssh 有一个整数溢出,可以远程利用。该漏洞导致 ssh 守护进程创建一个大小为零的哈希表,并在尝试在其中存储一些值时覆盖内存。

更多关于 ssh 整数溢出的细节:http://www.kb.cert.org/vuls/id/945216

关于整数溢出的更多细节:http://projects.webappsec.org/w/page/13246946/Integer%20Overflows

【讨论】:

  • 正如下面由 Ira Baxter 解释的示例,它必须是这样的特定情况 - 在分配允许您访问内存的哈希/缓冲区/数组时,您过度/不足流过一个整数不应该访问,然后有办法计算 FP 等。
  • @wuntee:我认为像这样缩小范围没有任何意义。每种情况都不同。足智多谋的人会找到一种无法想象的方式!我记得在 netscape 中有一个单独的错误,它用空格覆盖了单个字节。人们能够利用它!
  • 我很想知道缓冲区下溢的情况。
【解决方案2】:

我在 60 年代后期在 IBM 360/40 上使用 APL/370。 APL 是一种语言,其中基本上所有事物都是多维数组,并且有许多令人惊叹的操作符用于操作数组,包括从 N 维重塑为 M 维等。

不出所料,N 维数组的索引范围为 1..k,每个轴都有不同的 k.. 并且 k 在法律上总是小于 2^31(a 中的正值) 32 位有符号机器字)。现在,一个 N 维数组在内存中分配了一个位置。 APL 会根据数组上限检查使用对于轴而言太大的索引来访问数组槽的尝试。当然,这适用于 N == 1 的 N 维数组。

APL 没有检查您是否使用 RHO(数组重塑)运算符做了一些非常愚蠢的事情。 APL 只允许最多 64 个维度。因此,您可以创建一个 1-64 维的数组,如果数组维数都小于 2^31,APL 会这样做。或者,您可以尝试创建一个 65 维度的数组。在这种情况下,APL 搞砸了,出乎意料地返回了一个 64 维数组,但是未能检查轴的大小。 (这实际上是“发生整数溢出”的地方)。这意味着您可以创建一个轴大小为 2^31 或更大的数组...但被解释为有符号整数,它们被视为负数。

应用于此类数组的正确 RHO 运算符咒语可以将维数减少到 1,其上限为“-1”。称这个矩阵为“虫洞”(你马上就会明白为什么)。这样的虫洞阵列有 内存中的一个位置,就像任何其他数组一样。但是所有数组访问都根据上限进行检查...但是数组边界检查结果是由 APL 的 unsigned 比较完成的。因此,您可以毫无异议地访问 WORMHOLE[1]、WORMHOLE[2]、... WORMHOLE[2^32-2]。实际上,您可以访问整个机器的内存。

APL 还有一个数组赋值操作,您可以在其中用一个值填充数组。 WORMHOLE[]所有内存归零。

我只这样做了一次,因为它删除了包含我的 APL 工作区、APL 解释器的内存,以及显然启用分时共享的 APL 的关键部分(在那些日子里,它不受用户保护)......终端房间 在大约 2 秒内从其机械噪音非常大的正常状态(我们有 2741 个 Selectric APL 终端)变为完全无声。 透过玻璃进入计算机室,我可以看到操作员抬头看着 370 上的灯,因为它们都熄灭了。随之而来的是大量的跑来跑去。

虽然当时很有趣,但我还是闭上了嘴。

稍加小心,显然有人可能以任意方式篡改操作系统。

【讨论】:

  • 我绝对可以看到如何利用这一点(因为您可以访问机器的所有内存)。我想这个想法是这一切都取决于具体情况 - 在这种情况下,应用程序不会检查数组的分配,其中数组的大小是整数。我的思绪停留在简单的“缓冲区溢出”上,并认为有某种方法可以让 'int x = y + z * w' y 和 z 和 w 都是用户定义的,并且在该语句中可以以某种方式覆盖内存以可靠的方式。
  • 好吧,我的示例中的应用程序正在对数组分配进行边界检查,但实际上该检查因数组绑定本身的溢出而失败。你可以让你的例子像这样工作:x=y+z; data[x] x 的计算溢出。在 C 中,没有抱怨;你根据定义得到@(&data+x)。如果您可以将 x 设置为任何内容(通过溢出),则可以访问任何内容。
【解决方案3】:

这取决于变量的使用方式。如果你从来没有根据你添加的整数和输入整数做出任何安全决定(对手可能会引发溢出),那么我想不出你会遇到什么麻烦(但这种东西可能很微妙)。

再说一次,我见过很多这样的代码不能验证用户输入(虽然这个例子是人为的):

int pricePerWidgetInCents = 3199;
int numberOfWidgetsToBuy = int.Parse(/* some user input string */);
int totalCostOfWidgetsSoldInCents = pricePerWidgetInCents * numberOfWidgetsToBuy; // KA-BOOM!

// potentially much later
int orderSubtotal = whatever + totalCostOfWidgetInCents;

直到您以 - 21,474,817.95 美元的价格售出 671,299 个小部件的那一天,一切都变得很糟糕。老板可能会生气。

【讨论】:

  • 是的,但是您如何利用它来发挥自己的优势?你怎么能导致它覆盖帧指针 - 例如......
  • 一个更好的例子是:int arraySize = [一些用户输入];整数数组[arraySize];
  • 您不能使用此示例覆盖帧指针。但是,您可以使用它来窃取 4200 万美元,这仍然是在利用安全问题。
【解决方案4】:

一个常见的情况是通过询问将提供的输入数量,然后尝试强制执行该限制来防止缓冲区溢出的代码。考虑我声称提供 2^30+10 个整数的情况。接收系统分配一个 4*(2^30+10)=40 字节 (!) 的缓冲区。由于内存分配成功,我可以继续。当我发送第 11 个输入时,输入缓冲区检查不会阻止我,因为 11

【讨论】:

    【解决方案5】:

    我只是想总结一下我发现的关于我最初的问题的所有内容。

    事情让我感到困惑的原因是因为我知道缓冲区溢出是如何工作的,并且可以理解如何轻松利用它。整数溢出是一种不同的情况——你不能利用整数溢出来添加任意代码,并强制改变应用程序的流程。

    但是,整数可能会溢出,例如,该整数用于索引数组以访问内存的任意部分。从这里开始,可能会使用错误索引的数组来覆盖内存并导致应用程序的执行改变为您的恶意意图。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 2012-06-02
      • 2010-10-02
      • 2014-01-24
      • 2016-05-30
      • 1970-01-01
      相关资源
      最近更新 更多