引言
我曾经写过一篇文章
文章曾经比较详细分析了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)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。