first feedback implemented

bug/bundler_fix
Christian Mehlmauer 2013-08-23 21:59:36 +02:00
parent 556f17c47e
commit de3fc1fa6c
7 changed files with 91 additions and 60 deletions

View File

@ -11,22 +11,17 @@ module Msf::HTTP::Wordpress::Base
'method' => 'GET',
'uri' => normalize_uri(target_uri)
}, 20)
if res and res.code == 200
if res.body =~ /["'][^"']*\/wp-content\/[^"']*["']/i or
return true if res and
res.code == 200 and
(
res.body =~ /["'][^"']*\/wp-content\/[^"']*["']/i or
res.body =~ /<link rel=["']wlwmanifest["'].*href=["'].*\/wp-includes\/wlwmanifest\.xml["'] \/>/i or
res.body =~ /<link rel=["']pingback["'].*href=["'].*\/xmlrpc\.php["'] \/>/i
return true
else
return false
end
end
)
return false
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
rescue ::Timeout::Error, ::Errno::EPIPE
print_error("Error connecting to #{target_uri}")
return false
end
return false
end
end

View File

@ -3,9 +3,9 @@ module Msf::HTTP::Wordpress::Helpers
# Returns the POST data for a Wordpress login request
#
# @param user Usernam
# @param pass Password
# @param redirect URL to redirect after successful login
# @param user [String] Username
# @param pass [String] Password
# @param redirect URL [String] to redirect after successful login
# @return [String] The post data
def wordpress_helper_login_post_data(user, pass, redirect=nil)
post_data = "log=#{Rex::Text.uri_encode(user.to_s)}"
@ -17,13 +17,13 @@ module Msf::HTTP::Wordpress::Helpers
# Helper method to post a comment to Wordpress
#
# @param comment The comment
# @param comment_post_id The Post ID to post the comment to
# @param login_cookie The valid login_cookie
# @param author The author name
# @param email The author email
# @param url The author url
# @return [String] The location of the new comment/post
# @param comment [String] The comment
# @param comment_post_id [Integer] The Post ID to post the comment to
# @param login_cookie [String] The valid login_cookie
# @param author [String] The author name
# @param email [String] The author email
# @param url [String] The author url
# @return [String] The location of the new comment/post, nil on error
def wordpress_helper_post_comment(comment, comment_post_id, login_cookie, author, email, url)
vars_post = {
'comment' => comment,
@ -44,21 +44,24 @@ module Msf::HTTP::Wordpress::Helpers
options.merge!({'vars_post' => vars_post})
options.merge!({'cookie' => login_cookie}) if login_cookie
res = send_request_cgi(options)
if res and res.code == 302
location = URI(res.headers['Location'])
return location
if res and (res.code == 301 or res.code == 302) and res.headers['Location']
return wordpress_helper_parse_location_header(res)
else
message = 'Post comment failed.'
message << " Status Code: #{res.code}" if res
print_error(message)
return nil
end
end
# Helper method for bruteforcing a valid post id
#
# @param comments_enabled If true try to find a post id with comments enabled, otherwise return the first found
# @param login_cookie A valid login cookie to perform the bruteforce as an authenticated user
# @param range [Range] The Range of post_ids to bruteforce
# @param comments_enabled [Boolean] If true try to find a post id with comments enabled, otherwise return the first found
# @param login_cookie [String] A valid login cookie to perform the bruteforce as an authenticated user
# @return [Integer] The post id, nil when nothing found
def wordpress_helper_get_valid_post_id(comments_enabled=false, login_cookie=nil)
(1..1000).each { |id|
def wordpress_helper_get_valid_post_id(range, comments_enabled=false, login_cookie=nil)
range.each { |id|
vprint_status("#{rhost}:#{rport} - Checking POST ID #{id}...") if (id % 100) == 0
body = wordpress_helper_check_post_id(wordpress_url_post(id), comments_enabled, login_cookie)
return id if body
@ -69,9 +72,9 @@ module Msf::HTTP::Wordpress::Helpers
# Helper method to check if a post is valid an has comments enabled
#
# @param uri the Post URI
# @param comments_enabled Check if comments are enabled on this post
# @param login_cookie A valid login cookie to perform the check as an authenticated user
# @param uri [String] the Post URI Path
# @param comments_enabled [Boolean] Check if comments are enabled on this post
# @param login_cookie [String] A valid login cookie to perform the check as an authenticated user
# @return [String] the HTTP response body of the post, nil otherwise
def wordpress_helper_check_post_id(uri, comments_enabled=false, login_cookie=nil)
options = {
@ -94,11 +97,28 @@ module Msf::HTTP::Wordpress::Helpers
return res.body
end
elsif res and (res.code == 301 or res.code == 302) and res.headers['Location']
location = URI(res.headers['Location'])
uri = location.path
uri << "?#{location.query}" unless location.query.nil? or location.query.empty?
return wordpress_helper_check_post_id(uri, comments_enabled, login_cookie)
path = wordpress_helper_parse_location_header(res)
return wordpress_helper_check_post_id(path, comments_enabled, login_cookie)
end
return nil
end
# Helper method parse a Location header and returns only the path and query. Returns nil on error
#
# @param res [Rex::Proto::Http::Response] The HTTP response
# @return [String] the path and query, nil on error
def wordpress_helper_parse_location_header(res)
return nil unless res and (res.code == 301 or res.code == 302) and res.headers['Location']
location = res.headers['Location']
begin
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("Invalid Location Header returned (not an URI): #{location}")
return nil
end
end
end

View File

@ -3,8 +3,8 @@ module Msf::HTTP::Wordpress::Login
# performs a wordpress login
#
# @param user Username
# @param pass Password
# @param user [String] Username
# @param pass [String] Password
# @return [String] the session cookie on successful login, nil otherwise
def wordpress_login(user, pass)
redirect = "#{target_uri}#{Rex::Text.rand_text_alpha(8)}"
@ -12,7 +12,7 @@ module Msf::HTTP::Wordpress::Login
'method' => 'POST',
'uri' => wordpress_uri_login,
'data' => wordpress_helper_login_post_data(user, pass, redirect),
}, 20)
})
if res and res.code == 302 and res.headers['Location'] == redirect
match = res.get_cookies.match(/(wordpress(?:_sec)?_logged_in_[^=]+=[^;]+);/i)

View File

@ -3,9 +3,9 @@ module Msf::HTTP::Wordpress::Posts
# Posts a comment as an authenticated user
#
# @param comment The comment
# @param comment_post_id The Post ID to post the comment to
# @param login_cookie The valid login_cookie
# @param comment [String] The comment
# @param comment_post_id [Integer] The Post ID to post the comment to
# @param login_cookie [String] The valid login_cookie
# @return [String] The location of the new comment/post
def wordpress_post_comment_auth(comment, comment_post_id, login_cookie)
wordpress_helper_post_comment(comment, comment_post_id, login_cookie, nil, nil, nil)
@ -13,11 +13,11 @@ module Msf::HTTP::Wordpress::Posts
# Posts a comment as an unauthenticated user
#
# @param comment The comment
# @param comment_post_id The Post ID to post the comment to
# @param author The author name
# @param email The author email
# @param url The author url
# @param comment [String] The comment
# @param comment_post_id [Integer] The Post ID to post the comment to
# @param author [String] The author name
# @param email [String] The author email
# @param url [String] The author url
# @return [String] The location of the new comment/post
def wordpress_post_comment_no_auth(comment, comment_post_id, author, email, url)
wordpress_helper_post_comment(comment, comment_post_id, nil, author, email, url)
@ -25,24 +25,32 @@ module Msf::HTTP::Wordpress::Posts
# Tries to bruteforce a valid post_id
#
# @param login_cookie If set perform the bruteforce as an authenticated user
# @param min_post_id [Integer] The first post_id to bruteforce
# @param max_post_id [Integer] The last post_id to bruteforce
# @param login_cookie [String] If set perform the bruteforce as an authenticated user
# @return [Integer] The post id, nil when nothing found
def wordpress_get_valid_post_id(login_cookie=nil)
wordpress_helper_get_valid_post_id(false, login_cookie)
def wordpress_get_valid_post_id(min_post_id, max_post_id, login_cookie=nil)
return nil if min_post_id > max_post_id
range = Range.new(min_post_id, max_post_id)
wordpress_helper_get_valid_post_id(range, false, login_cookie)
end
# Tries to bruteforce a valid post_id with comments enabled
#
# @param login_cookie If set perform the bruteforce as an authenticated user
# @param min_post_id [Integer] The first post_id to bruteforce
# @param max_post_id [Integer] The last post_id to bruteforce
# @param login_cookie [String] If set perform the bruteforce as an authenticated user
# @return [Integer] The post id, nil when nothing found
def wordpress_get_valid_post_id_with_comments_enabled(login_cookie=nil)
wordpress_helper_get_valid_post_id(true, login_cookie)
def wordpress_get_valid_post_id_with_comments_enabled(min_post_id, max_post_id, login_cookie=nil)
return nil if min_post_id > max_post_id
range = Range.new(min_post_id, max_post_id)
wordpress_helper_get_valid_post_id(range, true, login_cookie)
end
# Checks if the provided post has comments enabled
#
# @param post_id The post ID to check
# @param login_cookie If set perform the check as an authenticated user
# @param post_id [Integer] The post ID to check
# @param login_cookie [String] If set perform the check as an authenticated user
# @return [String] the HTTP response body of the post, nil otherwise
def wordpress_post_comments_enabled?(post_id, login_cookie=nil)
wordpress_helper_check_post_id(wordpress_url_post(post_id), true, login_cookie)

View File

@ -10,7 +10,7 @@ module Msf::HTTP::Wordpress::URIs
# Returns the Wordpress Post URL
#
# @param post_id Post ID
# @param post_id [Integer] Post ID
# @return [String] Wordpress Post URL
def wordpress_url_post(post_id)
normalize_uri(target_uri.path) + "/?p=#{post_id}"
@ -18,7 +18,7 @@ module Msf::HTTP::Wordpress::URIs
# Returns the Wordpress Author URL
#
# @param author_id Author ID
# @param author_id [Integer] Author ID
# @return [String] Wordpress Author URL
def wordpress_url_author(author_id)
normalize_uri(target_uri.path) + "/?author=#{author_id}"

View File

@ -3,14 +3,14 @@ module Msf::HTTP::Wordpress::Users
# Checks if the given user exists
#
# @param user Username
# @param user [String] Username
# @return [Boolean] true if the user exists
def wordpress_user_exists?(user)
res = send_request_cgi({
'method' => 'POST',
'uri' => wordpress_uri_login,
'data' => wordpress_helper_login_post_data(user, 'x'),
}, 20)
})
exists = false
if res and res.code == 200
@ -26,7 +26,7 @@ module Msf::HTTP::Wordpress::Users
# Checks if the given userid exists
#
# @param user_id user_id
# @param user_id [Integer] user_id
# @return [String] the Username if it exists, nil otherwise
def wordpress_userid_exists?(user_id)
url = wordpress_url_author(user_id)

View File

@ -60,6 +60,12 @@ class Metasploit3 < Msf::Exploit::Remote
OptString.new('USERNAME', [ false, "The user to authenticate as (anonymous if username not provided)"]),
OptString.new('PASSWORD', [ false, "The password to authenticate with (anonymous if password not provided)" ])
], self.class)
register_advanced_options(
[
OptInt.new('MIN_POST_ID', [ false, 'Specify the first post_id used for bruteforce', 1]),
OptInt.new('MAX_POST_ID', [ false, 'Specify the last post_id used for bruteforce', 1000])
])
end
def peer
@ -115,7 +121,9 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("#{peer} - Using the user supplied POST ID #{@post_id}...")
else
print_status("#{peer} - Trying to brute force a valid POST ID...")
@post_id = wordpress_get_valid_post_id_with_comments_enabled
min_post_id = datastore['MIN_POST_ID']
max_post_id = datastore['MAX_POST_ID']
@post_id = wordpress_get_valid_post_id_with_comments_enabled(min_post_id, max_post_id, @cookie)
if @post_id.nil?
fail_with(Failure::BadConfig, "#{peer} - Unable to post without a valid POST ID where comment")
else