我的大多数没有计算机经验的朋友都想知道 Heartbleed 是什么以及它是如何工作的。如何向没有技术背景的人解释 Heartbleed?
没有技术术语如何解释 Heartbleed?
银行与银行员工的类比
你打电话给银行要求一个新的银行账户,预约 - 随便什么。不知何故,你和银行确保你是你自己,而银行实际上就是银行。这是保护您与银行之间连接的 TLS 流程,我们假设这已得到妥善处理。
本剧中的角色
- 银行:网络服务器
- 银行员工:该服务器的 OpenSSL 服务
- 你(银行劫匪):一个机器人从服务器获取所有它可以得到的东西
保持联系 - 心跳
银行员工接听您的电话。您要求提供一些信息。员工说等一下,然后关闭了他的麦克风。他能听到你,你听不到他。然后就安静了。需很长时间。你开始怀疑他是否挂断了电话。所以你说“你好?” 指示员工回应您所说的任何内容,并以“你好”回复。这是检查是否仍有连接的心跳。
现在对于这位特殊的银行员工,您需要先说出您将使用多少字,然后再询问该员工是否仍然在线。所以不要说“你好”,你需要说“一:你好”,或者“二:你好”。员工现在知道他可以通过重复这(前)两个词来回复,然后可以继续处理您的请求。这是心跳协议。
问题 - 心脏出血 - 没有检查返回的内容
好吧,你很无聊,你开个玩笑。你说“千:你好”。员工没有检查你是否只说了一个词(你好),而是开始回复“你好”,然后是他说的、想的或记忆中的接下来的 999 个词,然后才关掉麦克风。这是导致问题的错误。
那 999 个词是不相关的。其中大部分是无用的,关于天气的评论、咖啡的请求、午餐约会等。其中一些可能是有关银行或其他客户的重要信息。运输黄金,客户将带来 100 万美元,进入银行或保险箱的密码等。
没有检查是否真的有 1000 个字要回复。另外,您可以一遍又一遍地执行此请求 - 员工不会抱怨,其他人也不会注意到发生了什么。
有一个限制。您只会从这位银行员工那里获得信息,并且只会从他谈论或思考的内容中获取信息。其他员工不受影响。你看不到他的桌子上或他的通讯录里有什么。(类比:只有内存(RAM)中的数据有风险;硬盘上没有读入内存的数据,以及来自其他程序和进程的数据是安全的。)
这样做你不知道你会得到什么信息,但是一遍又一遍地做很长时间,你会得到足够的信息,最终能够在没有人注意到的情况下闯入。您可以在下班后进入银行,打开保险箱等。这就是涉及的风险。
解决方案 - 检查请求和更新代码
如果员工想了一会儿,他只会回复一个词,然后关闭麦克风,这样你就再也听不到他在讨论什么了。通过进行此检查,您将保持联系并知道员工没有挂断电话,但不会再听到任何随机信息。实际上,员工需要新的指令来回应什么。这已通过更新到最新版本的 OpenSSL 得到修复。
银行必须更新安全密钥才能进入银行和保险箱,因为不知道是否有人拥有旧代码。
我将不得不使用一些技术术语,但会尽量减少并描述它们。
TLS 和加密的基本介绍
您(客户)访问使用加密(地址以 开头)的网站(称为服务器),https://
这样除了您和另一端的网站之外没有人可以知道您发送的消息的内容或接收。因此,当您的消息在互联网上的计算机之间传输时,它们会被加密——他们称之为传输层安全 (TLS),它是一种加密协议。实现 TLS 的一个库是 OpenSSL(TLS 是 SSL 的较新名称,但两者的目的相同——加密互联网上的网络流量)。
什么是 Heartbeat - 受损的 TLS 功能?
要建立 TLS 连接,需要进行相对昂贵的协商(这需要时间)。客户端和服务器之间必须交换几条消息,然后它们才能相互信任并安全地来回发送加密数据。为了获得快速响应的体验(并最小化服务器负载),您希望尽可能少地执行此协商,而不是在每个请求之前执行此协商(因为您通常会在几分钟内执行现代交互式网站的数百个请求)。更复杂的是,互联网上的数据包经常丢失或损坏。服务器可能会因过多的请求而不堪重负,需要断开其 TLS 连接端。或者客户端可能已经关闭了它的浏览器窗口,所以服务器不需要继续存储它的加密连接结束。
因此,在 2012 年,OpenSSL(称为 Heartbeats)中实施了一项提议,以在客户端和服务器之间发送“保持活动”消息以减少协商次数,而双方仍在使用连接。客户端定期询问网络服务器“你还在吗?” 和网络服务器(如果它仍然存在),回复告诉它是否仍然存在或未来的请求是否需要新的 TLS 协商。
心跳扩展的工作原理
客户端发送一个 Heartbeat 消息,该消息由客户端选择的有效负载以及包含有效负载大小的简短标头组成。例如,您可以发送大小18
和文本的 Heartbeat 请求This is my payload
(尽管通常它将是随机选择的数据)。网络服务器获取该请求,将有效负载的内容保存到网络服务器的内存中,并保存18
客户端告诉它的有效负载的大小。
然后,当服务器向客户端发送“保持活动”响应时,库18
从存储有效负载的位置开始读取内存的下一个字符并将其发送回客户端(客户端检查是否收到了正确的数据)然后连接保持活动状态。
OpenSSL 中的 Heartbleed 缺陷
致命缺陷(已被命名为 Heartbleed)是OpenSSL 库从未检查过 Heartbeat 有效负载大小是否与正在发送的有效负载的实际长度相对应。无论有效负载的真实大小如何,用户都可以输入最多 65535(64 KB)的任何数字。如果攻击者发送 Heartbeat 请求说大小是65535
,但是只有 18 个字节长的有效负载,易受攻击的服务器将仅在内存中存储 18 个字节。但是,响应将从存储的 18 个字节开始,但会继续将数据从下一个 64KB 内存发送回客户端。这些数据可能是用户名和密码、私钥、用户名、HTML 页面、随机垃圾,甚至是网络服务器用来建立其身份的私人秘密。(在 1.0.1g 和更高版本中实现的 OpenSSL 修复本质上是对客户端告知的有效负载大小执行完整性检查)。
攻击可以重复多次,通常每次都会暴露网络服务器内存的不同部分。对于典型的网络服务器配置,攻击可以以无法检测的方式匿名执行。通常,您只在提供网页时记录 IP 地址,但这种攻击可能发生在易受攻击版本的协商过程的早期,在提供任何网页之前。
攻击客户端
还有一个相反的版本,连接到恶意 TLS 服务器的用户将信任从恶意服务器发送的保持活动请求,该服务器谎称其保持活动负载的大小。这将导致网络浏览器向网络服务器泄露多达 64KB 的信息。(当然,要从中获取可用信息要困难得多,并且不能匿名完成,并且必须由选择访问该网页的客户端发起。但是,如果您使用受影响的版本。)
补救
使用 OpenSSL 的客户端和服务器的补救措施是更新它。运行使用易受攻击的 OpenSSL 库的网络服务器的系统管理员需要撤销其秘密 TLS 密钥并生成新密钥(以及使长期会话令牌无效)。客户应更改可能已泄露的受影响网站的密码。对于客户端,lastpass 发布了一个heartbleed 检查器工具,用于测试网站是否 (1) 当前易受攻击,(2) 先前测试为易受攻击,或 (3) 可能易受攻击(使用 unix/linux 网络服务器和 TLS,可能表明使用OpenSSL 主要用于 unix/linux 系统),这可能有助于确定您是否需要在给定网站上更新密码。
SSH 不是 TLS,因此 SSH 密钥是安全的
SSH(代表 Secure Shell)是 unix 和 linux 机器上的常用工具,允许用户远程登录机器并发出通过网络加密传输的命令。 SSH 是与 TLS 完全不同的协议(答案是 SSL,但这只是 TLS 的旧名称——这些术语通常可以互换使用)。即使 OpenSSH(最常见的 SSH 实现)和 OpenSSL 具有相似的名称,您的 SSH 密钥也不会因为 Heartbleed 攻击而受到攻击。
只有进行 TLS 加密的进程的内存可以通过 Heartbleed 攻击泄露。(进程是应用程序运行实例的计算术语。)现代操作系统实现进程隔离,以防止进程读取或写入分配给同一系统上其他进程的内存。因此,与xkcd.com/1353 不同的是,您不必担心计算机的所有内存都会受到损害,只需担心网络服务器进程的内存(或反向形式的网络浏览器)。其他进程(ssh、sshd、ssh-agent)使用的 SSH 密钥等秘密不会泄露,因为您还在 Web 服务器中使用了 TLS。
为了完整起见,我应该提到这个漏洞应该会影响任何可能使用 OpenSSL 库来执行 TLS 的东西,这不仅限于网络服务器;例如,FTPS 服务器(但不是 SFTP)、电子邮件服务器、数据库服务器都可能容易受到攻击,具体取决于配置。
有关易受攻击的提交的更多信息
还值得注意的是,编写不验证有效负载大小的易受攻击代码的同一个人是 TLS 心跳扩展的同一作者(在RFC 6520中描述)。请注意,该协议没有指定 Heartbeats 响应的最大大小(同时指定了最小大小),但允许它是任意长度,并让有效负载大小由两个字节的标头描述(允许它上升到 65535 而不是仅255 带有 1 字节的标头,它只会暴露在网络服务器进程 RAM 的 255 字节以下)。老实说,我想不出任何合理的理由来要求心跳有效载荷超过 16 字节(128 位),如果你想变得超级偏执,你可以让它为 32 字节(256 位)。有了这些限制,就不太可能泄露很多有用的信息。
令人好奇的是,易受攻击的代码可以追溯到 2011 年新年前夜的晚上,这似乎是一个很可能会通过雷达或由于假期而减少审查的时间。
用非常简单的英语:攻击者说他们正在发送一个大小为“x”的数据包并要求服务器将其发回,但实际上发送的数据包要小得多。OpenSSL 库信任攻击者,将小的真实数据包作为回复的开始发回,然后从内存中抓取数据以将回复填写到预期的大小。这可能是服务器最近处理的任何数据,并且通常包含敏感信息。