发现漏洞:issue2689
9月2号有开发者在fastjson的仓库提了一个issue:Fastjson新版本解析到特定字符后直接触发异常。
具体问题是:字符串中包含x转义字符时可能引发OOM的问题 ,如:
//CodeString DEATH_STRING = "{"a":"x";Object obj = JSON.parse(DEATH_STRING);//OOMjava.lang.OutOfMemoryError: Java heap spaceat 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)...
具体问题从错误中可以找到:fastjson在JSONLexerBase.scanString
中遇到x
当做16进制处理,没有检查,而如果解析的字符串是以x
结尾,或者解析完x
字符串结束的时候,那么就会进入死循环,无限新增EOI
case 'x':char x1 = ch = next();char x2 = ch = next();int x_val = digits[x1] * 16 + digits[x2];char x_char = (char) x_val;putChar(x_char);break;
死循环代码片段如下,
ch = next();//next函数在字符最后会返回:EOI,EOI=0x1A...if (ch == EOI) {if (!isEOF()) {putChar((char) EOI);continue;}throw new JSONException("unclosed string : " + ch);}
解决漏洞
在遇到x
处理的时候做16进制检查:
官方建议
拒绝服务安全漏洞涉及之前所有FASTJSON版本,建议升级到最新版本1.2.60。如果遇到不兼容问题,可以使用如下兼容版本:1.1.15~1.1.31 -> 1.1.31.sec07 这版本不一样是因为1.1.31.sec06发布后,发现1.1.31版本特有一个的问题,又发布了1.1.31.sec07
1.1.32~1.1.33 -> 1.1.33.sec06
1.1.34 -> 1.1.34.sec06
1.1.35~1.1.46 -> 1.1.46.sec06
1.2.3~1.2.7 -> 1.2.7.sec06 因为1.2.7使用最多特别提供,也可以直接使用1.2.8.sec06
1.2.8 -> 1.2.8.sec06
1.2.9~1.2.29 -> 1.2.29.sec06
总结:
由于这次漏洞,我才知道fastjson在反序列化的时候会处理16进制,也正是fastjson会处理16进制的反序列化才会导致这样的问题,其他JSON工具如jackson
、gson
等都不会处理,这里我还尝试了一下:
//CodeString json = "{"name":"x61x62x63"}";Object obj = JSON.parse(json);System.out.println("obj = " + obj);//Resultobj = {"name":"abc"}
对于正常的JSON是不会引出漏洞的,只有在特殊情况,或者恶意攻击的时候才会,这也就是这个问题直到现在才发现,所以,如果用了fastjson处理JSON的还是尽快升级,避免引发问题。