心脏出血漏洞攻击流程
心脏出血漏洞攻击流程
2014年4月7日,心脏安全研究员Neel Mehta在OpenSSL的出血代码里翻出一个要命的bug——攻击者可以随意读取服务器内存里的数据,每次最多64KB。漏洞流程这个漏洞被命名为Heartbleed,攻击中文翻译成“心脏出血”,心脏因为它出问题的出血地方正好是TLS协议里的心跳扩展(Heartbeat Extension)。
攻击流程其实不复杂。漏洞流程OpenSSL的攻击心跳扩展本意是让客户端发一个心跳请求,服务器收到后原样返回数据,心脏用来确认连接还活着。出血请求包里包含两个字段:一段数据和一个长度值。漏洞流程问题就出在这里——代码没有校验声明的攻击长度是否和实际数据长度一致。攻击者只要把长度值写得很大,心脏比如写成65535,出血实际数据只发1个字节,漏洞流程服务器就会按照声明长度去内存里找数据,把后面那65534个字节全吐出来。
我试着跑过一次复现实验。用的是Vulhub搭的靶机,一个跑着OpenSSL 1.0.1f的Nginx容器。攻击工具是Nmap的ssl-heartbleed脚本,命令就一行:nmap -p 443 --script ssl-heartbleed 靶机IP。脚本跑完,屏幕上直接甩出一串乱码,里面混着“HTTP/1.1”、一堆十六进制字符,甚至还有几个明文单词——那是之前某个用户访问时留下的URL片段。内存里什么都有,cookie、session token、私钥,全看运气。
更狠的是,这个漏洞不需要任何身份验证,不需要交互,攻击者可以反复触发。每次读64KB,多读几次就能把内存里翻个底朝天。有研究者实测过,只要触发几百次,就能把服务器上正在使用的私钥完整捞出来。拿到私钥意味着什么?意味着攻击者可以解密所有经过该服务器的TLS流量,还能伪造服务器证书,中间人攻击直接变成“合法操作”。
真实世界里,这个漏洞被利用的例子不少。加拿大税务局在漏洞公布后不久就确认有约900个社保号码被窃取,攻击者正是通过Heartbleed读取了内存中的敏感数据。英国 parenting 网站Mumsnet也遭了殃,用户的会话cookie被偷,账号被批量接管。这些案例有个共同点:攻击者根本没用什么高级手法,就是反复发心跳包,像拧开没关紧的水龙头,一滴一滴把内存里的机密全漏出来。
修复方式倒是简单——升级OpenSSL到1.0.1g或更高版本,代码里加了个长度校验。但麻烦在于,就算打了补丁,已经被泄露的私钥和会话数据仍然有效,必须全部吊销、重新生成。很多公司当时连夜换证书,忙得焦头烂额。有个运维朋友跟我吐槽,那周他唯一的工作就是批量重启服务、换证书、通知客户重新登录,整整三天没睡好觉。
这漏洞之所以叫“心脏出血”,还有个原因——它攻击的是TLS的心脏机制,却让整个互联网跟着流血。到今天快十年了,偶尔还有扫描器在网上扫出老版本OpenSSL的机器。你说,这算不算技术债里最要命的那种?
相关文章:
