2017-03-21 14:34:15
来源:安全客 作者:360天眼实验室
阅读:770次
点赞(0)
收藏
传送门
【重大漏洞预警】Struts 2 远程代码执行漏洞(s2-045\s2-046) (含PoC)
0x00 漏洞介绍
S2-046漏洞和S2-045漏洞非常相似,都是由报错信息带入了buildErrorMessage这个方法造成的。 但是这次存在两个触发点。
Content-Length 的长度值超长
Content-Disposition的filename存在空字节
0x01 漏洞分析
Content-Length 的长度值超长
这个漏洞需要在strust.xml中加入 <constant name="struts.multipart.parser" value="jakarta-stream" />才能触发。
触发漏洞的代码在 JakartaStreamMultiPartRequest类中,processUpload函数处理了content-length长度超长的异常,导致问题触发。
privatevoidprocessUpload(HttpServletRequestrequest,StringsaveDir) throwsException{ //Sanitycheckthattherequestisamulti-part/form-datarequest. if(ServletFileUpload.isMultipartContent(request)){ //Sanitycheckonrequestsize. booleanrequestSizePermitted=isRequestSizePermitted(request); //InterfacewithCommonsFileUploadAPI //UsingtheStreamingAPI ServletFileUploadservletFileUpload=newServletFileUpload(); FileItemIteratori=servletFileUpload.getItemIterator(request); //Iteratethefileitems while(i.hasNext()){ try{ FileItemStreamitemStream=i.next(); //Ifthefileitemstreamisaformfield,delegatetothe //fielditemstreamhandler if(itemStream.isFormField()){ processFileItemStreamAsFormField(itemStream); } //Delegatethefileitemstreamforafilefieldtothe //fileitemstreamhandler,butdelegationisskipped //iftherequestSizePermittedcheckfailedbasedonthe //completecontent-sizeoftherequest. else{ //preventprocessingfilefielditemifrequestsizenotallowed. //alsowarnuserinthelogs. if(!requestSizePermitted){ addFileSkippedError(itemStream.getName(),request); LOG.warn("Skippedstream'#0',requestmaximumsize(#1)exceeded.",itemStream.getName(),maxSize); continue; } processFileItemStreamAsFileField(itemStream,saveDir); } }catch(IOExceptione){ e.printStackTrace(); } } } } 触发点在LOG.warn("Skippedstream'#0',requestmaximumsize(#1)exceeded.",itemStream.getName(),maxSize);
之后进入了函数addFileSkippedError,我们又见到了熟悉的buildErrorMessage,而这次带入的参数为fileName
privatevoidaddFileSkippedError(StringfileName,HttpServletRequestrequest){ StringexceptionMessage="Skippedfile"+fileName+";requestsizelimitexceeded."; FileSizeLimitExceededExceptionexception=newFileUploadBase.FileSizeLimitExceededException(exceptionMessage,getRequestSize(request),maxSize); Stringmessage=buildErrorMessage(exception,newObject[]{fileName,getRequestSize(request),maxSize}); if(!errors.contains(message)) errors.add(message); }Content-Disposition的filename存在空字节
第二种触发漏洞的方式,属于直接触发,在streams.class中,会对filename进行检查,如果检查出错,也会记录log。
publicstaticStringcheckFileName(StringfileName){ if(fileName!=null&&fileName.indexOf('\u0000')!=-1){ //pFileName.replace("\u0000","\\0") finalStringBuildersb=newStringBuilder(); for(inti=0;i<fileName.length();i++){ charc=fileName.charAt(i); switch(c){ case0: sb.append("\\0"); break; default: sb.append(c); break; } } thrownewInvalidFileNameException(fileName, "Invalidfilename:"+sb); } returnfileName; }最终进入的是JakartaStreamMultiPartRequest类的,我们又见到了buildErrorMessage
publicvoidparse(HttpServletRequestrequest,StringsaveDir) throwsIOException{ try{ setLocale(request); processUpload(request,saveDir); }catch(Exceptione){ e.printStackTrace(); StringerrorMessage=buildErrorMessage(e,newObject[]{}); if(!errors.contains(errorMessage)) errors.add(errorMessage); } }0x02 规则添加注意点
由于存在两种方式,因此规则不是很好添加。且存在一定情况的bypass可能。
由于strust2会对data字段逐字解析,filename后可以跟如下几种情况。
多个空格
多个空格,且里面可以添加\r\n
n个空格
\0b不可当成检测字符,\0b可以被替换成\0000,\0a - \0z 等等。
0x03 漏洞修复
升级版本到 2.3.32 、 2.5.10.1
传送门
【重大漏洞预警】Struts 2 远程代码执行漏洞(s2-045\s2-046) (含PoC)
本文由 安全客 原创发布,如需转载请注明来源及本文地址。
本文地址:http://bobao.360.cn/learning/detail/3639.html