CVE-2015-2080 分析
jetty是一个使用非常广泛的java容器,在开发javaweb的应用的时候,使用jetty作为嵌入式的容器,调试起来非常方便。很多大的互联网公司都使用它来替代tomcat,就我所知,阿里里面使用jetty也是比tomcat多的。
2015年2月25号的时候gdssecurity公布了jetty的一个缓冲区数据泄露的漏洞,以及漏洞的利用方式
http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html这个漏洞可能导致攻击者获取同时访问该jetty的其他用户http请求中的敏感数据。
乌云上面已经有一篇翻译文章了(http://drops.wooyun.org/papers/4972),我学习了一下,并总结原理如下:
1、jetty在处理http请求的时候,会把http请求的内容都保存在一个特定的buffer里面。每一次新的请求,都会覆盖这个buffer。jetty使用了nio,所以主要的保存在bytebuffer中
2、在收到http请求之后,jetty会逐个字符解析和判断http头,http内容的信息。其中如果判断到http头部中包含非ascii的字符,则会抛出一个IllegalCharacter的异常
3、该异常会在http返回里面打印一些用户友好的debug信息,这就需要jetty继续去解析buffer里面的值。在将buffer里面的内容转换成debug信息的时候,由于没有考虑周全,buffer里面包含了上一次正常的用户请求的内容。如果本次请求比上一次请求短,则会连带将上一次请求的内容打印出来。
我画了一个图,看完了应该非常容易理解这个漏洞。
蓝色部分就是我们构造的非法数据,在抛出异常的时候,本来只应该返回蓝色部分的数据。但是jetty继续往下读,会读到绿色部分的16个字节,然后后面以“...”省略,再读取最后的16个字节。
这样,只要构造特定长度的蓝色部分,就可以将黄色部分的数据全部读出返回。
修复:
官方已经发布了修复代码。https://github.com/eclipse/jetty.project/commit/4df5647f6dfdc5fa7abb812afe9290d60b17c098
我们可以看到,修复方式也是非常简单的。
for (int i = buffer.position(); i < buffer.limit(); i++) { appendContentChar(buf,buffer.get(i)); if (i == buffer.position() + 16 && buffer.limit() > buffer.position() + 32) { buf.append("..."); i = buffer.limit() - 16; } } buf.append(">>>\""); // ignore content beyond limit() return buf.toString();
这样就不回显后面的数据了,一切都恢复了平静。
上一篇: lucene入门-简单的WEB搜索界面