There is a malevolent stream of traffic on the Internet that no one notices. You’re not aware of it, but it’s out there, lurking, travelling in unseen packets from website to website, hoping to come across that one domain where the website security is a little too lax, the passwords a little too simple, and then pounce on it, infecting it with alien code that can do anything from pop up ads to trashing or deleting the site, and maybe even copying and sending your user information back to the mothership.
If you’re starting to feel nervous then good, I’m getting my point across.
You can Google “How can I protect my WordPress site?” and get dozens of excellent articles on simple, mostly non-technical website security measures you can implement quickly to immediately boost your site’s security. I recommend implementing as many as you can. For persistent attacks however, I’ve taken it one step further. Well, two steps.
The Nature of the Common Attack
Automated scripts called bots trawl the Internet jumping from link to link, constantly searching for unsecured, poorly secured, or sites with as-yet-undiscovered security flaws. When a bot does come across a site that they recognize as a WordPress, Joomla, Drupal, Mambo, Ghost, CodeIgnite, Zend, or any other popular Website platform, they’ll begin to probe it. Typically this amounts to trying default settings for usernames and passwords. If your password is “12345”, “qwe123”, “qwe321”, “manager” or something easy to guess, I’m 100% certain that sooner or later, your site is going to get hacked. It’s a small comfort to know that these attacks aren’t personal— at least most of the time. But you feel violated nonetheless.
If a bot successfully exploits a website security weakness and manages to worm its way into a site, one form of infection is that the bot deposits little chunks of code disguised as legitimate files. These piles of code poo can then execute instructions that may rewrite a web page, redirect your traffic to porn sites, or artificially craete links so when Google indexes your site, you inadvertently offer hundreds of backlinks to sites for enhancement pills, online gambling, or sites of a similarly dodgy nature. Have you ever see the startling red warning screen Google Chrome and Mozilla Firefox throw up when you reach a compromised site? Then you know what I’m talking about.
Website Security Countermeasures
I started noticing a little while ago that a WordPress website I manage would get knocked offline every once in a while. Fixing it was relatively easy, so I didn’t think much about it. Then, as it started happening with more frequency, so I looked more deeply into the problem. The issue was that code would get corrupted on various pages that WordPress needed to function. But I couldn’t spot where the attack vector (the point where the malicious code was inserted) originated. I needed a way to identify what was being executed that resulted in my site going blank. And then I needed a way to combat it. Because I was going to war.
The first part of the solution to improve the website security of the affected site presented itself as an excellent article on Logging post data. This gave me the basis for seeing what I couldn’t see, namely what data was being sent to my site to trigger the exploit. I set the script up and let it run overnight.
The logs the next morning were enlightening. As expected, the site was receiving an encoded message activating code that overwrote key files on the site, rendering it unusable. But it also gave me the starting point for enhancing the website security. Pages disguised as normal web page files had been inserted in odd places on the site. Sometimes the files would stand out as too obvious, such as code files in a galley image folder. Other times it would be the name of the file that gave it away. I combed through the site and eradicated the files that were being used to trigger the code, then I set about improving the website security to prevent this type of attack from endangering the site any further.
Active Defense
The exploit followed a certain pattern of attack. By generalizing the pattern, I set up a simple check: if the request being sent matched, deny access to the site from that IP address by writing the rule directly to the .htaccess file. For good measure, I added a check to see if “admin” was being used as a potential username for the site. Since I insist that “admin” never be used as a username, I knew this would be a probe, and I banned the originating IP address. Simple, foolproof and rock solid.
I know it isn’t elegant code, but it works:
$htaccessfile = "/hsphere/local/home/site_root_directory/.htaccess";
$ht = file_get_contents($htaccessfile);
# "ex" was the name of the $_POST key the injected code was using
# "log" is the WordPress username field
if(isset($_POST["ex"]) || (isset($_POST["log"]) && $_POST["log"]=="admin") ){
$fp = fopen($htaccessfile,"r");
flock($fp, LOCK_EX);
$ht = fread($fp , filesize($htaccessfile));
flock($fp, LOCK_UN);
fclose ($fp);
$pattern = "deny from ".$_SERVER['REMOTE_ADDR'];
if(!preg_match($pattern, $ht)){
$hn= str_replace("#postlogban\n","#postlogban\ndeny from ".$_SERVER['REMOTE_ADDR']." #".strtotime('now')."\n",$ht);
$fp = fopen($htaccessfile, "w");
if (flock($fp, LOCK_EX)) {
fputs ($fp, $hn);
flock($fp, LOCK_UN);
fclose ($fp);
}
And in .htaccess, all I need to put in at the top is:
php_value auto_prepend_file /hsphere/local/home/site_directory/postlog/postlog.php
#With many thanks to apokalyptik for this one line of code
order allow,deny
#postlogban
allow from all
...
False positives at this level are essentially nonexistent, but they can happen. Make sure to test, test, test until you’re sure legitimate visitors aren’t being banned accidentally. Since this particular exploit used data sent to the site, I could easy ignore any traffic that wasn’t POSTing data, which is most of the traffic anyway.
The Result
It’s been weeks since the site has been compromised, and the only maintenance I have to do is clean out the log files and banned IP addresses every once in a while.
Website security is the responsibility of every webmaster. You don’t have to be a security expert, but you should know enough to ensure that the websites you are responsible for stay protected. If you are concerned that your site might be under attack, please contact me to discuss adding this website security measure to your site.
Deprecated: Function get_magic_quotes_gpc() is deprecated in /srv/marcgottlieb.com/wp-includes/formatting.php on line 4803
Deprecated: Function get_magic_quotes_gpc() is deprecated in /srv/marcgottlieb.com/wp-includes/formatting.php on line 4803
Deprecated: Function get_magic_quotes_gpc() is deprecated in /srv/marcgottlieb.com/wp-includes/formatting.php on line 4803