Analysis of compromised websites - hacked PHP scripts

Filed Under: Malware, SophosLabs

Things have been pretty busy lately as far as web attacks ago. Over the past few weeks we have seen several large spikes of threat detections, corresponding to various waves of mass defacement attacks against legitimate web sites.

Pages on the hacked sites are typically injected with iframes (or scripts that add iframes), which explains the dominance of Mal/Iframe detections in our web threat data.

At the start of last week I happened to notice that a security-related site had been hacked in one of these attacks. Thankfully when I alerted the site owners of the problem, the site was taken offline quickly, and the matter resolved.

I do not believe the organisation was specifically targeted - it just appears to be one of many victims in this aggressive wave of mass-defacement attacks.

The incident raises some interesting questions. Most notably the malicious content being injected into the web pages was changing over time (sometimes a straight iframe, sometimes JavaScript).

This is not what you necessarily expect for hacked sites - ordinarily pages are injected with a fixed string (for example an iframe redirect or a script).

However, in these attacks, we were seeing various Sophos detections being triggered:

Clearly the injected content was dynamic, suggesting a slightly more sophisticated type of hack.

Hacked PHP files

Subsequently we managed to gather a few of the compromised files (PHP scripts) from servers in these attacks. In each case, the PHP scripts had been modified to include malicious code at the start of the file. Several flavours of code have been seen. In the simplest cases, the malicious payload is hidden within a base-64 encoded string:

Sometimes, an additional layer of compression is added as well:

And in several cases, I have seen obfuscation used to try and hide the malicious code (from security scanners and site admins!):

In this latter case, you can see that preg_replace has been used in order to obfuscate the use of eval, gzinflate and base64_decode.

The presence of any of the above strings within PHP scripts on web sites suspected of being hacked, should ring alarm bells for site administrators. Scripts to routinely check the size and last modified date of all PHP files within the site can be useful.

Payload of inserted PHP

And what of the actual payload of the prepended PHP? They are pretty easy to manually decode, and then the actual payload is normal quite straightforward to determine. Obviously the exact payloads vary between attacks but in the case of the sophisticated dynamic injection attacks described above, it is summarised below.

  1. retrieve IP for the user requesting the web page ($_SERVER).
  2. retrieve user-agent string from the page request header ($_SERVER).
  3. check user-agent string against an array of strings the PHP script contains for search-engine bots.
  4. if the request is deemed to be from a search-engine bot, bail. The original web page is delivered with no modifications.
  5. if the request is deemed to NOT be from a bot, check the IP against a local blacklist.
  6. if the IP has requested the page before, bail. The original web page is delivered with no modifications.
  7. otherwise, download a web page from a remote server (using cURL). This page contains the string to inject.
  8. echo the string to inject to the requested page.
  9. add the user IP to the local blacklist.

Note the check for bots - search-engines will never get to see the malicious code. This is done to stop search-engines blacklisting/removing compromised pages from their search results. Also note the use of a local IP blacklist. This is done to only hit each user once, which makes it harder to troubleshoot/investigate the problem!

The following diagram gives an overview of how the drive-by attacks proceed once the web servers are compromised:

From this analysis, what other clues might be present on hacked web servers? The cURL request to the remote server could be logged, or blocked with URL filtering. Use scripts to check the web folders for unexpected files such as those used for storing the local IP blacklist data.

, , , ,

You might like

5 Responses to Analysis of compromised websites - hacked PHP scripts

  1. Bahi · 1173 days ago

    I have a question?
    How do they inject into these PHP files in the first place?

  2. Keith Roberts · 1134 days ago

    What about using something like to detect the changes to the PHP files?

    Or even SELinux which is not that hard to learn:

    • Keith Roberts · 1134 days ago

      Another thing. PHP allows the admin to disable certain functions, so the eval function may be able to be disabled and even the cURL functionality?

      ; This directive allows you to disable certain functions for security reasons.
      ; It receives a comma-delimited list of function names. This directive is
      ; *NOT* affected by whether Safe Mode is turned On or Off.
      ; disable_functions = "dl,readfile,putenv,exec,passthru,shell_exec,system,proc_open,p
      disable_functions = ""

      ; This directive allows you to disable certain classes for security reasons.
      ; It receives a comma-delimited list of class names. This directive is
      ; *NOT* affected by whether Safe Mode is turned On or Off.
      disable_classes = ""

  3. AmiFen · 1046 days ago

    I actually have a question... How do you find someone if they set their profiles to invisible?

  4. greg aiken · 582 days ago

    my site was recently compromised. my web log shows a file 'ms.php' was called (status 200) successfully bu the hacker. it was called 7 times. not coincidentally, all seven of my 'index.html' files were modified to include an 'iframe' command. when i logged into my ftp client program to manage my site, the rogue script 'ms.php' was not found. my question, is just how could someone install a file 'ms.php' to my site? i regularly change my ftp password. im on a 'shared server' and assume perhaps a 'cross-site script' could have done this. ive checked, and the apache server thankfully does not support the 'PUT' command, so they couldnt have done it that way. im concerned that if this could happen once, it can repeatedly happen.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

About the author

Fraser is one of the Principal Virus Researchers in SophosLabs. He has been working for Sophos since 2006, and his main interest is in web related threats.