Monthly Archives: March 2009

wordpress mu XSRF

Cross-site request forgery (XSRF). It’s something that’s becoming a big issue in internet security, and yet is still relatively poorly understood by many developers. If you don’t already know what it is, you can find an excellent introduction in wikipedia:

http://en.wikipedia.org/wiki/XSRF

In a nutshell, anything on your website is a security risk if it lets someone modify something on your system (eg an entry in a database) without first making sure that the request for that modification actually came from your site. This isn’t restricted to a URL query string. Forms are probably the worst offender because many developers seem to think they’re somehow safe. They’re not.

A good way of preventing a XSRF attack is to give each form a unique identifier which keeps changing. Only your web application will know for sure that a request has come from a form on your site, because that application generated the identifier in the first place and can cross-check it against an entry in a database. Drupal does this, and so does WordPress (including WordPress MU).

Here I’m focusing on how WordPress MU does the XSRF protection. It’s called, wait for it…

Nonce?

ok, ok. Get the sniggering done now. And relax…

To the good people at WordPress (and seemingly everyone in America) nonce has only one – very unfunny – meaning: a word or expression which only ever occurs once. ie. a unique key which changes its value every time it’s used.

By default all WordPress forms use nonce values to help prevent XSRF. If you write your own plugins, to get this to work in WordPress is amazingly simple. Just put this in your home-grown form:

 wp_nonce_field('my_nonce_phrase');

where ‘my_nonce_phrase’ can be any unique phrase which acts as a base for the system-generated nonce key. It’s usually a good idea to use something like plugin-name+form-name so you eliminate the risk of clashing one nonce value with one from a different form. But basically you can use any phrase you like.

If you need more info, the WordPress API listing is here:

http://codex.wordpress.org/Function_Reference/wp_nonce_field

If you want to put a nonce in a URL rather than a form, just use the very similar:

wp_nonce_url('theurl', 'my_nonce_phrase');

where this time ‘theurl’ is, predictably, the url that you want to noncify, and ‘my_nonce_phrase’ is once again your unique phrase which is going to act as the seed for the eventual nonce key.

Whitelist

There is however a slight catch. Some forms on the backend are forms where you want someone to update various options parameters. For example, if you’ve built a plugin and want someone to be able to set various plugin default options. In standard WordPress, you use options.php as the form’s action, and can use the following as a nonce field:

wp_nonce_field('update-options');

This way, when the update button is pressed the fields you’ve added to your form will automatically get updated as part of the options.php code, and the nonce system will be happy that the form came from the right website. Everyone’s smiling. Everyone’s happy.

This doesn’t work with WordPress MU, however.

Instead you need to add this to your form:

wp_nonce_field('my_nonce_phrase-options');

where adding -options to the end is crucial if you want options.php to work properly. I’m not sure why. It just is.

Finally, in your plugin you need to be able to alter the nonce whitelist ie. the list of option names which are accepted by options.php. You could just alter options.php, but that would be crazy. Instead use a filter to intercept the whitelist and add your own values to it:

function my_plugin_alter_whitelist_options($whitelist) {
  if(is_array($whitelist)) {
    $option_array = array('my_nonce_phrase'=>array('plugin_option_1', 'plugin_option_2', 'plugin_option_3', 'plugin_option_4'));
    $whitelist = array_merge($whitelist, $option_array);
  }
  return $whitelist;
}
add_filter('whitelist_options', 'my_plugin_alter_whitelist_options');

Yes, it’s ugly and bad. But there doesn’t seem to be any way round this for WordPress MU and forms used for setting your own options in a plugin.

Summary

WordPress MU lets you build forms which are relatively safe against XSRF attacks. Doing this is easy, and takes just one line of code in your form. A word of warning: adding protection to forms which make use of WordPress’s options feature is more fiddly in MU than it needs to be, but still not too bad.

Twitter Updates for 2009-03-20

  • @fooflington also large areas of countryside north of Aberdeen. google countrylaneview in reply to fooflington #
  • large tracts of the Norfolk countryside in #streetview – lovely, but why? Because they can… #
  • cool Edinburgh’s in #streetview. Absolutely nothing in Kent or Sussex. Not even Brighton. #
  • some bizarre places in street view: Scunthorpe?? #
  • hey google street view is in the uk! #

Twitter Updates for 2009-03-20

  • @fooflington also large areas of countryside north of Aberdeen. google countrylaneview in reply to fooflington #
  • large tracts of the Norfolk countryside in #streetview – lovely, but why? Because they can… #
  • cool Edinburgh’s in #streetview. Absolutely nothing in Kent or Sussex. Not even Brighton. #
  • some bizarre places in street view: Scunthorpe?? #
  • hey google street view is in the uk! #

Twitter Updates for 2009-03-19

  • nice article on combining twitter accounts. http://tinyurl.com/combinetwitter #
  • @dmchapman Thanks for letting me know about the event. Partly organized by the mysql people at sun, partly drupal people in reply to dmchapman #
  • On train home from drupal enterprise event. Useful stuff. Need to check the aegir multisite modules #
  • @bencc they even tried building ships from wood pulp and ice (called pykrete) in reply to bencc #
  • I knew it wouldn’t be long before someone mentioned Lego #
  • Met Tim Deeson at drupal enterprise event. Good sign I guess. #
  • @markfendley might not do the same this year is what could go wrong. in reply to markfendley #
  • Apparently drupal4enterprise had beer and pizza for lunch last year. #
  • On the train to drupal enterprise event at Sun. #