我曾经写过一篇文章java
文章曾经比较详细分析了fastjson
在1.2.24以及以前版本存在远程代码执行高危安全漏洞的问题。json
本文则是针对另外一个漏洞的介绍和分析。安全
官方对此次漏洞的说明是这样的:服务器
近日,阿里云应急响应中心监测到fastjson爆出远程拒绝服务漏洞,攻击者在请求中构造特定json字符串,可远程形成服务器内存和CPU等资源耗尽,最终拒绝服务。官方已发布公告说明,最新的1.2.60和带有sec06字符的版本不受影响,请使用到的用户尽快升级至安全版本。
fastjson处理x转义字符不当,攻击者在请求中构造特定json字符串可致使服务器内存和CPU等资源耗尽,最终拒绝服务。阿里云应急响应中心提醒fastjson用户尽快采起安全措施阻止漏洞攻击。app
官方说的很明白了,咱们根据这段说明来构造一个“死亡”字符串重现下。this
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。spa
如上图所示,当解析到字符x
时,由于是最后一个字符,因此x1和x2都是\u001A
,也就是十进制的26。由于每次char ch = this.next();
获取的都是26这个字符,而后就在第三张图的位置死循环了。.net
有人可能会问,
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)