I have recently been the unfortunate recipient of some website hacking leading to a minor bit of spam injection into my mail server. Nothing too serious and due mainly to an old version of Centos and some WordPress code that could have been constructed a little bit better, but anyway. So what do you look for when checking your webserver and how do you keep it a little bit more secure?
In my case, I had a few random .php pages inserted and my investigation spurned me on to take the basic steps I should have done in the first place. Some of these were already correct but no harm in covering them:
- Set your apache instance to NOT run as root and set your file permissions to read-only to all places that need access by the server. Things to look for:
- in /etc/https/conf/httpd.conf, make sure the user and group lines are a user like “www-data” or “apache”
- Keep an eye on /var/log/<websitename>-access_log for odd stuff going on
- I have a php page on my webserver that looks for post messages for example. Any that I don’t like, I block the client site. To block people from your website, include this in your vhost:
- Order deny,allow
- deny from 1.2.3.4/24
- allow from all
- If you run phpMyAdmin, ensure you ONLY allow hosts you recognise
- Install mod_security (read: https://www.cyberciti.biz/faq/rhel-fedora-centos-httpd-mod_security-configuration/)
- Edit your .htaccess file to prevent http1.0 POSTing:
-
# require HTTP 1.1 for POST <IfModule mod_rewrite.c> RewriteCond %{THE_REQUEST} ^POST(.*)HTTP/(0\.9|1\.0)$ [NC] RewriteRule .* - [F,L] </IfModule>
-
- Setup a PHP file on your website to allow you to quickly review what is going on from anywhere. Mine does this for example:
<?php $badtext = array("<",">"); $goodtext = array ("{","}"); $output = shell_exec('ls -la webcam.jpg'); echo "<pre>$output</pre>"; $output = shell_exec('date'); echo "Page Refreshed:<pre>$output</pre>"; echo "Who has been trying to hack simkin.org...<br>"; $simkinhackers = shell_exec('tail -n60 /var/log/simkin.org-access_log | grep "POST" '); foreach(preg_split("/((\r?\n)|(\r\n?))/", $simkinhackers) as $line){ //output the first bit of each line with the ip address $pos = strpos($line, "-")-1; //now the rest of the line $ip = substr($line, 0,$pos); if (strlen($ip)>1) { echo "<br /><a href='chkIP.php?item=".$ip."'>".$ip."</a>"; echo "<a href='https://www.abuseipdb.com/check/".$ip."'>.</a>"; echo substr($line,$pos,strlen($line)-$pos); } } $simkinhackers2 = shell_exec('tail -n60 /var/log/simkin.org-access_log | grep "USER"'); foreach(preg_split("/((\r?\n)|(\r\n?))/", $simkinhackers2) as $line){ //output the first bit of each line with the ip address $pos = strpos($line, "-")-1; //now the rest of the line $ip = substr($line, 0,$pos); if (strlen($ip)>1) { echo "<br /><a href='chkIP.php?item=".$ip."'>".$ip."</a>"; echo "<a href='https://www.abuseipdb.com/check/".$ip."'>.</a>"; echo substr($line,$pos,strlen($line)-$pos); } } $simkinhacker3 = shell_exec('tail -n60 /var/log/simkin.org-access_log | grep "action=upload"'); foreach(preg_split("/((\r?\n)|(\r\n?))/", $simkinhackers3) as $line){ //output the first bit of each line with the ip address $pos = strpos($line, "-")-1; //now the rest of the line $ip = substr($line, 0,$pos); if (strlen($ip)>1) { echo "<br /><a href='chkIP.php?item=".$ip."'>".$ip."</a>"; echo "<a href='https://www.abuseipdb.com/check/".$ip."'>.</a>"; echo substr($line,$pos,strlen($line)-$pos); } } $simkinhackers4 = shell_exec('tail -n200 /var/log/simkin.org-access_log | grep "lostpassword"'); foreach(preg_split("/((\r?\n)|(\r\n?))/", $simkinhackers4) as $line){ //output the first bit of each line with the ip address $pos = strpos($line, "-")-1; //now the rest of the line $ip = substr($line, 0,$pos); if (strlen($ip)>1) { echo "<br /><a href='chkIP.php?item=".$ip."'>".$ip."</a>"; echo "<a href='https://www.abuseipdb.com/check/".$ip."'>.</a>"; echo substr($line,$pos,strlen($line)-$pos); } } # Grab the IP addresses to a logfile $ip1 = shell_exec('tail -n60 /var/log/simkin.org-access_log | grep "POST" | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}"'); $ip2 = shell_exec('tail -n60 /var/log/simkin.org-access_log | grep "USER" | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}"'); $ip3 = shell_exec('tail -n200 /var/log/simkin.org-access_log | grep "lostpassword" | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}"'); $textstring = $ip1.$ip2.$ip3; file_put_contents('~/badpeople.log',$textstring , LOCK_EX); $nul = shell_exec("cat ~/badpeople.log | awk '!seen[$0]++' > ~/badpeople.txt"); $handle = fopen("~/badpeople.txt", "r"); if ($handle) { while (($line = fgets($handle)) !== false) { // process the line read. echo "<br /><a href='https://www.whois.com/whois/".$line."' target='new'>".$line."</a>"; } fclose($handle); } else { // error opening the file. } ?>
- Whitelist your website to only allow POSTing to pages you expect to see POSTS (see: https://perishablepress.com/protect-post-requests/)
- Keep a backup
- Update everything regularly with sudo apt-get update or yum update