Apache Security

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:

  1. 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”
  2. 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
  3. If you run phpMyAdmin, ensure you ONLY allow hosts you recognise
  4. Install mod_security (read: https://www.cyberciti.biz/faq/rhel-fedora-centos-httpd-mod_security-configuration/)
  5. 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>
  6. 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.
 }
 ?>
  1. Whitelist your website to only allow POSTing to pages you expect to see POSTS (see: https://perishablepress.com/protect-post-requests/)
  2. Keep a backup
  3. Update everything regularly with sudo apt-get update or yum update