heartbleed bug是C中经典缓冲区溢出漏洞的表现吗?

在我们关于安全性的第一次CS讲座中,我们讨论了C的问题,没有检查所谓的缓冲区长度以及可以利用此漏洞的不同方式的一些示例。

在这种情况下,它看起来像是一个恶意读操作的情况,其中应用程序只读出了很多字节的内存

  1. 我是否正确断言Heartbleed错误是C缓冲区长度检查问题的表现?

  2. 为什么恶意使用在尝试读取其他应用程序的内存时不会导致分段错误?

  3. 在写入内存之前简单地将内存归零(然后随后从中读取)会导致分段错误吗? 或者这在操作系统之间有所不同吗? 或者其他一些环境因素?

  4. 显然无法识别漏洞的利用。 是因为心跳function在调用时不记录? 否则,对64k字符串的任何请求肯定是恶意的?

我是否正确断言Heartbleed错误是C缓冲区长度检查问题的表现?

是。

heartbleed bug是C中经典缓冲区溢出漏洞的表现吗?

不可以。“经典”缓冲区溢出是指更多数据写入堆栈分配缓冲区而不是它可以容纳的缓冲区溢出,其中写入的数据由恶意代理提供。 恶意数据溢出缓冲区并覆盖当前方法的返回地址。 当方法结束时,然后返回包含攻击者选择代码的地址并开始执行它。

相比之下,心脏缺陷不会覆盖缓冲区并且不会执行任意代码,它只会读取很可能在内存中附近有敏感数据的代码中的界限。

为什么恶意使用在尝试读取其他应用程序的内存时不会导致分段错误?

它没有尝试读取另一个应用程序的内存。 漏洞利用读取当前进程的内存,而不是另一个进程。

为什么恶意使用在尝试读取超出缓冲区范围的内存时会导致分段错误?

这是这个问题的副本:

为什么这不会给出分段违规错误?

分段错误意味着您触摸了操作系统内存管理器尚未分配给您的页面。 这里的错误是您触及了堆管理器尚未分配给您的有效页面上的数据 。 只要页面有效,您就不会遇到段错误。 通常,堆管理器要求操作系统提供大量内存,然后将其划分到不同的分配中。 就操作系统而言,所有这些分配都在有效的内存页面上。

解除引用null是一个段错误,因为操作系统永远不会使包含零指针的页面成为有效页面。

更一般地说:编译器和运行时不需要确保未定义的行为导致段错误; UB可以导致任何行为,包括什么都不做。 有关此问题的更多想法,请参阅:

可以在其范围之外访问局部变量的内存吗?

对于我抱怨UB 应该始终相当于安全关键代码中的段错误,以及关于漏洞静态分析讨论的一些指示,请参阅今天的博客文章:

http://ericlippert.com/2014/04/15/heartbleed-and-static-analysis/

在写入内存之前简单地将内存归零(然后随后从中读取)会导致分段错误吗?

不太可能。 如果读出界限不会导致段错误,则写入越界不太可能。 一页内存可能是只读的,但在这种情况下似乎不太可能。

当然,将你不应该排除的所有类型的内存归零的后期后果都是整个节目的错误。 如果在该归零内存中有一个指针,您稍后将取消引用,那将取消引用null,这将产生段错误。

这在操作系统之间有所不同吗?

问题很模糊。 让我重新说一下。

不同的操作系统和不同的C / C ++运行时库是否提供了不同的策略来分配虚拟内存,分配堆内存以及识别内存访问何时超出范围?

是; 不同的东西是不同的

或者其他一些环境因素?

如?

显然无法识别漏洞的利用。 是因为心跳function在调用时不记录?

正确。

当然对64k字符串的任何请求都可能是恶意的?

我没跟随你的思路。 什么使得请求可能是恶意的是发送的字节和请求回显的字节之间的不匹配,而不是要求回显的数据的大小。

不会发生分段错误,因为访问的数据紧邻所请求的数据,并且通常在同一进程的内存中。 如果请求足够大,它可能会导致exception,但这样做并不符合开发人员的利益,因为崩溃进程会阻止他们获取数据。

为了清楚解释,这个XKCD漫画很难更好:

在此处输入图像描述