Archive for the ‘PHP’ category

SB Child List Update 1.2

June 19th, 2010

Just a quick one today… I have just checked in an update to the SB Child List plugin. It has been hugely popular with the Wordpress community with only the one complaint to date… the reliance on the GUID field in the wp_posts table.

For some reason Wordpress does not update this field often enough and it leads to broken links. I have updated the plugin to use the get_permalink function which I understand to work correctly in more recent versions of Wordpress. I have also fixed a bug with the nesting level not saving correctly on the settings page.

Enjoy the release and please do let me know if you think the plugin can benefit from an update.

Wordpress sites hosted by Rackspace Cloud hacked!

June 18th, 2010

I spent the best part of last night helping someone sort out their hacked sites. An interesting problem really… it’s a hack that has been effecting Wordpress sites hosted with Rackspace Cloud and early speculation suggests it’s to do with an outdated version of PhpMyAdmin that someone had managed to break into. Rackspace have, apparently, been keeping quiet about it and have been logging into peoples servers and removing the appropriate files and records (so i’m told).

What does it do?

The hack causes a file to be uploaded to one of your plugin directories and masks itself as a language template file (pot). So far I have seen it hiding within All in one SEO pack and Si Captcha plugins but there are more! Within the file is a huge amount of garbage that looks to be rubbish. In actual fact it’s all valid php code but nonsense in the form of massive nested ternary IF statements using Hex codes as the condition and action parts. The point is, of course, to make the file look encrypted whilst actually masking a single function. This function simply calls a single row from the wp_options table, selects a portion of the data, reverses it runs it.

The second part of the hack is as follows… The database row that the above file decodes is stored on wp_options with an option_name of rss_ followed by a long number… again an attempt to make it look genuine. Within the row is a serialised string containing what looks like valid data but with a huge encoded section in the middle. To the trained eye it’s known to be a base64 encoded string, however, the twist is that the string and corresponding ‘eval’ statement are reversed and therefore running base64_decode won’t work out of the box.

When reversed and run, it’s a chunk of php with yet more base64 encoding inside but this time the correct way round! The end result is that it’s both a shell and a mysql browser allowing anyone knowing the correct URL parameters to gain access to both your file system and database(s).

Scary huh! Anything else…

Sadly yes! Most sites are reporting a new user in their users table with administrative rights sometimes called ‘amin’, other times having a … in it and other times completely hidden. I have read that the username is actually a huge amount of JS code which hides itself. Fairly clever to give the author of this hack credit where it’s due!

Next other sites are reporting some dodgy iFrames showing up in their posts. This is, apparently the extent of the problem however with complete access to your database and file structure they could be a lot more malicious.

Is there a fix?

Yep… Rackspace are, apparently, doing their best to fix the problem whilst not (at the time of writing and to my knowledge) taking responsibility for the problem. I am told that the site setup has been blamed and permissions of 777 have been mentioned. Again, all speculation so best go read up at more official sources.

So other than Rackspace sorting it you can do any of the following…

  • Remove any spurious rows from wp_options where there is a large encoded block in the value field. You should be looking for anything with an option name of rss_…. where … is a large number.
  • Remove the user ‘amin’ or anything with ‘…’ inside it from your database and change any passwords. The hack can NOT give the hacker your admin password so don’t worry but it’s best to change it just in case. There are always ways!
  • Check your plugin files for anything that looks odd. The file that I have seen has the ending .H.bak.pot or something similar. Bear in mind that .h is a library file, .bak is a text backup file and .pot is a language file. Neither .h nor .bak have any business on a Wordpress site.

How can I stop this sort of thing from happening again?

You technically can’t but there are a couple of things to help you out…

  • Backup your site files and database regularly (where regularly is more frequent than once a month or just relying on your provider to do them!)
  • Turn off PHP commands like EXEC and EVAL. Anything that gives the PHP script access to your filesystem. It will definitely cause problems with plugins and sites but it’s the price we pay for safety
  • Make sure your permissions are all correct and check them regularly.
  • Check plugins before uploading them, a simple check in files for eval or exec should do it but it depends on how fussy you want to be!

That’s it for me… there are loads of blogs about detailing more about the problem and I understand the threat to be several days old now. Still worth knowing isn’t it!

Recursive PHP function for finding a top level parent post

June 5th, 2010

So… the name says it all doesn’t it! Here’s the story.. I wanted to apply different sidebar widget areas in Wordress for different pages.

One of the sites I am working on has three top level pages which will form three distinct sections of the site. I decided that it would be good to show different sets of widgets within these sections and therefore had to concoct a way to determine from any page it’s top level parent page. The function below simply returns true or false if the first argument is a child of the second. It also returns true if the first argument is the same as the second.

The Function

function page_has_parent($current_page, $target_parent=0) {
	global $wpdb;

	$return = false;

	if ($current_page == $target_parent) {
		$return = true;
	} else {
		$sql = 'SELECT post_parent
			FROM ' . $wpdb->posts . '
			WHERE ID = ' . $current_page;
		if ($parent = $wpdb->get_var($sql)) {
			if ($parent == $target_parent) {
				$return = true;
			} else if ($parent) {
				$return = page_has_parent($parent, $target_parent);
			}
		}
	}

	return $return;
}

The Usage

The following is a Wordpress example of showing one sidebar or the other based on page

$this_page = get_the_ID();
if (page_has_parent($this_page, 7)) {
	dynamic_sidebar('Sidebar2');
} else if (page_has_parent($this_page, 11)) {
	dynamic_sidebar('Sidebar2');
} else ....