1.介绍
Apache Commons Fileupload是阿帕奇基金会开源的一个java上传文件工具类。历史上爆出了两个dos漏洞,了解详情可以查阅http://commons.apache.org/proper/commons-fileupload/security-reports.html
CVE2014-0050
一个比较古老的 dos漏洞,通过查看commit提交纪录,可以看到一条古老的提交纪录
https://github.com/apache/commons-fileupload/commit/c61ff05b3241cb14d989b67209e57aa71540417a
- this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length];
this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length;
+ if (bufSize < this.boundaryLength + 1) {
+ throw new IllegalArgumentException(
+ "The buffer size specified for the MultipartStream is too small");
+ }
+ this.boundary = new byte[this.boundaryLength];
可以看出修复方案是 在new byte[this.boundaryLength] 之前检查了一下长度,如果 this.boundaryLength > bufSize - 1就抛出异常。从调用的地方可以看到
size的值是4096,加上BOUNDARY_PREFIX这个默认长度为4的数组之后要大于4095,那么boundaryLength本身的值只要大于4091即可。BOUNDARY_PREFIX的定义可以在类的开始位置找到
整个流程可以理解Apache Commons Fileupload默认会在用户上传的头部添加一些标识。
其实漏洞真正的触发原因是死循环,在代码处
原本开发者的意图是想通过抛出异常让程序跳出死循环,可是把buffer的长度设置为4096的话,input.read()的返回值永远不会为-1,这就导致了作者企图让程序跳出循环的条件被破坏了。
其中跟踪到findSeparator发现buffer其实是会添加boundary到其内容中的。
那么整个流程就可以理解了,如果boundary超过4091,会导致buffer超过4096,那么input.read()恒不为-1,这样一样就永远无法抛出异常,那么程序就会一直在死循环里面,这样导致了dos。
###测试攻击
boundary之类的可以根据rfc2046http://tools.ietf.org/html/rfc2046去查阅,我们只要伪造下就可以了。
用burp多开几个线程去跑,然后就回发现cpu占用的比较多。
CVE-2016-3092
分析commit了,发现了修改的地方如下 修复的地方还是和CVE2014-0050一样的位置,只是这次将bufSize扩容了。从修复层面上来看,buffer的长度的不足回导致整个程序源码算法的性能受到影响。
参考链接
https://threathunter.org/topic/594139ee03027c9d712abeff