WordPress 2.0.3: Nonces
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.
[...] 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. [...]
Great post.
[...] 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: [...]
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.
Excellent post Mark, but there is one more thing:
Correct me if I’m wrong but,
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
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.
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…
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…
[...] What’s in WordPress 2.0.3? (Nonces) [...]
Thanks a ton for this.
[...] What’s in WordPress 2.0.3? (Nonces) [...]
Small problem… “Nonce” in UK English means s*x offender or p*dophile.
Yeah, we considered that but decided we didn’t care.
[...] What’s in WordPress 2.0.3? (Nonces) [...]
[...] 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 [...]
[...] 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 [...]
[...] Using nonces in [...]
Great idea, shame about the name!
WordPress 2.0.3: Nonces « Mark on WordPress
geat tool for verification and authentication of user intent. nonces.
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 1219After 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.
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.[...] hier is een uitleg van Mark en in het kort: …nonces are unique “passwords” embedded in the comment moderation emails, [...]
[...] de kullanımı WordPress geliştiricileri tarafından tavsiye ediliyor (detaylı bilgiye buradan [...]
[...] 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 [...]
[...] WordPress nonce functionality to improve admin menu [...]
[...] 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 [...]
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?
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
Im using wordpress 2.0.5
[...] WordPress nonce added to admin pages to improve security [...]
[...] http://markjaquith.wordpress.com/2006/06/02/wordpress-203-nonces/ [...]
[...] 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 [...]
[...] http://markjaquith.wordpress.com/2006/06/02/wordpress-203-nonces/ [...]
[...] WordPress Nonces [...]
[...] http://markjaquith.wordpress.com/2006/06/02/wordpress-203-nonces/ http://www.wordpress.com [...]
big pizza sausage trinity
big pizza sausage trinity
Great post!!!
Im using wordpress 2.2.3
http://soundproducer.blogspot.com/
no rx valium
no rx valium
[...] 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 [...]
generic l441 xanax
generic l441 xanax
You should write another post like this about the newest WordPress release.
Ryan
[...] 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). [...]
[...] 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 [...]
[...] 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 [...]
[...] Added nonce security. [...]
[...] 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 [...]
[...] 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 [...]