关于 Apache Log4j 2 存在远程代码执行漏洞的安全公告
2021年11月24日,Apache官方收到了安全研究员报送的 Apache Log4j 2 存在远程代码执行漏洞的报告。
2021年12月13日,Apache官方又发布了Apache Log4j 2.16.0, 完全删除对消息查找的支持,默认情况下禁用 JNDI,如果需要开启,需要手动将 log4j2.enableJndi 设置为 true 以允许 JNDI。
- 漏洞描述
Apache Log4j 2 是一个基于Java的日志记录组件。该组件 是 Log4j 的升级版本,它重写了 Log4j 框架,并且引入了大量丰富的特性。开发人员可以控制日志信息输送的目的地为控制台、文件、GUI组件等,通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程。该日志框架被广泛应用于业务系统开发,用来记录程序输入输出日志信息。
由于 Log4j2 组件在处理程序日志记录时存在 JNDI 注入缺陷,未经授权的攻击者利用 Log4j2 提供的 lookup 功能通过一些协议去读取相应环境中的配置。但在实现的过程中,组件并未对输入进行严格的判断。攻击者可向目标服务器发送精心构造的恶意数据,触发 Log4j2 组件解析缺陷,实现目标服务器的任意代码执行,获得目标服务器权限。
Apache Log4j 2 组件在开启了日志记录功能后,凡是在可触发错误记录日志的地方,插入漏洞利用代码,即可利用成功。特殊情况下,若该组件记录的日志包含其他系统的记录日志,则有可能造成间接投毒。通过中间系统,使得组件间接读取了具有攻击性的漏洞利用代码,亦可间接造成漏洞触发。
同时该漏洞还影响很多全球使用量的Top序列的通用开源组件,例如 Apache Struts2、Apache Solr、Apache Druid、Apache Flink等。
- 影响范围
用户认证:不需要用户认证
触发方式:远程
配置方式:默认
利用条件:需要外网访问权限
影响版本: 2.0-beta9≤Apache Log4j 2≤2.15.0-rc1
不受影响版本:
Apache Log4j 2.16.0
Apache Log4j 2.15.0-rc2(与官网的Apache Log4j 2.15.0(稳定版)相同)
Apache Log4j 2.15.1-rc1
注:
① 使用Apache Log4j 2 1.X版本的应用,若开发者对JMS Appender利用不当,可对应用产生潜在的安全影响。
② Apache官方在Apache Log4j 2.15.0-rc1版本中已将log4j2.formatMsgNoLookups默认设置为true,在没有更改此默认配置的情况下,Log4j 2.15.0-rc1版本不受该漏洞影响。
利用难度:极低,无需授权即可远程代码执行
威胁等级:严重,能造成远程代码执行
综合评估漏洞利用难度极低,利用要求较少,影响范围很大,危害极其严重,且已经被黑客公开利用持续全网扫描,根据部里要求,需要紧急修复。
- 安全建议
- 排查应用是否引入了Apache Log4j 2 Jar包,若存在依赖引入,则可能存在漏洞影响。尽快升级 Apache Log4j 2 所有相关应用到最新的 Apache Log4j 2.16.0:
https://logging.apache.org/log4j/2.x/download.html
ps:若用户目前已经升级为Apache Log4j 2.15.0-rc1或Apache Log4j 2.15.0-rc2版本,默认配置下已不受该漏洞影响。
注:防止升级过程出现意外,建议相关用户在备份数据后再进行操作。
修复最彻底,但是需要关闭应用系统,重新打包提测。
- 配置网络防火墙,禁止 Apache Log4j 2 组件所在服务器主动外连网络,包含不限于DNS、TCP/IP、ICMP。并在边界对dnslog相关域名访问进行检测。部分公共dnslog平台如下:
ceye.io、dnslog.link、dnslog.cn、dnslog.io、tu4.org、
burpcollaborator.net、s0x.cn、dns.1433.eu.org。
- 紧急加固缓解措施:
① 修改JVM启动参数:
-Dlog4j2.formatMsgNoLookups=true。
② 在应用classpath下添加
log4j2.component.properties配置文件:
log4j2.formatMsgNoLookups=True。
③ 系统环境变量:
FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS设置为true。
注:当且仅当Apache Log4j 2 >= 2.10版本时,可使用①、②、③的任一措施进行防护。
需要关闭应用系统 log4j2.formatMsgNoLookups=True。
- 使用下列命令,移除log4j-core包中的JndiLookup 类文件
zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
- 采用人工方式禁用JNDI,例:在spring.properties里添加spring.jndi.ignore=true
- javaagent,需要给JDK注入一个jar,在jar中将存在漏洞的class代码直接修改。
参考
https://github.com/chaitin/log4j2-vaccine
https://github.com/qingtengyun/cve-2021-4428-qingteng-online-patch
https://github.com/qingtengyun/cve-2021-4428-qingteng-patch
不需要关闭应用系统,不会影响线上业务。
- 反射修改属性
不需要重启应用系统,只需要可以在对方的JVM中执行代码,就可以修复。无任何风险。当然前提一定是可以执行代码,方式包括jsp文件等。
把这段代码包装成jsp文件,直接上传到web站点运行就行。如果是SpringBoot的话,想办法执行代码也是可以的。
Object obj = LogManager.getLogger();
Field contextF = obj.getClass().getDeclaredField("context");
contextF.setAccessible(true);
Object context = contextF.get(obj);
Field configurationF = context.getClass().getDeclaredField("configuration");
configurationF.setAccessible(true);
Object configuration = configurationF.get(context);
Field substF = configuration.getClass().getSuperclass().getDeclaredField("subst");
substF.setAccessible(true);
Object subst = substF.get(configuration);
Field variableResolverF = subst.getClass().getDeclaredField("variableResolver");
variableResolverF.setAccessible(true);
Object variableResolver = variableResolverF.get(subst);
Field strLookupMapF = variableResolver.getClass().getDeclaredField("strLookupMap");
strLookupMapF.setAccessible(true);
HashMap strLookupMap = (HashMap) strLookupMapF.get(variableResolver);
strLookupMap.remove("jndi");
- JDK使用11.0.1、8u191、7u201、6u211及以上的高版本,可以在一定程度防止RCE。
- 升级已知受影响的应用及组件,如
spring-boot-starter-log4j2、Apache Struts2、Apache Solr、Apache Druid、Apache Flink。