WordPress Hacks

Being hacked is scary. It's the worst thing that can happen to most people. Generally speaking, a hacked site boils down to some pretty obvious avenues of attack:


 * 1) Insecure customer password
 * 2) Insecure behaviors
 * 3) Bad plugins/themes/extensions
 * 4) An insecure webserver

DreamHost works very hard to make sure that last item isn't an issue, but since it's something out of the most people's hands (unless you're on a VPS/Dedicated server), it's best to concentrate on what you can address.

Being More Secure
Security starts at home and there are some basic things you can do to make your site more secure. Remember, if your site is important, treat it with love and respect.


 * Don't reuse passwords - Most of us use the same password in multiple places. We shouldn't.
 * Use strong passwords - You can generate them from places like Strong Password Generator.
 * Use a password tool - LastPass and 1Password are great for protecting your passwords and generating new ones.
 * Don't use FTP - Use SSH or SFTP whenever possible

If you think you've been hacked, request a scan. DreamHost can run a tool to check your site. That will send you an email with a list of any files that may be problematic. This does not scan your database. Even after that scan, you'll want to clean your site up.

Cleaning WordPress
The best way to clean WP is to delete everything and start over. Obviously we don't want to do this all the time, because after a hundred posts, we don't want to lose anything. Don't worry! WordPress is actually pretty easy to do this with, you just have to go in order.

Determine what you have
Make a list of everything on your account. Separate the ‘personal’ files from the application files. For example, in WordPress list the themes and plugins as the ‘application’ files, because we can easily download them from the repository. It's best to download the themes, in case you have someone with a child-theme. The ‘personal’ files would be the images in  and   (for any Multisite install created pre 3.5), the   file and   file.

If you've install WordPress in your main site folder, everything will be laid out like this:

/home/username/example.com/ /home/username/example.com/wp-config.php /home/username/example.com/.htaccess /home/username/example.com/wp-content/uploads/

Keep in mind, the themes and plugins folders are also in your wp-content folder, but we don't want to leave those. Instead, make a list of everything in there. You'll be able to get fresh copies from WordPress.org. If you're using a commercial plugin or theme, you will probably need to download their code from them directly. Most good shops will let you do this.

You can make your list using the folder names:

/home/username/example.com/wp-content/plugins/akismet /home/username/example.com/wp-content/plugins/jetpack /home/username/example.com/wp-content/plugins/wordpress-seo /home/username/example.com/wp-content/themes/twentyeleven

If you can't see the .htaccess file, you may need to edit the settings on your FTP program to show hidden files.

Make a Backup
Backup all your files and your database. Your files can be done easily via FTP (remember, use SFTP), and your database is best done through phpMyAdmin. You can log into your database via your Panel. In an emergency, we'll have to restore from this backup, so remember to get all your files.

Delete the files
Every file gets deleted off the server. Yes. Every file. When it’s WordPress, kill it all with fire except those personal files. If you've added additional software (like you have zenphoto or drupal in the same folder), you should not remove those, but be wary - They too may be hacked.

At this point, your site will be down. That's okay. We have to make sure it's clean before we put things back. The only files/folders you should have left are these:

/home/username/example.com/ /home/username/example.com/wp-config.php /home/username/example.com/.htaccess /home/username/example.com/wp-content/uploads/

Change Passwords
You will need to change the following passwords:


 * Panel
 * Email (if hosted on DreamHost, or if it's the same as any other password)
 * SSH (shell/FTP) for that site's users
 * SQL for that database users

You can change all of these inside Panel.

Review your files
Still with the site down, look over my .htaccess and config files with a fine toothed comb. If you don't know what they should be, revert back to the defaults for both content and permissions. You can rebuild the wp-config.php in a pinch.

wp-config.php
If there is anything like the following in your file, you have definitely been hacked, and you MUST remove it ASAP. Base64 hacks are insidius and leave backdoor that hackers can use again and again on your site.



Delete that section entirely, or better yet, just rebuild the wp-config.php.

.htaccess
The default .htaccess for a non-Multisite install is as follows:

 RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule. /index.php [L] 
 * 1) BEGIN WordPress
 * 1) END WordPress

If you're using Multisite, you'll want to read Multisite htaccess and Mod Rewrite, and select the correct .htaccess for your install.

Your wp-config.php should be pretty straight forward. If you see anything with base64, delete it right away. Also you will need to change the SQL password here.

Reinstall
Go to WordPress.org's download page and upload those files to your server. Magically your site will be back, though you'll note it's missing the themes and plugins. That's okay. Remember that list you made of all your plugins and themes? You had a list like this:

/home/username/example.com/wp-content/plugins/akismet /home/username/example.com/wp-content/plugins/jetpack /home/username/example.com/wp-content/plugins/wordpress-seo /home/username/example.com/wp-content/themes/twentyeleven

Now go to http://wordpress.org/extend/plugins/akismet and you can download the file right away.

If you're comfortable on command line, you can use wp-cli to install by typing the following:

wp plugin install akismet wp theme install twentyeleven

and so on.

The End!
After you've done all that, your site should be back to 'normal.' You may find your theme needs some customization again, in the way of widgets and menus being reset. That's an unavoidable situation that happens when people have hacked your site. WP does its best to remember the way things should be, but it's not perfect.

One More Scan
If you're interested in going that extra mile, there are more things you can look for.

Look 'one folder up' for index.php and wp-config.php : Sometimes if you installs WordPress in domain.com/wp/ you'll run it out of domain.com. When that happens, you'll have those two files in domain.com, and from time to time they get missed when you clean up. Go look and make sure there isn't any base64 in there

Look for funny named files : Any file named ljkdhsf92328kjhsdfsdf or mai1.php (that's mai-one, not mail) is probably suspect. Delete them.

Look at the website : Does it look legit? You're smart, you know what's sketchy. If a pop culture blog has viagra all over it, that should stand up as strange. Pun intended.

Who are the users : WP-CLI is your friend! is a fast way to find out if they have extra users.

wp-content/uploads
There should only be media files here. One of the things a hacker likes to do is to put PHP in there to exploit later. You can run this command to see if there are any PHP files in their uploads and, if so, look at the files for hacker stuff.

find /home/user/domain.com/wp-content/uploads/ -name "*.php"

Also look at the blogs.dir if there is one: find /home/user/domain.com/wp-content/blogs.dir/ -name "*.php"

There should rarely be a .php file in your uploads. If you don't recognize it, it's most likely to be spam, and should be removed (or renamed .txt) right away.

.htaccess
Another lovely vector is the .htaccess. If you search for .htaccess files on the account, there really shouldn't be that many, just the one in the main blog folder. Run the following search and review the .htaccess files that come up.

find /home/user/domain.com/ -name ".htaccess"

If you see things like this, it's bad:

       RewriteEngine On        RewriteBase / RewriteCond %{HTTP_REFERER} ^http://[w.]*([^/]+) RewriteCond %{HTTP_HOST}/%1 !^[w.]*([^/]+)/\1$ [NC] RewriteRule ^.*$ http://globalconferencemanagementgroup.com/hcwf.html [L,R] 

Base64
tl;dr - Base64 is usually bad. Really bad. Super bad. And yet there are legit use cases.

Running  should only give you these results for core WordPress:

./wp-admin/includes/class-wp-importer.php:	$headers['Authorization'] = 'Basic '. base64_encode( "$username:$password" ); ./wp-includes/class-smtp.php:       		fputs($this->smtp_conn, base64_encode("\0".$username."\0".$password) . $this->CRLF); ./wp-includes/class-smtp.php:       		fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); ./wp-includes/class-smtp.php:       		fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); ./wp-includes/class-smtp.php:       		fputs($this->smtp_conn,"AUTH NTLM " . base64_encode($msg1) . $this->CRLF); ./wp-includes/class-smtp.php:       		$challange = base64_decode($challange); ./wp-includes/class-smtp.php:       		fputs($this->smtp_conn, base64_encode($msg3) . $this->CRLF); ./wp-includes/ID3/module.audio.ogg.php:		$flac->setStringMode(base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value'])); ./wp-includes/ID3/module.audio.ogg.php:		$data = base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']); ./wp-includes/class-IXR.php:               	$value = base64_decode($this->_currentTagContents); ./wp-includes/class-IXR.php:       		return ' '.base64_encode($this->data).' '; ./wp-includes/class-feed.php:			$data = base64_decode( $data ); ./wp-includes/class-phpmailer.php:       	$encoded = chunk_split(base64_encode($str), 76, $this->LE); ./wp-includes/class-phpmailer.php:       	$encoded = base64_encode($str); ./wp-includes/class-phpmailer.php:       	$chunk = base64_encode($chunk); ./wp-includes/class-phpmailer.php:     	return base64_encode($signature); ./wp-includes/class-phpmailer.php:   		$DKIMb64  = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body ./wp-includes/SimplePie/Sanitize.php:		$data = base64_decode($data); ./wp-includes/SimplePie/File.php:		$out .= "Authorization: Basic ". base64_encode("$url_parts[user]:$url_parts[pass]"). "\r\n"; ./wp-includes/class-http.php:			return 'Proxy-Authorization: Basic '. base64_encode( $this->authentication ); ./wp-includes/class-wp-atom-server.php:		explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6))); ./wp-includes/class-wp-atom-server.php:		explode(':', base64_decode(substr($_SERVER['REDIRECT_REMOTE_USER'], 6))); ./wp-includes/class-snoopy.php:			$headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n"; ./wp-includes/class-snoopy.php:			$headers .= 'Proxy-Authorization: '. 'Basic '. base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n"; ./wp-includes/class-snoopy.php:			$headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass);

Now that said, you will see it in plugins and (sadly) themes. Are these safe? Hard to say. There are over 24,600 plugins in the WPOrg DB alone, so it's very much a your-milage-may-vary situation. The best thing to do is delete the plugins and reinstall them. Same with themes.

Split The Users
Splitting up your user accounts is also a good idea to isolate your sites. By assigning one domain per user account, you ensure that if that user gets hacked, only that site is broken. Also you make sure that if that site is hacked, it can't infect the others.

We have a One User Per Domain Policy which means each domain can only have one user account, but one user account can 'own' multiple domains. To do this, simply make a new user account for that domain, and go in to your panel to edit domains. Change the value for "Run this domain under the user:" to the new user, and your site will be moved over for you.

Please only do this AFTER you clean the site, otherwise we'll never be able to track down what happened.

Hiring Help
DreamHost has partnered with StopTheHacker to provide a service to clean your entire account.