再聊聊fastjson的一個漏洞

引言

我曾經寫過一篇文章

fastjson遠程代碼執行漏洞問題分析

文章曾經比較詳細分析了fastjson在1.2.24以及之前版本存在遠程代碼執行高危安全漏洞的問題。

本文則是針對另一個漏洞的介紹和分析。

官方對這次漏洞的說明是這樣的:

近日,阿里雲應急響應中心監測到fastjson爆出遠程拒絕服務漏洞,攻擊者在請求中構造特定json字符串,可遠程造成服務器內存和CPU等資源耗盡,最終拒絕服務。官方已發佈公告說明,最新的1.2.60和帶有sec06字符的版本不受影響,請使用到的用戶儘快升級至安全版本。

漏洞的詳細說明以及重現

fastjson處理\x轉義字符不當,攻擊者在請求中構造特定json字符串可導致服務器內存和CPU等資源耗盡,最終拒絕服務。阿里雲應急響應中心提醒fastjson用戶儘快採取安全措施阻止漏洞攻擊。

官方說的很明白了,我們根據這段說明來構造一個“死亡”字符串重現下。

public class App {
    static final String DEATH_STRING = "{\"a\":\"\\x";

    public static void main(String[] args) {
        try {
            JSON.parse(DEATH_STRING);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

運行這段代碼,你會發現這段不足10行的代碼居然可以導致OOM。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.alibaba.fastjson.parser.JSONLexerBase.putChar(JSONLexerBase.java:5041)
	at com.alibaba.fastjson.parser.JSONLexerBase.scanString(JSONLexerBase.java:889)
	at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:483)
	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1394)
	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1360)
	at com.alibaba.fastjson.JSON.parse(JSON.java:165)
	at com.alibaba.fastjson.JSON.parse(JSON.java:175)
	at com.alibaba.fastjson.JSON.parse(JSON.java:144)
	at com.app.App.main(App.java:21)

我們可以順着這個異常信息,擼一擼源碼,看看到底是哪裏的BUG。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

如上圖所示,當解析到字符x時,因爲是最後一個字符,所以x1和x2都是\u001A,也就是十進制的26。因爲每次char ch = this.next();獲取的都是26這個字符,然後就在第三張圖的位置死循環了。

有人可能會問,

if (this.isEOF())

這個語句爲啥沒有生效,不是已經到了結尾了嗎?那我們來看看isEOF的實現,

public boolean isEOF() {
        return this.bp == this.len || this.ch == 26 && this.bp + 1 == this.len;
    }

因爲前面兩次next操作,bp+1已經不等於len了,(你可以單步調試看看),所以isEOF方法永遠返回false

漏洞修復原理

官方已經給出瞭解決方案,那就是升級fastjson到1.2.60或以上版本。

我覺得作爲一個優秀的程序員,既然知其然,也要知其所以然。我們來看看阿里的優秀工程師是如何修復這個漏洞的。我們把fastjson升級到1.2.60,然後繼續debug源碼,發現代碼變成了這樣:

在這裏插入圖片描述

這種解決方案雖然簡單粗暴,但也是很有效的不是嗎,哈哈!

com.alibaba.fastjson.JSONException: invalid escape character \x
	at com.alibaba.fastjson.parser.JSONLexerBase.scanString(JSONLexerBase.java:983)
	at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:483)
	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1397)
	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1363)
	at com.alibaba.fastjson.JSON.parse(JSON.java:170)
	at com.alibaba.fastjson.JSON.parse(JSON.java:180)
	at com.alibaba.fastjson.JSON.parse(JSON.java:149)
	at com.app.App.main(App.java:25)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章