How to rescue a WordPress Hack

livesaverThis evening, I rescued a client’s WordPress website from a hack that was so bad their host shut it down. I have a checklist that I use now to recover WordPress sites, which I’d like to share with you. Or you can hire me to do it for you as it requires some technical confidence!

You’d save a lot of heartache, if you backed up your database regularly!
The following step are for when you haven’t and your site is trashed. These should get you back up and running. Take them at your own risk and don’t blame me or sue me – hey your site was trashed anyway!

Gather your account passwords

You’ll need to be able to access PHPMyAdmin and FTP.
PHPMyAdmin is a script on most webhosts control panel that allows you to work on the MySQL database that drives WordPress.
FTP means File Transfer Protocol – it’s the way that you can make changes to the files on your server using a program like Filezilla.
You’ll need usernames and passwords to get into both.
I’m going to assume you know how to use them – if not hire me!

1) Put WordPress in maintenance mode

If your host hasn’t taken the site offline, you’ll want to prevent anyone from doing anything within a wordpress login by putting the site into maintenance mode.
Create a one line php file with the filename .maintenance (just like .htaccess it’ll be a “hidden” file)
the one line you need is

Upload the file to the root directory of the install – usually the same directory as wp-config.php
That forces WordPress into maintenance mode with the message “Briefly unavailable for scheduled maintenance. Try again in a minute.”

2)Change the database passwords

Delete the database user in your webhost control panel and create a new one with a completely different password.
Download the wp-config.php file and edit it. Most wordpress hacks are through a compromised login, where the hacker then uploads a plugin. Assume they know now your db password.
Adjust the wp-config.php lines

Replacing the hashes with the new username and password combination.

Next scroll down to the Authentication Unique Keys and Salts section.
It will look something like this…

Changing these will force logout of anyone logged in.
The WordPress boys and girls have provided a useful tool to regenerate these at https://api.wordpress.org/secret-key/1.1/salt/. Don’t be lazy and copy the above 😉

Go ahead and change these in wp-config.php.
Have a quick scan through the rest of the file to check nothing weird is in there. You can compare it to wp-config-sample.php to be sure!
Your wp-config.php is now ready – but don’t upload yet.

3) Delete the current WordPress Install

I think it’s safest to upload a complete fresh install, rather than update.
So delete the following directories – wp-admin, wp-includes and all the files in the root except .htaccess. Do not delete wp-content!

4) Note what plugins and theme were active

If your site is down and you can’t remember which plugins and theme were active then follow this step
Login to PHPMyAdmin and find your WordPress table and click the wp_options (you may have a different prefix than wp_) and then SQL tab

Use the statement SELECT * FROM wp_options WHERE option_name = “active_plugins”
Click on edit to see what the value is
It will look something like this

Yikes! That is a serialized arrray – but I can see PostLikes, akismet, church-admin-csv, church-admin, emergency-password-reset, never-loose-contact-form and signup-before-leaving are the plugin directories of active plugins.

Simpler is finding which theme was active
The SQL statement
SELECT * FROM gateway_options WHERE option_name = “current_theme”
will show which theme was active!

5) Clean up the users

Go to the wp_users table and delete any unknown users – especially with date stamps around when your site was hacked.
If you still have an “admin” user – change the username away from admin right NOW! That is likely how the hackers got in!

6) Check the Database for hacked posts and comments…

In phpmyadmin, click your database name at the top, so that all tables are showing and then click “search” – search for “iframe” in all tables

search-database

You can then check the entries that show for anything untoward.

7)Clean the wp-content directory

This is where the hacker will have most likely done damage. You should have the directories plugins,themes,upload and upgrade there. Some plugins may have added other directories or even files too.
The index.php file in wp-content should just have

Goto the plugin directory – delete everything! You will upload fresh copies later.
Next the themes directory – again delete everything (careful you have copies of bespoke/child themes stored elsewhere!)
Then go through the uploads directory, by year and month. Delete any .php files – should just be images, pdfs and other user uploaded files.
Delete anything in the wp-content directory that looks suspicious and especially any files ending in .php that don’t look like above.

8) Download fresh copies of plugins and themes

The quickest approach is to download them all as zips, unzip and uplaod back to wp-content/plugins, so that when you get wordpress going again, they are already in their activated state.

9) Download a fresh copy of wordpress from wordpress.org

Unzip all files and upload

9) Upload your prepared wp-config.php files

10) Finally delete the .maintenance file

Delete the .maintenance file from the root directory and you should be live again

I’m happy to help – get in touch for a quote

Does anyone have any other steps they take to clean hacked wordpress sites?

Small Group Maps

The latest version 0.557 of the WordPress Church Admin plugin has gone international and maptastic!

1) Addresses are now entered in a one line format to be more international friendly. On the output pages a comma will trigger a new line.

2) People can have a prefix before their surname like “van der” – but the directories will still be sorted by alphabetic surname

3) You can store a meeting venue for small groups and geocode the address for a map
[church_admin type=”small-groups-list” map=1] will give the map format if you have geocoded addresses and defaults back to the old format if not.

Improvements to Church Admin Plugin

I’ve made some improvements to the Church Admin Plugin in v0.52

Main menu – vastly improved with drag and drop and close

Rota management – the rota now uses autocomplete to store people in their job! You can also email the rota out to participants

Sermons – can now be uploaded and podcasted – mosts hosts have an upload limit of 8MB, so there is a facility to add already uploaded files that perhaps you have ftp’d.

The cache of emails is now stored in a subdirectory the uploads directory – with a redirect in the old directory.

Photos You can upload photos for people, but not much use is made of them yet

Fixes

  • Activation errors
  • Tied up code and initialise all variables more correctly
  • Functions that require people to be in the directory first only show when directory is populated.

Coming Soon

  1. Shortcodes page in the menu to list all the shortcode options
  2. Photos in the directory as an option
  3. Bible passages in the sermon uploader
  4. Rewrite of the calendar module – with ical support
  5. Instruction Manual

Writing and updating the plugin is pretty time consuming but fun and largely fuelled by coffee, so if you like, please thank me with a brew!…


What would you like to see added to the plugin?

Bulk WordPress Password Reset

Reset by Orse on flikr.com
Reset by Orse on flikr.com
Sometimes it is a good idea to reset all the passwords for your WordPress website and email the users to let them know their new password. Especially when you have been hacked – if you have been hacked, read about what to do

My emergency password reset plugin will regenerate every user’s password and email it to them. If you have been hacked, I advise you change all the SALTS in wp-config.php, which forces all users to log out too. WordPress.org provides a tool to generate new SALTS.

To us my bulk emergency password reset and email plugin…

1) Download the emergency-password-reset at wordpress.org plugin
2) Upload the zip file to your plugins directory and activate.
3) If you are and administrator you can click on “Reset all Passwords” – the plugin will generate new more secure passwords and let all the users know.

Hope you find it useful

How to internationalise a wordpress plugin

If you want your plugin to have a greater reach why not internationalise it – hopefully people will soon start translating it for you!

Here’s what to do!

Step 1

set up the plugin to load the translation files with this code, changing “your-plugin-name” as needed.

That means that wordpress will load the right translation file from your plugins languages directory.

Step2

Change all the output text in your plugin to use the internationalised versions

so $foo= ‘Blah Blah’; becomes $foo=__(‘Blah Blah’,’your-plugin-name’);
and
echo ‘Blah Blah’; becomes _e(‘Blah Blah’,’your-plugin-name’);
Thoroughly test your plugin at this stage!

Step 3

Set up the initial default translation file defautlt.po in the languages folder.
Download and install poedit from http://www.poedit.net/download.php
The instructions are about as useful as a chocolate teapot, hence this blog post.

Once you have installed the Poedit program, open it.
poedit-first-screen
Click on File then New catalog…
poedit-new-catlog-first-tab
Fill out the Project Name at least and then click on the Sources Path tab.
This is where everyone goes wrong on Windows computers! The base path needs to be the full path to your plugin root directory not “.” e.g. C:\xampp\htdocs\wordpress\wp-content\plugins\church-admin
Then you can add the sub directories in the paths section by clickingthe second icon from the left (dotted box type icon).

Next click on the Sources Keywords tab and select each of the current ones and delete them.
Add __ and _e and then press ok

With any luck you will not get the annoying “Updating the catalog failed error” which happens when you don’t do the full windows path.
poedit-error

Now you can save the file as default.po in the languages folder of your plugin.

Click on Update at the top and it will search your php files finding words that will need to be translated

poedit-done

Click save to save it!
Then commit the default.po file and language directory using your SVN programme and let your user base now of the update, by announcing it readme.txt, your facebook plugin page, twitter account….

Hope that helps. A future post will be how to translate your favourite wordpress plugin!

Control how Facebook likes & Tweeted URLs look from WordPress

If you want to control what image and content Facebook uses when someone likes a post/page on your WordPress site, then add this snippet to your theme functions.php. Any Facebook likes will then use the featured image from that post or page.

A similar thing can be done with Twitter – called Twitter cards – a simple version is previewed below. It can add a neat little card under a tweeted url from your site if you use the code below and apply to the program! It takes 5-10 days to be improved, so do it now!

twitter-card-preview

How to get it working
1) Use the code below in your theme and get it uploaded
2) Go to https://dev.twitter.com/docs/cards/preview to check it works with a url from your site with my code!
3) Go to https://dev.twitter.com/form/participate-twitter-cards to apply.

[code]add_action( ‘wp_head’, my_theme_facebook_meta_tags );
function my_theme_facebook_meta_tags()
{
global $post;
echo'<!–Facebook tags–>’;
//image
if(function_exists( ‘has_post_thumbnail’ )&& has_post_thumbnail( $post->ID ))
{
$thumb = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), ‘thumbnail’ );
echo'<meta property=”og:image” content=”‘.$thumb[0].'”/>’;
}
elseif(function_exists(header_image))
{
$thumb=header_image();
if(!empty($thumb)) echo'<meta property=”og:image” content=”‘.$thumb.'”/>’;
}
//url
echo'<meta property=”og:url” content=”‘.get_permalink($post->ID).'”/>’;
//post title
echo'<meta property=”og:title” content=”‘.get_the_title() .'”/>’;
//site name
echo'<meta property=”og:site_name” content=”‘.get_bloginfo(‘name’).'”/>’;
//excerpt
if ( !empty($post->post_excerpt) ) {
$description = strip_tags(strip_shortcodes($post->post_excerpt));
}
else
{
$description = my_theme_wordlimit(strip_tags(strip_shortcodes($post->post_content)));
}
echo ‘<meta property=”og:description” content=”‘.$description.'”/>’;
echo'<!–End Facebook tags–>’;
}
function my_theme_wordlimit($string, $length = 50, $ellipsis = “…”)
{

$words = explode(‘ ‘, $string);
if (count($words) > $length)
return implode(‘ ‘, array_slice($words, 0, $length)) . $ellipsis;
else
return $string;
}[/code]