About me

Welcome to my little piece of the web and yeah, that’s my crazy face… This is where I share some of my experiences and tools about business, marketing and the web to help you start your very own business on your journey to freedom and happiness.Keep on reading

Find me here

How Do WordPress Nonces Work. Really.

WordPress nonces are an easy piece of security measure you can implement into your plugins or themes to prevent your users from Cross Site Request Forgery attacks. But how do WordPress nonces really work? You heard they were valid for 24 hours? Are they really? How can they be called nonces if they can be reused?

Let’s dive right into in and see how WordPress nonces are not pure nonces but still are useful to provide an higher level of security to your website’s users.

What is a Nonce?

A nonce simply stands for a Number used ONCE. It’s a unique token used to add a layer of security to your application and also to validate the intent of a user initiated action.

This Nonce is generated by a server-side application, stored on the server and sent to the client to be part of the payload it’s going to send back to the server. This way, you have a way to validate the payload and have a higher level of certainty that the request was actually made by the client.

Why use a Nonce?

A nonce could be seen as a one time password for user initiated actions. May it be sending a form, encrypting data or executing an action, the nonce adds a level of security by preventing a malicious script sending forged requests to your application. This is called Cross Site Request Forgery ( CSRF or XSRF ) and malicious scripts use this method to send requests on your server in a way that you have not intended to. This can have important consequences depending on what your script is used for.

An example of this is an attacker putting up a script on his website that POST to a form on your website automatically on an authenticated user session without the user really wanting to do that specific action. That was a mouthful! In other words, an attacker disguising a link to your authenticated user doing something (potentially bad) that the user never intended to do. So if your form doesn’t contain a nonce, then there is not much that prevents an attacker to flood bad data in your database, potentially bringing down your whole site or worse, costing you or your users to lose money or to leak private information. If your form contains a nonce, then the POST would not go through since the nonce would not be able to be validate positively coming really coming from that user. It would not satisfy the intent part of the request.

This example includes forms as it’s an easy target for CSRF, but really, any requests made to a server that a script is listening for is vulnerable to CSRF if no precaution are taken to prevent it.

Breaking down the process of a nonce, it should look something like this:

The server generates the unique token ( nonce ), stores it locally and passes it on to the client.

The client does it’s thing, prepares the payload and includes the nonce in it.

When the server receives the payload, it first checks if it contains a nonce, then, it will validate it by comparing it to the one stored locally. If a match can be made, the payload is considered genuine. If not, the payload should not be trusted.

After the validation returned a match, the process should invalidate ( or destroy ) the nonce for it to be a true used ONCE number.

If you properly create your nonce, CSRF should not be a problem. Since a properly formed nonce should contain at least a secret key ( like a secret salt securely stored on your server ) and a unique or at least very descriptive action as a name ( maybe including a timestamp ? ), then there is no way an attacker could recreate a valid nonce without having access to both parameters.

So a true nonce would be destroyed after it’s been validated, effectively preventing an action of being performed twice ( or multiple times ), may it be maliciously or accidentally, without being validated again by a new nonce. A nonce also prevents CSRF attacks since secret salts and other unique parameters are used to created the nonce and are not available to an attacker to replicate a fake nonce.

About WordPress Nonces Implementation

Ok, so now that we explained what a nonce is, let’s see why WordPress nonces are not true nonces.

The way WordPress implements nonces lacks the one part that makes a nonce a nonce, it’s “used ONCE” part.

WordPress creates a nonce that will remain valid for at least 12 hours by default (can be valid for up to 24 hours). This implementation in itself invalidates the definition of a true nonce because a generated nonce can be used an unlimited amount of time, within that valid period. A new one will be generated every 12 hours (UTC time), and will remain valid for a maximum of another 12 hours depending on when it was generated within the tick cycle (See graph below).

Tick tock

This brings me to talk about ticks.

Ticks are what WordPress uses, as one parameter, to create a nonce.

It is generated by the wp_nonce_tick() function used in the nonce creation process.

So what is a tick? It’s a value that changes a midnight (+1 second) and midday (+1 second) by 1 unit. So every 12 hours (UTC time).

You might have read that a WordPress nonces are valid for 24 hours, but that’s just not true. At least not entirely.

A WordPress nonce is valid for a maximum of 24 hours. Or in truer terms, it is valid for the current tick’s value and the previous one.

But since a tick changes every 12 hours, a nonce will only truly be valid for 24 hours if it’s created at the beginning of the tick, specifically, at hour 0:00:01 or 12:00:01. The more you advance towards the end of the current tick, the shorter the lifespan of the nonce will be (or closer to a lifespan of 12 hours).

As you can see in the graph, a nonce created within the end of a tick, will have a shorter lifespan than a one created towards the beginning. This is because a wp nonce is generated with that tick’s value as one of it’s parameters. If we look at how wp_verify_nonce() verifies a nonce, we’ll see that it checks the current tick value, and the previous one (tick – 1). If the wp nonce is verified close to 24 hours later and it was created deeper within the cycle of the tick, then the nonce would be 2 ticks behind, failing the verification.

On the graph, only NONCE 1, 13 and 25 will be valid for close to 24 hours, assuming they are generated at the beginning of the hours not the end of it.

I agree that in reality, this should not be that much of an issue, since nonce should be used relatively quickly after their creation to verify actions/requests.

But it’s a misconception thinking that WordPress nonces are valid for 24 hours, when in reality, we should say they are valid for 2 ticks or for a maximum of 24 hours.

And it’s not a good idea to rely on WordPress nonces to validate an action that could take more than 12 hours for a user to actually request. Since the nonce will become invalid anywhere between 12 and 24 hours, chances are that the nonce validation would fail and results in unexpected behaviours

WordPress Nonces hooks

Invalidating WordPress Nonces

Like I discussed above, nonces will auto expire in maximum 24 hours after they’ve been created.

But I prefer to say, they will auto expire 2 ticks from now.

The other way a nonce can become invalid is if a user’s session token changes. That state change occurs when a user logs out and back in again. Since a new session token is generated, all previous nonces won’t validate anymore.

To make things clearer, WordPress doesn’t store the nonce it creates for a user. Instead, it stores the session token and will use it to rehash a nonce upon validation. If the session has not changed and the nonce is still within the 2 ticks valid period, then the submitted nonce and the rehashed one will match. Of course, like I just told you, if either the current tick is 2 or greater than the one used to create the nonce or the session token changes, then the nonce is invalid.

Security Concerns

WordPress not offering true nonces doesn’t mean you should not implement it within your application. It’s still useful to prevent CSRF.

But you should not rely on nonces to securely allow actions that should be restricted to specific users or users roles within your WordPress installation.

Your scripts should only allow such actions for users with the right capabilities (permissions) to do so.

Here, your best tool to use is current_user_can() and wrap your functions within this check.

Remember that nonces will tell you that the payload is from a genuine source (user), but it does not tell you if that source has sufficient permission to actually execute the payload.

This should be taken care of by another process, thus checking against capabilities.

Using WordPress Nonces

Ok, let’s give you a few example to show you how easy it is to implement a nonce in your code.

wp_create_nonce()

The first one is a general usage function, meaning you can use the created nonce anywhere you would like.

The function takes 1 parameter, the $action name (optional) and returns the nonce for you to use.

While the action name is optional, it is recommended to supply one as specific to the action as possible. This will prevent a user having the same nonce for 2 different actions. For instance, deleting a custom post type and sending an email.

So let’s say I have a plugin that sends email to my users. The user I want to send an email to is stored in $send_to_id. I will then pass that user id value in the request so I can used again when I’ll be verifying the nonce.

Again, while optional, it is recommended to provide better security, to set a custom and specific $action value and a custom $name for the field. The value of $name will be the name of the field what you will use to retrieve the value of the created nonce in your request ( $_REQUEST, $_POST or $_GET ).

The $referer parameter outputs a second hidden field with the name _wp_http_referer containing the value of the referrer URL as found in the 'REQUEST_URI' element of the $_SERVER PHP superglobal variable, unless it is set to false.

Finally, the wp_nonce_fields() function prints by default the field, but if you set $echo to false the function will return it so you can use it within PHP.

So, reusing the same sending email example as above, creating the nonce and outputting the nonce and referrer fields using this function is as simple as

wp_verify_nonce()

Once you have created your nonce, and used it, you need a way to verify it. Your general goto function to complete this will be wp_verify_nonce().

This function takes in 2 parameters, the first one, $nonce is required and is the actual value of the nonce. The second one, $action is optional, but you will need to provide it if you used an action name when creating your nonce. Remember that action names are recommended practice.

So let’s see how to use the function, still using our send email example.

Since wp_verify_nonce() will return 1 if the nonce was generated within the current tick value and 2 if the nonce was generated in the previous tick value. Then you could do different stuff based on when the nonce was generated.

check_admin_referer()

Another function you can use to verify a nonce is check_admin_referer(). While the name is improper and may be misleading, it is still kept for backward compatibility. Also, know that using this function without providing an $action is obsolete since version 3.2.

So basically, this function now behaves the same as wp_verify_nonce()except it will die calling the wp_nonce_ays() function which display the Are you sure? message.

WordPress True Nonce

While implementing your nonce methods could be relatively easy to implement, why reinvent the wheel when you could start of by using what’s done already! There’s a repo on github called wp-simple-nonce that works just fine and will bring you true nonce for you to implement in your application.

While WordPress nonces implementation is good to prevent CSRF, it is not very useful to prevent multiple submission of the same data, which is often a reason to implement nonces within your application. This is why you might want to take a look at WP Simple Nonce

Wrap up

I hope you found this post constructive, if you have questions, comments or concerns, let me know by commenting below!

Want more?

bynicolas.com runs on the Genesis Framework

The Genesis Framework empowers you to quickly and easily build incredible websites with WordPress. Whether you're a novice or advanced developer, Genesis provides the secure and search-engine-optimized foundation that takes WordPress to places you never thought it could go. It's really that simple - start using the Genesis Framework now!

Take advantage of the 6 default layout options, comprehensive SEO settings, rock-solid security, flexible theme options, cool custom widgets, custom design hooks, and a huge selection of child themes ("skins") that make your site look the way you want it to. With automatic theme updates and world-class support included, Genesis is the smart choice for your WordPress website or blog.

Comments

Thanks for the great article! if a want to generate a new page (new URL) should I use a nonce? I think I should but the nonce returns false if I’m not logged in. My purpose is others can view the new URL without logging in. Thanks a lot in advance!

WP NONCES are mainly used to protect (logged in) users from CSRF by providing the user with an unique link on (more critical) actions to prevent a man in the middle attack (i.e. replacing a link with a fraudulent one). An attacker wouldn’t be able to recreate the nonce without knowing the WordPress salt.

Hi, Thanks for your fast respond, What I’m trying to do is to create a new page with a new link (it will expire when I decide, but I’m taking care of that), so so far I think I don’t need any nonce, right?! The problem is I’m getting a warning: Processing form data without nonce verification

Well are what kind of form are you POSTing? You are using WP nonces for logged in users right? Again, I can’t be sure for your specific use case but you might need to use WP nonces to protect your users.

So maybe your false validation comes from you using the wrong parameters to validate the nonces.

Double check that to make sure you are validating against the correct nonces parameters

I’m sure I’m using the right parameters, I’m checking them with a different case and it’s working well. I’ll try to be more specific: I need my URL that I’m creating to be shown everywhere, also when users are not logged in, and for many users at once. What I’m checking is That the URL is not expired and so on… these parameters, that I want to check are passed in the URL so my code uses $_GET to check it, and this is where the warning comes from, on the other hand, if I use nonce if seems to block some users. Was I clear? Does this make sense?

If you need to validate URL that is time sensitive, then I would suggest you implement a custom validation mechanism. What you want is a validation key and Nonces by definition are ment to be used once. So as I understand it, your link will be valid until your key is valid, once you invalidate your key, the link cannot be used anymore. So you would need to generate a unique key and store it in a table, then write some validation code to check the link against the key within your table.

When you create a wp_nonce, you tell the user that the link comes from the current site (because it’s hashed using the SALT found in wp-config.php). If a malicious script would try to access the url, it wouldn’t know the salt and couldn’t recreate a valid WPnonce.

As I said, if you wish to give access to a url based on a valid timeframe, you would need to code something specific for your use case and generate some unique key that would be stored in your database.

Then you could invalidate a key after n hours pretty easily and this would allow you to share the link with anyone without a problem