游客发表
2021年12月9日,严重漏洞Apache Log4j 2 的严重漏洞一个远程代码执行漏洞被公开。CVSS 评分:10.0。严重漏洞满分。严重漏洞这意味着不需要任何认证,严重漏洞不需要用户交互,严重漏洞攻击者只要构造一段特定字符串,严重漏洞就能在目标服务器上执行任意代码。严重漏洞
当时我在一家中型互联网公司做后端。严重漏洞凌晨两点,严重漏洞安全群炸了。严重漏洞运维说线上有几台机器出现了异常外连,严重漏洞目标 IP 在境外。严重漏洞排查到四点,严重漏洞确认是严重漏洞 Log4j 被打穿了。攻击者留了一个挖矿脚本,CPU 跑满,但还没做更过分的事。
天亮之后,整个技术部进入战时状态。CTO 在群里发了一句话:所有 Java 服务,不管版本,全部排查。
为什么一个日志库能捅出这么大的篓子?Log4j 几乎是 Java 生态里最基础的组件,你写不写日志它都在那里,被无数框架间接引入。很多人根本不知道自己的项目依赖了它。这就是供应链攻击的可怕之处——你信任的不是 Log4j 本身,而是信任了依赖它的那一百个库。
漏洞原理其实不复杂。Log4j 支持一种叫 JNDI 的查找功能,当日志内容里包含 ${ jndi:ldap://...} 这样的字符串时,它会主动去请求那个地址,加载远程的 class 文件并执行。设计这个功能的人大概没想到,日志内容是可以被用户控制的。你输入一个用户名,用户名里带了这段 payload,服务器就中招了。
修复方案倒不复杂。升级到 2.17.0 以上,或者删掉 JndiLookup 这个 class 文件,或者设置 log4j2.formatMsgNoLookups=true。但问题在于——你得先知道哪些系统用了 Log4j。
我们花了三天,把公司所有 Java 应用的依赖树全部拉了一遍。结果不乐观。有些老项目用的是 Log4j 1.x,以为不受影响,但里面间接依赖了 2.x 的包。有些服务是外包团队写的,文档早就丢了,只能反编译 jar 包去看。还有几个边缘系统,负责人已经离职了,没人敢动。
那几天安全圈有个段子:这个漏洞的修复难度不在于技术,在于你得先找到你的代码在哪。
更让人头疼的是,攻击流量很快就铺开了。安全设备厂商的规则库更新速度跟不上变种速度。一开始是 ${ jndi:ldap://,后来变成 ${ ${ lower:j}ndi:...,再后来用各种编码绕过。WAF 拦了一批,但总有人能绕过去。
我印象最深的是一个内部工具。它只在办公网用,不对外。按理说风险很低。但有一天运维发现它往外发 DNS 请求,查下来是某个同事在测试时把 payload 贴进了搜索框。办公网也不是绝对安全的。
这件事之后,我们做了一次彻底的依赖治理。引入 SBOM(软件物料清单),所有项目的第三方依赖必须登记。新项目上线前要过安全扫描。老项目逐步替换或下线。过程很痛苦,但比再来一次 Log4j 要好。
说句实在话,Log4j 不是第一个,也不会是最后一个。开源组件的维护者往往只有几个人,甚至一个人。他们凭热情在维护,没有安全团队,没有渗透测试。你用的时候默认它是安全的,但默认本身就是一种风险。
后来我养成了一个习惯:每次引入新的依赖,先去查一下它的 CVE 记录和最近一次更新时间。如果一个库两年没更新了,我会犹豫一下。这不是不信任开源,是知道开源背后的真实状况。
那个凌晨的挖矿脚本后来被清理了,没造成数据泄露。但每次想起来,还是觉得悬。如果攻击者不是来挖矿的呢?
友情链接