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