Overview
On September 5, 2017, Apache Struts released the latest security bulletin announcing that the REST plug-in in Apache Struts 2.5.x and some 2.x versions is prone to a high-risk remote code execution vulnerability, which has been assigned CVE-2017-9805 (S2-052). When using an XStream handler with an instance of XStream for deserialization, the REST plug-in does not perform any type filtering, thereby causing remote code execution.
Related information is available at the following links:
https://struts.apache.org/docs/s2-052.html
https://cwiki.apache.org/confluence/display/WW/S2-052
Affected Versions
- Struts 2.1.2 – Struts 2.3.33
- Struts 2.5 – Struts 2.5.12
Unaffected Versions
- Struts 2.3.34
- Struts 2.5.13
Vulnerability Analysis
According to the official description, when the REST plug-in uses an XStream handler to handle XML data, it does not perform any filtering before converting the XML data to objects in the deserialization process, leading to remote code execution.
Environment Setup
Users can download all source code packages from the official website (https://archive.apache.org/dist/struts/2.5/struts-2.5-all.zip) and then directly deploy struts2-rest-showcase.war onto Tomcat. I prefer manual compilation using Maven. During deployment, note that, due to the javax.imageio dependency, the version of JDK must be JDK8 or later. Some earlier versions of JDK8 do not support the deployment. Here, jdk8_102 is used as an example for vulnerability verification.
Patch Analysis
Let’s have a look at the related configurations of the REST plug-in.
As shown in the preceding figure, the XStream handler uses the default method, Content-Type:xml, to process file handles. Therefore, the REST plug-in is prone to XStream deserialization vulnerability.
The official patch for fixing this vulnerability is available at the following link:
https://github.com/apache/struts/commit/19494718865f2fb7da5ea363de3822f87fbda264
In the official solution, data (collection data, map data, basic class data, and time class data) in the XML document is whitelisted, in a bid to prevent bringing in harmful operations during XStream deserialization.
Generation of PoC
Currently, the public Proof of Concept (PoC) is based on javax.imageio, which can execute commands locally. However, marshelsec provides 11 XStream deserialization libraries, most of which are based on JNDI, including CommonsConfiguration, Rome, CommonsBeanutils, ServiceLoader, ImageIO, BindingEnumeration, LazySearchEnumeration, SpringAbstractBeanFactoryPointcutAdvisor, SpringPartiallyComparableAdvisorHolder, Resin, and XBean. External request class data is used for deserialization.
Vulnerability Verification and Analysis
The following figure shows simple verification and analysis. As shown in the PoC, the request method is PUT; the URL contains the “xml” extension; Content-Type of the request is delicious/bookmark+xml; the prefix of the requested XML is <set>.
The following figure shows the execution call stack that triggers the vulnerability.
XStreamHanler.toObject calls fromXml of XStream for deserialization.
Official Workaround Not Working
Apache provides a workaround like this: <constant name=”struts.action.extension” value=”xhtml,,,json” />. Apparently, the vendor tries to work around the vulnerability by removing “xml” from the “action.extension” values. This workaround is supposed to work as follows:
Change the statement in the red box in the following figure into:
<constant name=”struts.action.extension” value=”xhtml,,json” />
To do that, perform the following steps:
Use a compression tool to open the JAR package. Here struts2-rest-plugin-2.5.10.1.jar is used as an example.
Extract struts-plugin.xml, modify the settings as required, and then put it back into the compressed package.
Restart the server.
After XML resolution is stopped, a request for accessing a URL containing xml will return an HTTP 404 error, indicating that XML data cannot be resolved.
Following is the test case. In our PoC, the POST request does not contain the “xml” extension. XStream relates only to Content-Type. If Content-Type values include xml, this type of data will be handed over to XStream for handling. Therefore, the PoC works regardless of whether xml is included as a content type.
As shown in the preceding figure, XML support is removed. Let’s see how the payload is executed:
The calculator successfully pops up as expected. In addition, by comparing two different PoCs, we find that Content-Type supports a number of XML formats. A POST, PUT, GET, or even a custom request can trigger the vulnerability. Even if we change <map><entry> to <set>, the vulnerability can still be triggered. Worse still, there are as many as 11 PoCs related to XStream. It is understandably difficult to protect against this vulnerability.
Technical Solutions
Official Solution
Apache has released updates to fix this vulnerability. Users of the affected applications are advised to upgrade as soon as possible.
Links:
- Struts 2.3.34:
https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.3.34
- Struts 2.5.13:
https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.13
NSFOCUS’s Recommendations
Use NSFOCUS’s detection product or service to detect the vulnerability:
- For Internet-facing assets, use the emergency vulnerability detection service of NSFOCUS Cloud to check for the vulnerability online. The service is available at the following link:
https://cloud.nsfocus.com/#/krosa/views/initcdr/productandservice?page_id=12
- For internal assets, use NSFOCUS RSAS V6, WVSS, or IDS to check for the vulnerability:
Remote Security Assessment System (RSAS V6):
http://update.nsfocus.com/update/listRsasDetail/v/vulweb
Web Vulnerability Scanning System (WVSS):
http://update.nsfocus.com/update/listWvss
Network Intrusion Detection System (NIDS):
http://update.nsfocus.com/update/listIds
You should upgrade your devices to the latest version by downloading upgrade packages from the preceding links before using them to detect vulnerabilities.
Use NSFOCUS’s protection product (NIPS, NIDS, NF, or WAF) to protect against the exploitation of the vulnerability:
Network Intrusion Prevention System (NIPS):
http://update.nsfocus.com/update/listIps
Next-Generation Firewall (NF):
http://update.nsfocus.com/update/listNf
Web Application Firewall (WAF):
http://update.nsfocus.com/update/wafIndex
You should upgrade your devices to the latest version by downloading upgrade packages from the preceding links before using them for protection.
Workaround
Add an XML filter to filter out requests whose Content-Type is “application/xml”. This, however, will indiscriminately cause all such requests to fail. Therefore, it can be used only as a temporary solution.
Code for the filter is as follows:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException { if (request.getContentType() != null) { String contentType = request.getContentType().toLowerCase(Locale.ENGLISH); if (contentType != null && contentType.contains(“application/xml”)) { response.getWriter().write(“Reject!”); } else { chain.doFilter(request, response); } } else { chain.doFilter(request, response); } } |
After creating this filter, conduct a PoC test. The test result proves that matched requests can be blocked.
Note that the default restriction policy adopted by the latest versions will cause some functions of REST to stop working, exerting a negative impact on some services. It is recommended that the following new APIs be used:
- org.apache.struts2.rest.handler.AllowedClasses
- org.apache.struts2.rest.handler.AllowedClassNames
- org.apache.struts2.rest.handler.XStreamPermissionProvider