Mark on WordPress

WordPress puts food on my table.

WordPress 2.0.3: Nonces

with 75 comments

WordPress 2.0.3 has some security enhancements that a lot of people are wondering about, so here’s my attempt at explaining them.

Authentication: cookies are your backstage pass

When you sign into WordPress, you are granted a cookie… a little file that lives in your browser and acts as your “backstage pass” to the WordPress admin. This prevents unauthorized people from accessing your admin and doing bad things. They don’t have the cookie, so they’re stopped at the door by the bouncer. Your cookie is tied to your user account, which ties into the WordPress capabilities system which controls what things you can and can’t do in the admin. This is authentication: verifying that the person performing an admin action is authorized to do it.

Intention: the need to protect you from yourself

Say you’re logged in to your WordPress install. You can click links and submit forms that do things to your blog. Things like changing options, deleting posts, creating users, etc. What would happen if someone were to create a link or a form that points to your WordPress admin and attempts to do something malicious? Well, if an unauthorized person submits the form or clicks the link, nothing happens. They get rejected by the browser because they don’t have a login cookie. But what if you were tricked into clicking that link? Uh oh… the bouncer lets you in, and the action is performed. You have authority, but you lacked intention. You didn’t mean to click a link that would delete a post. You were tricked! In order to protect you from this, WordPress needs to make sure that you intend to do the things you do.

Intention: HTTP_REFERER is the old way

In the past, WordPress did the following: it verified that the page you were viewing before you initiated the action was a WordPress admin page. That is, you were already inside… the link or the form that you clicked wasn’t malicious; it was part of the WordPress admin. WordPress did this by checking the HTTP_REFERER value that your browser sent.

Intention: HTTP_REFERER shortcomings

HTTP_REFERER has problems. First, it can be spoofed by JavaScript in a certain popular browser (I’ll give you one guess). Second, some firewalls or proxies strip this information out. The spoofing means that it isn’t secure. The stripping of the referer means that some users won’t be able to perform actions in their WordPress admin. I grew tired of people complaining about not being able to use their WordPress admin, and wary of the security implications. I posted this message to the WP-Hackers list on April 17th, and a huge discussion ensued. I suggested an alternative method of verifying intention, and as of WordPress 2.0.3, this system has been implemented.

Intention: nonces are the way forward

A nonce is a number used once, and it is used for intention verification purposes in WordPress. Think of it as a password that changes each time it is used. WordPress’ implementation isn’t technically a nonce, because the electronic key only changes every 12 hours, and is valid for 24 hours (that is, the current key, and the penultimate key are valid), but it’s close enough. The idea is simple: we verify that user’s request is intentional by verifying that the request originates from within the WordPress admin. And we do that by providing a piece of information (a nonce) to them when that first page is requested. When the action is performed, the piece of information is passed along, and verified. Nonces can be locked down in many ways. They are unique to the WordPress install, to the WordPress user, to the action, to the object of the action, and to the time of the action (24 hour window). That means that if any of these things changes, the nonce is invalid. So if you (somehow) intercept a nonce being used by me, you would, first of all, only have 24 hours to use this key to attempt to trick me. And you’d only be able to use this key to trick me, on my blog, into doing a specific action to a specific item. So even if you got a nonce used to delete a post, the absolute worst case scenario is that you might be able to trick me into deleting that specific post. The nonce is useless for any other purpose.

Nonces: use them in your plugins!

Plugin authors, listen up. In order to prevent the backwards-compatibility “Are you sure?” dialog from coming up when HTTP_REFERER-agnostic users interact with your plugins (especially options pages), you need to add nonce capabilities to your plugins. Don’t worry, it’s way easy.

<form> nonce protection

To protect your <form> with a nonce, simply use the wp_nonce_field() function within the <form> (I’d do it right after the opening tag.) For backwards compatibility, use function_exists() to execute the code conditionally. The string you pass to the function should be unique to your plugin. Use the following convention: plugin-name-action_object So, if my plugin is called “cool plugin” and the action the form does is “update options” and the object is “advanced options,” I’d do cool-plugin-update-options_advanced. The “object” part isn’t required, but if you have multiple forms, protect each one with a different object for the highest level of protection.

<form ...>
<?php
if ( function_exists('wp_nonce_field') )
	wp_nonce_field('plugin-name-action_' . $your_object);
?>

Link nonce protection

If you’re performing actions based on the clicking of links, you can add a nonce to your links using wp_nonce_url() which takes two parameters. The first is the URL of the link, the second is your nonce key. Note the use of function_exists() for backwards compatability:

<?php
$link = 'your-url.php';
$link = ( function_exists('wp_nonce_url') ) ? wp_nonce_url($link, 'plugin-name-action_' . $your_object) : $link;
?>

<a href="<?php echo $link; ?>">link</a>

Nonce verification

On the backend, before performing the action protected by the nonce, simply call this:

<?php check_admin_referer('plugin-name-action_' . $your_object); ?>

Feedback and other resources

Please let me know if any of this information (especially regarding plugin nonce implementation) is incorrect and I’ll update it. You should also give Owen’s post on WordPress’ nonce implementation a read.

Written by Mark Jaquith

June 2, 2006 at 12:24 am

Posted in wordpress

75 Responses

Subscribe to comments with RSS.

  1. [...] OK, WordPress just came out with a minor upgrade the other day. I decided to go ahead and play with this one for several reasons. First, for all that this is minor, there’s a pretty good security patch to it, the “nonce” security key that reduces the chance of someone hacking their way into the admin panel. Second, a more major upgrade (2.1) is planned for the end of summer and this would be good practice before then. [...]

  2. Great post.

    Matt

    June 2, 2006 at 11:18 am

  3. [...] WP 2.0.3 Security Enhancements: Mark details out the security enhancements of WordPress 2.0.3 while paying a lot of attention to Nonces. Well written, very thorough technical post. Thanks a bunch Mark! Technorati Tags: nonces wordpress 2.0.3   Related Posts from the Past: [...]

  4. Blathering:

    The format for the nonce action names you describe is worth following: verb-noun_object (like delete-post_100 or cool-plugin-update-options_advanced). It may seem pointless now, but future versions of WordPress may (no promises) parse the action name to make the “Are You Sure” message more informative.

    Perhaps plugin:verb-noun_object should be encouraged (cool-plugin:update-options_advanced). However, without anything even resembling a guarantee that the action names will be processed like this, it’s not worth starting a campaign.

    mdawaffe

    June 2, 2006 at 4:36 pm

  5. Excellent post Mark, but there is one more thing:

    Correct me if I’m wrong but,

    So even if you got a nonce used to delete a post, the absolute worst case scenario is that you might be able to trick me into deleting that specific post. The nonce is useless for any other purpose.

    Isn’t the only way you could get a nonce be if you carried out an action? I mean, in order to retrieve the nonce key in the first place, you’d have to have already had deleted the post in question by your intention, and as such, the best one can do would be to trick you into deleting that post again – except it’s already gone?

    Not sure if that made too much sense….
    -CG

    Computer Guru

    June 3, 2006 at 12:48 am

  6. CG,
    The nonce is provided in the previous load, during which the action might or might not take place. For instance, when you open up a post for editing, you get the deletion nonce for that post, so if it was intercepted downstream, it could be used, even when you didn’t intend to use it. But consider that if people are intercepting your Internet traffic, they’d be better off just grabbing your authentication cookie.

    The different ways that a hacker might get their hands on a nonce might not be known. But in the event that it does, somehow, happen… the effects will be limited to a specific blog, a specific user, a specific action, a specific object, and a specific time period. And also, keep in mind that getting a nonce is only half of the puzzle, if you’re a hacker… you also need to mount a CSF attack whereby you trick that specific user on that specific blog into visiting your malicious link/form. And you only have 12 to 24 hours in which to do so.

    The prize generally sucks, the attack must be manual, and it relies on social engineering to succeed. And as of right now, there isn’t even a known way to intercept a nonce.

    Mark Jaquith

    June 3, 2006 at 4:35 am

  7. Protegiendo WordPress 2.0.3

    Hoy he encontrado una página web donde nos dan unas pequeñas instrucciones sobre las mejoras de seguridad qeu se han lelvado a cabo en esta última actualización de este sistema de publicación que, recientemente, sobrepaso los 200.000 blogs creados…

    kakoky.net

    June 5, 2006 at 6:09 pm

  8. il mio sistema d’allarme

    È sempre spiacevole ricevere una visita non gradita, specialmente se l’ospite ha la tipica mascherina nera, un sacco sulle spalle, ed una calzamaglia tutta nera. A me è successo nella vita reale, e non lo augurerei al mio peggior nemico: sapere…

    due chiacchiere

    July 1, 2006 at 5:05 am

  9. Thanks a ton for this. :D

    Viper007Bond

    July 7, 2006 at 7:00 pm

  10. [...] What’s in WordPress 2.0.3? (Nonces) [...]

  11. Small problem… “Nonce” in UK English means s*x offender or p*dophile.

    polyxena

    July 19, 2006 at 12:30 pm

  12. Yeah, we considered that but decided we didn’t care.

    Mark Jaquith

    July 19, 2006 at 1:12 pm

  13. [...] What’s in WordPress 2.0.3? (Nonces) [...]

  14. [...] applies not only to WordPress but plugins so plugin authors take note of nonces. Mark Jaiquith has more on nonces and how to use them. He details the specific implementation in a way my grandmother (who is dead) could understand. In [...]

  15. [...] stato ripreso l’utilizzo, introdotto nella 2.0.3, dei nonces: sono delle password inserite nelle email di moderazione dei commenti che permettono ad una [...]

  16. [...] Using nonces in [...]

  17. Great idea, shame about the name!

    Ben XO

    January 22, 2007 at 6:28 am

  18. WordPress 2.0.3: Nonces « Mark on WordPress

    geat tool for verification and authentication of user intent.  nonces.

    Stickiing around

    January 22, 2007 at 12:39 pm

  19. This is totally not working for me. I have the wp_nonce_field() function working correctly in my , looking at the source code. The problem is when I click the Submit button.

    Presumably, if the nonce is working correctly, the action should be performed without any further user intervention. What I get instead is the WP admin header, followed by this message:

    Warning: Cannot modify header information - headers already sent by (output started at C:\Documents and Settings\joepan\My Documents\Developer\wpdev\wp-admin\admin-header.php:16) in C:\Documents and Settings\joepan\My Documents\Developer\wpdev\wp-includes\functions.php on line 1219

    After that, there is the “Are you sure you want to do this?” confirmation message.

    The code for my action handling currently looks like this:

    // Clear logs if told to
    if ($_POST['lumberjack_logviewer_action'] == 'Clear logs') {
    check_admin_referer('clear-logs');
    $query = "TRUNCATE TABLE `$lumberjack_logs_table`";
    $lumberjack_db->query($query);
    ?>

    What am I not doing correctly? This is in WP 2.1.

    ketsugi

    January 23, 2007 at 12:00 am

  20. Part of my code got cut off there, because of HTML markup, but the code excerpt should be enough and I assure you the problem has nothing to do with parsing errors or any other such thing. It works fine without the check_admin_referer() function call.

    ketsugi

    January 23, 2007 at 12:01 am

  21. [...] hier is een uitleg van Mark en in het kort: …nonces are unique “passwords” embedded in the comment moderation emails, [...]

  22. [...] de kullanımı WordPress geliştiricileri tarafından tavsiye ediliyor (detaylı bilgiye buradan [...]

  23. [...] sparse. The same goes for the nonce functionality, introduced in 2.0.3, for which I can only find one tutorial on the web detailing its usage, and no official [...]

  24. [...] WordPress nonce functionality to improve admin menu [...]

  25. [...] Entendi que são itens de segurança, que estão disponíveis desde o WordPress 2.0.3, e parei aí. Há um texto aparentemente mais completo sobre o assunto, inclusive recomendado pelo Brazell, mas que não me ajudou muito… Enfim, quem souber, ou [...]

  26. Can someone help me out here? I was expecting that if the ‘unique string’ passed from the form to the processing of that form was different then the update would somehow be stopped for a check to be made. But no matter what I pass in either function – no identical characters whatsoever – my update proceeds untouched every time. Is that right?

    Andy

    February 9, 2007 at 10:10 am

  27. Hi Mark,
    Is it necessary that to create wp_nonce_field when we are creating a plugin for administrator or is it purely optional ? I’m trying to use wp_redirect, which results always is headers already sent refering to admin-header.php and pluggable-functions.php

    Sai Krishna

    February 20, 2007 at 3:59 am

  28. Im using wordpress 2.0.5

    Sai Krishna

    February 20, 2007 at 4:01 am

  29. [...] WordPress nonce added to admin pages to improve security [...]

  30. [...] contains 2 lines of change, but still worths it, since these 2 lines add a bit of security using nonce — which is basically a random number designed to forbid direct submission of form without [...]

  31. [...] WordPress Nonces [...]

  32. big pizza sausage trinity
    big pizza sausage trinity

    Lyhouxox

    October 4, 2007 at 11:11 pm

  33. Great post!!!
    Im using wordpress 2.2.3
    http://soundproducer.blogspot.com/

    pharmamaster

    October 5, 2007 at 8:49 am

  34. no rx valium
    no rx valium

    Cavojpop

    October 5, 2007 at 2:08 pm

  35. [...] really nice article by Leonid Mamchenkov on how to make options pages for WordPress plugins, and this piece by Mark Jaquith on how to make such things more [...]

  36. generic l441 xanax
    generic l441 xanax

    Ruvoqxox

    October 15, 2007 at 12:52 pm

  37. You should write another post like this about the newest WordPress release.

    Ryan

  38. [...] Explicación Debido a la falta de sanitización de la variable: “dean_pm_config[’oldstructure’]” es posible inyectar código malicioso (XSS), aunque esta cuenta con unos filtros estos no están ni por un poco preparados para sanitizar de manera adecuada la información que se piensa guardar, lo cual nos lleva a la posibilidad de inyectar código malicioso (XSS) dentro de esta misma. Sin embargo para que esto funcione se requiere que el usuario inyecte el código malicioso (XSS), lo cual se puede lograr diseñando una pagina maliciosa para hacer que el usuario realice esta acción sin darse darse cuenta (XSRF) el cual es posible debido a que el plugin no hace uso de las funciones para proteger formularios incluidas en WordPress (WP-Nonces). [...]

  39. [...] WordPress 2.0.3: Nonces Artikel #539, 31. Januar 2008 · Code, PHP, Tipps, WordPress · 0 Kommentare Tags: Code, Entwicklung, PHP, Plugin, Sicherheit, WordPress, WP Gelesen: 6 · heute: 6 · zuletzt: 31. Jan 08, 14:00 Kommentar-Feed zum Artikel, TrackBack URL Hinzufügen zu: Technorati, del.icio.us, Mr. Wong, LinkARENA, SEOigg [...]

  40. [...] guards against CSRF attacks in general by confirming actions that don’t seem quite right (i.e. when the nonces don’t check out), but this attack hides all of the confirmation message except the approval button, which appears [...]

  41. [...] Added nonce security. [...]

  42. [...] Cross-Site Request Forgeries (CSRF).  We tackled this security issue in WordPress two years ago.  I wrote an article about the issue that still holds true (plugin authors should definitely give it a read if any of [...]

  43. [...] Upgrade plugin is an unnecessary precaution, I am puzzled why it did not work.  According to Mark’s post on nounces, it sounds like in theory this "number use ounce" should still be valid if you [...]

  44. [...] Improved security via nonces [...]

  45. [...] flexible), but it can be a curse if your plugin is not code with security in mind. If things like CSRF, the prepare() method (SQL injection protection), XSS are not intimately known to you, it’s [...]

  46. Yeah, great idea, shame about the name! Good job!

    Gry Logiczne

    September 21, 2008 at 11:05 am

  47. Look at my website about photoes.

    Gry Logiczne

    September 24, 2008 at 10:43 am

  48. Look at my website about photoes, zdjęcia.

    zdjęcia

    September 24, 2008 at 10:44 am

  49. great job! thx :)

    gry dla dziewczyn

    December 1, 2008 at 8:59 am

  50. Very good!

    gry

    December 1, 2008 at 9:00 am

  51. thanks man , i needed this tutorial and it really helped

    bootcat

    December 7, 2008 at 3:47 am

  52. apuestas payout on net…

    secretive Karl hotels hitch intermingles …

    apuestas payout on net

    December 7, 2008 at 7:22 pm

  53. affordable driver insurance young dr quotes and rates direct reciprocalgroup company jaguar xkr…

    waking interrogates materially Tarrytown flock …

  54. Mark — your link to Owen’s article on nonces is broken. I found the article here: http://asymptomatic.net/2006/06/01/365/what-is-all-this-nonce-sense

    Frank Geshwind

    February 22, 2009 at 6:02 pm

  55. [...] 2.1.3 fixes issue with extra slashes being added. Also adds Nonce support for extra [...]

  56. شرکت مهندسی حارس هوشمند با فعالیت در زمینه امنیت اطلاعات و ارتباطات و همچنین حفاظت الکترونیک بازوی کمکی حراست ها و تولید کننده نرم افزار کنترل مراجعین می باشد.

    Reza

    April 12, 2009 at 2:55 am

  57. [...] No NONCEs This is such an offensive mistake it makes me cry a little. As I(and Mark Jaquith and Vladimir Prelovac and many others) have written, using nonces is a must for any plugin which [...]

  58. [...] 2.1.3 fixes issue with extra slashes being added. Also adds Nonce support for extra [...]

  59. “This is authentication: verifying that the person performing an admin action is authorized to do it”

    IMHO, this is authorization. Authentication is about making sure you are the one you claim to be.

    My .02€

    Greg

    September 1, 2009 at 7:42 am

  60. TOUR717> Все путешествия начинаются отсюдаTOUR717 – делится самой полной информацией о всех музеях, достопримечательностях, церквях и соборах, дворцах всех самых изумительных городов Европы.

    Николай

    September 15, 2009 at 8:55 am

  61. [...] Mark Jaquith – WordPress Nonces [...]

  62. Hi Mark,

    I looked around google and the wp docs and forums for information regarding nonce in theme options pages, but I only seem to find information regarding nonce in plugin nonce pages.

    I have added the question to the wp forum, but I guess nobody knows the answer or don’t care, as nobody has replied yet, so I was wondering if you could shed some light on the subject. Is it required for security and if so, do you know of any tutorials regarding this?

    Cheers,
    Olaf

    Olaf

    October 8, 2009 at 7:25 am

  63. [...] the script. This stops you from being tricked into doing something you don’t want to. You can read more about nonces from Mark [...]

  64. Дневник ПутешественникаМир находящийся вокруг нас настолько прекрасен что все время хочется посмотреть а чтоже есть еще на свете.

    Артем

    October 22, 2009 at 2:10 am

  65. [...] the script. This stops you from being tricked into doing something you don’t want to. You can read more about nonces from Mark [...]

  66. I’ve just started developing (reading a lot about WP plugin development, best practices and Twitter API) a Twitter plugin. This post is one of the best I’ve read pointing out security issues!

    Thank you!

    WebDev

    October 30, 2009 at 3:46 pm

  67. This post is clear and helped me out. Thank you.

    Justin

    November 17, 2009 at 1:31 pm

  68. I hate to nit pick, but its the Standards editor in me. In the realm of software security the terms authentication and authorization have specific meanings and are not interchangable (as your article suggests in the first paragraph). If you weren’t providing a widely quoted introduction to WordPress security and instead were just mentioning this in passing, then I wouldn’t bring it up. But since you have the attentive ears of people who want to learn, then I feel compelled to correct the mistakes so that others don’t learn mistakes.

    Authentication is the process of proving your identity. This is typically done with providing some secret (e.g. a password) that should only be known by the individual in question. In well secured systems, not even the system knows this secret. Unix, for example saves a hash of the password so its authentication system really only compares a hash of the password supplied with what it has on record.

    Authorization is the process of determining if you have the permissions to request what you have asked the system to do. For example, being able to update the settings in WordPress will require WordPress first determine what priviledges are required for this action and then determine if you have those priviledges (this is authorization).

    I’ll stop here because this reply is getting too long, but its important to get these fundamental concepts straight so that you (and your readers) are using the accepted nomenclature of software security.

    Brenton

    November 17, 2009 at 10:23 pm

  69. Промышленные полы на сегодняшний день являются лучшим решением в промышленном строительстве. Там мы можем применить также и наливные полы.

    Мак Сим

    November 21, 2009 at 4:45 am


Leave a Reply