【问题标题】:Stack Corruption Detection using canary value使用金丝雀值的堆栈损坏检测
【发布时间】:2020-07-21 23:42:54
【问题描述】:

我正在阅读一本教科书,该教科书描述了能够检测堆栈何时损坏的防御。书上说:

最新版本的 gcc 将一种称为堆栈保护器的机制合并到生成的代码中以检测缓冲区溢出。这个想法是在任何本地缓冲区和堆栈状态的其余部分之间的堆栈帧中存储一个特殊的金丝雀值,如下图所示:

这个金丝雀值,也称为警戒值,是在每次程序运行时随机生成的,因此攻击者没有简单的方法来确定它是什么。在恢复寄存器状态并从函数返回之前,程序会检查金丝雀是否已被此函数的某些操作或它调用的操作更改。如果是这样,程序会因错误而中止。

我明白了,但我仍然认为这个设计存在缺陷。是的,攻击者可能无法确定 canary 的值是什么,但攻击者知道 canary 的大小(8 字节),因此攻击者可以操纵指针绕过栈中金丝雀所在的这 8 字节区域,然后覆盖返回地址,所以金丝雀实际上什么都不保护,我的理解是否正确?

【问题讨论】:

  • 你能告诉我这本书的书名是什么吗?会很感激的。
  • @LostSoul 你能找到的最好的书,叫做 CSAPP

标签: c stack x86-64 buffer-overflow callstack


【解决方案1】:

如果攻击者有任意写入,那么是的,金丝雀是无用的。事实上,任意写入可以使金丝雀失效的方法有很多,包括覆盖__stack_chk_fail的GOT条目(覆盖金丝雀时调用的函数),或者只是不覆盖金丝雀。然而,任意写入并不总是可获得的。它通常仅在存在格式字符串漏洞时发生。当只有缓冲区溢出时,要写入金丝雀之后的地址,您必须写入该地址之前的地址,其中包括金丝雀。这意味着用缓冲区溢出覆盖返回地址的唯一合理方法是猜测金丝雀或通过另一个漏洞泄漏它。

【讨论】:

  • 对不起,“如果攻击者有任意写入”是什么意思?
  • 任意写入是指可以将任何你想要的值写入你想要的任何内存地址。
【解决方案2】:

首先,重要的是要注意该图虽然正确,但与大多数传统的堆栈图相反。因此,用户输入将从 buf 开始并向上进行。

由于随机堆栈金丝雀放置在缓冲区和返回地址之间,并且攻击的目标通常是覆盖返回地址以重定向程序流,因此无法避免覆盖金丝雀值。这有效地击败了任何依赖缓冲区溢出的漏洞利用。此外,堆栈金丝雀总是以空字节结束,这也使得即使它的值已知也难以编写,因为许多字符串函数将在空字节处终止。

缓冲区溢出漏洞利用如此普遍的原因是程序员很容易意外地获取超出缓冲区容量的输入。在实践中,能够像您建议的那样操作堆栈指针或跳过堆栈金丝雀比缓冲区溢出要困难得多(如果不是不可能的话),并且在许多情况下无论如何都需要控制返回地址。

但是,阻止一种类型的漏洞利用并不意味着其他技术不可行。正如 Aplet 所提到的,还有其他技术可以绕过或取消堆栈金丝雀提供的保护。不可能阻止所有的利用技术,一般来说,应用的保护越多,性能损失就越大。堆栈金丝雀在性能损失小和检测大量攻击之间取得了很好的平衡。

【讨论】:

  • 这是组织堆栈图的一种非常典型的方式,它会向下增长。数组的索引从左到右甚至会变小,这对于使用从左到右自上而下的语言的人来说是有意义的。
  • 这是真的!我已经看到了面向两个方向的堆栈,我认为任何一个都不比另一个少见。我所说的“传统的堆栈图”的意思是从纯粹的数据结构角度来看的堆栈,从顶部推送和弹出。我教初学者,有时把它画下来让他们感到困惑,所以我想澄清一下也没有什么坏处。
  • 您提到这些漏洞很常见。我想知道,现在缓冲区溢出漏洞在实践中有多普遍?听起来任何最新的系统都会有保护机制来防止它,对吧?
猜你喜欢
  • 2016-10-04
  • 1970-01-01
  • 1970-01-01
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 2016-02-12
  • 1970-01-01
相关资源
最近更新 更多