文章来源:https://mp.weixin.qq.com/s/bBRzV4wdB82_HmH_Dxofhw
作者:凉小尘
前段时间,FastJson被挖出来一个漏洞,可能导致服务直接瘫痪,这个问题就严重,搞的人心惶惶,半夜拼命升级,就怕飞来横锅。
我也是很好奇,一个序列化工具那么大能耐,可以直接把服务弄瘫痪?
本着好奇心,先看下最新版本是怎么修复的,上FastJson的github的官网,找到对应的commiter记录,很好找。
![03055a5212b71f46666832462a1440fb.png](https://i-blog.csdnimg.cn/blog_migrate/bc384c8dab8b0467600b15bd26344c71.jpeg)
就是它了,点进去可以看到具体的代码差异
![4d13a3416f1fa06adce121dd3a2433d0.png](https://i-blog.csdnimg.cn/blog_migrate/4418e92a286165ed87aa415ba46bd23c.jpeg)
原来这个处理方案很暴力,直接加一层过滤,如果字符串包含x,就甩一个异常到你脸上。
那就在本地写一个demo,看看能不能复现,本地用的是1.2.58
![a8e977d65c94d129fd644149ad0b56f4.png](https://i-blog.csdnimg.cn/blog_migrate/1d8d31611fd3eec17495fe67f9a0dd32.jpeg)
设置-Xmx4G,开始运行,过了一两秒,果然甩了我一个OOM
![76adbe4ebd6f0aa48aba93a356dbc6ff.png](https://i-blog.csdnimg.cn/blog_migrate/526a7e7398396936e9f7de7bf1445096.jpeg)
既然复现了,那就debug下哪里出了问题,根据修复代码,我们在JSONLexerbase类的ScanString方法的switch分支中的case 'x' 打个断点。
![53e2fca4c0a34b2642603e8b279ddbda.png](https://i-blog.csdnimg.cn/blog_migrate/37a26addea61431485f178240680e488.jpeg)
开始debug,进来之后,进入第一个next方法
![c0f01490d08c500392b5c67841fec1ee.png](https://i-blog.csdnimg.cn/blog_migrate/39250c2e1a6e5768d46ee1124b6ad752.jpeg)
next方法会对bp进行+1操作并赋给index,如果index>=this.len(JSON的长度)就会返回'',表示已经读完,否则返回文本内容。
在我们这个例子中,执行完第一个next,index的值已经等于JSON字符串的长度,所以返回了''
执行 charx2=this.next()的时候,index等于9,大于JSON字符串长度,也返回''
继续执行这个case分支的最后一行 this.putChar(x_char)
![7691408ddaa1e2d08e93b5de12cf6f32.png](https://i-blog.csdnimg.cn/blog_migrate/db50e81c119725ab5381ad898c543d2b.jpeg)
这个方法中,会对sp和sbuf.length(默认是512)进行比较,如果达到了,就进行扩容,可以猜到这里可能是OOM的元凶,不断的进行扩容,把内存耗尽。
继续往下执行,返回到了scanString方法,在while循环中,执行next方法,因为index值肯定大于JSON字符串长度,所以会返回''
![c26224cc18e3afb6cabde7f6a1b7254a.png](https://i-blog.csdnimg.cn/blog_migrate/2a22477e6ad7a30203d036a62da0d3cf.jpeg)
接下去会返回的字符ch,如果是'',会执行 putChar方法(该方法在上面截图中有显示),执行完sp的值+1,然后继续执行,又返回scanString方法,又开始了一轮。
最终sp会涨到512,这个时候,进入if分支,开始扩容。
噩梦就这么开始了...
还没升级到最新版 1.2.60 的小伙伴,抓紧哦。
我自己是一名从事了多年开发的Java老程序员,辞职目前在做自己的Java私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的Java学习干货,从最基础的JavaSE到Spring各种框架都有整理,送给每一位Java小伙伴,想要获取的可以关注我的头条号并在后台私信我:Java,即可免费获取。