Just recently I realized one of my non-profit organizations had a problem with their pre-existing wordpress website – it was suddenly broken.
Fatal error: Call to undefined function is_blog_installed() in ….. on line 440
I asked one of their volunteer programmers to look into it and they replied the site was hacked – The custom theme was corrupted and there was nothing more they could do – a clean install was needed. I asked if there were backups of the site… no one knew. I then asked the webhosting company to restore the oldest backup they had…. which was only 5 days old. A text search in the backups revealed the backups were also “infected” – useless, but something we can keep around incase my cleaning efforts further and/or totally break the site. The programmer was also unable to find a backup of the custom theme. Darn, I liked that theme!
I took a cursory look and then got deeper than never before – into some “very cool stuff”. Below is what I did to clean and secure the site.
1- Naive as I am to hacked wordpress installs, the programmer explained to me files like <base_path>/wp-content/theme/<themename>/index.php had gibberish code. Here is a snippet of that code…
2- Google-ing around revealed there is a massive attack on wordpress sites and due to some bad programming, the malicious infecting code is buggy and instead of stealthily hacking sites, is possibly unintentionally breaking them.
While a broken site is bad, there was a flip side – good news: The poor code revealed that the site is broken, insecure, and hacked… yet possibly fixable. 3 different issues that I will deal with as separate thought processes and troubleshooting.
- A broken site displays nothing – bad.
- A hacked site is infected and the actual infection needs to be removed.
- A hackable site means it has weak security – I need to find and close the holes that are enabling the hack.
3- The first place I turned to was WordPress @ http://codex.wordpress.org/FAQ_My_site_was_hacked.
This made me look into what was actually installed on the site. The WordPress version was old, the php version was not as high as it could be, and themes and plugins were all suspect but this did not help with the immediate problem, the site was unable to display anything. The programmer reinstalled the newest version of wordpress, re-attached the wp database, then used a default theme to get a basic version of the website up and running. In the meantime, I attempted to fix what I could on the backend.
4- After I cleaned 300+ infected files with a search and replace, updated the wordpress version, upgraded all plugins and increased the php version and disabled suspect plugins…. and backed up the site as is, I waited. A few hours later I did a search for that code and I found several files were infected again…and again. This told me the wordpress version, php version and plugins were not the entry point. I then restored from the backups and changed themes… and was still reinfected. Note:I am purposely NOT securing the site as much as possible, as fast as possible. I am trying to systematically disable possible entry points, allowing me to realize what the entry point was for future knowledge.
Zipping the website and downloading the zip to local computer and expanding locally, allowed me to do further “search and replaces” with notepad++. As the website was cleaned, I continued snapshotting the site (using zip) and moving the zip to local computer in order to further search and replace and investigate. If, at any time, the site no longer functioned, I always had a point to return back to using the versioned zip files.
Each time I was in cleaning mode, I temporarily disabled public access to the site with .htaccess…. allowing only my ip address to access the site.
deny from all
allow from <Your IP Address Here>
I continued to search with this command…
find . -name “*.php” -print | xargs sed -i ‘s@php eval(gzinflate(base64_decode(‘pRlrc9o69nN2Zv+Dyrgxbh….
…which I eventually shortened to …
find . -type f | xargs grep “eval(gzinflate”
…or variations of such.
5- I continuously watched the website logs with “tail -f access.log” and “tail-f error.log”. This showed me some urls/pages that were constantly being accessed from the outside, so I tried them myself. Yikes! Up popped a very flashy and “glittery” asian website – running on the site! I promptly deleted the hacked pages.
While zipping and re-downloading the site to my local computer, my virus scanner caught a hacked file or 2… awesome! These files were investigated and deleted.
6- I then installed the sucuri security plugin and audited all wp accounts. Some were disabled and others were demoted. Any remaining admin accounts were then reset with long and complex passwords.
I followed some great security steps using the sucuri plugin (and used the sucuri website (http://sitecheck.sucuri.net/scanner/) to scan the website, which did not really assist at this point).
The sucuri plugin allowed me to keep track of files being changed. Any file changed was investigated.
The sucuri plugin allowed me to change the secret keys. This blocked anyone who is currently logged into the blog from remaining logged in.
7- After doing a final zip, and after a 10 hour wait – no signs of any re-hacks, just the normal frequent attempts from bots trying to access the site (which I continued to monitor with access.log and also the sucuri plugin). While waiting, I asked the webhost do a free scan. They also identified some issues which I took care of, but days later, the site is still clean. At this point, I believe the hack was either a password issue or a hacked page like “top.php” with a script that executed every time the site was loaded.
Update: The Sucuriy security plugin’s wp-content protection feature breaks cforms 2’s ability to submit a form; It just hangs. Also, wp super cache breaks cform 2’s Visitor verification feature.
…and if you DONT want to wipe everything: