An Introduction to WordPress Nonces with Examples
WordPress security is a topic we take very seriously and a little too literally. WordPress itself isn’t the problem, in fact, the issues most users face with security are the result of faults in everything we add to it.
One of the most widely used methods of prevention against a range of potential security threats is by employing nonces. Nonces have a simple functionality: to protect all user actions that are initiated by a plugin.
In this article, we’ll give you a good introduction to WordPress nonces so that you can get an understanding of what they do and why you might want to pay more attention to them in the future. We’ll also take a look at a practical example so you can get a real life example of how they can be used.
Let’s get started.
An Introduction to WordPress Nonces
WordPress itself defines nonces as “a ‘number used once’ to help protect URLs and forms from certain types of misuse, malicious or otherwise.” If you understood that definition right off the bat then it’s safe to assume you’re knowledgeable in programming and have implemented something similar yourself.
For those of you who didn’t get it (don’t worry, it took me a while to fully understand it too) it basically means that a nonce is an identification value that a user needs to show in order to authenticate their user permission before they can carry out any user action.
What Do Nonces Look Like
According to their definition, a nonce is a number. Although this may be accurate in other implementations of nonces, in the world of WordPress nonces are hash values made up of a combination of numbers and letters. This makes them more secure than regular nonces.
Despite these two major differences in implementation from regular nonces, we refer to these WordPress security tokens as WordPress nonces because the basic principle behind them is the same.
Why Do We Need Nonces
Nonces protect WordPress sites against malicious exploits that are based primarily on Cross Site Request Forgery (CSRF). This technique of hacking involves transmitting unauthorized commands from a user that the website trusts.
Let’s look at an example in our attempt to understand CSRF attacks better. Say, for example, there is a malicious person who wants to populate your database with useless data to overload it. If you have a contact form on your site (as most of us do) that isn’t protected with nonces (as most of them aren’t…yet), the malicious attacker can write a simple PHP script to POST on your site’s contact form.
They would create and post a link in a popular forum to have as many people click on it as possible. Every time a user clicks on the link, your contact form is filled with spam. Storing excess amounts of garbage data in your database can quickly overload it and cause harm to the performance of your WordPress site.
Now stop for a minute and actually think about this. A person who can successfully undertake a mission like this could also have the ability to delete important content from your site, create/remove user accounts, and even initiate transactions.
These WordPress security attacks are common and WordPress nonces are there to ensure something like this doesn’t happen to your site. This is achieved by adding an extra layer of security. A URL with a nonce implementation would look like this in the scenario for removing the account of the user with:
Since the nonce will always be different it becomes virtually impossible for anyone to guess the correct value of the nonce.
How Do Nonces Work
Most webmasters are unaware that nonces are used widely in the core functionality of WordPress. Nonces are hash values and as is the case with other such variables, nonces have some properties that are specific to their functionality.
Lifetime of Nonces
WordPress nonces have a limited lifetime that the website admin specifies. The nonces expire once their lifetime is over and they cannot be used to perform the user action they were defined for. By default, the validity value of a nonce is 24 hours.
User Specific Nature of Nonces
What if a malicious user taps into the HTML source of a WordPress site and identifies the nonce field? Technically, they could add it to their custom URL. Couldn’t they? As luck would have it, this won’t work because WordPress nonces are unique to the session of the currently active user. This means that the nonces on a page won’t be valid if a user logs in and out of their WordPress site asynchronously. Pretty cool, right?
Let’s go through another example to understand the functionality of WordPress nonces.
Suppose you’ve implemented nonces on your WordPress site to increase security and prevent potential CSRF attacks on your team member’s and employees’ user accounts. Deleting an account from the site’s back-end is a common user action that can be programmed to work through the site’s front-end by manipulating the relevant URL.
In this particular case, let’s suppose that your admin screen generates a URL for the user action by which an admin removes a user and appends a nonce at the end of it. It might look something like this:
Now, if a malicious user tries to enforce a CSRF attack by replacing the user’s ID with another value, say,
user=5 the nonce would be invalid and the user action would fail.
In such a scenario, WordPress displays a 403 Forbidden response to the malicious user’s browser with an error message that reads “Are you sure you want to do this?” Nonces make it practically impossible for malicious users or hackers to tamper with your site’s content or purposefully attempt to cause it harm by removing content.
Now that we’ve covered the basics of nonces, let’s take a look at how we would go about implementing them in WordPress. But first a quick note on CSRF attacks.
Cross Site Request Forgery
Cross site request forgery (CSRF) attacks are one of the most common malicious exploits of websites. The biggest issue with it is that the attack is carried out from the unwitting user’s own IP address which makes it more difficult to trace.
CSRF attacks are designed to perform some sort of action, not steal data as is common with other such attacks. Attackers that come across reproducible URLs that are associated with specific user actions use them to trick the administrator into causing their own site harm.
The process is quite simple once the attacker acquires the link and modifies it. All he has to do is place the link in a source trusted by the website admin and make sure it’s clicked when the site’s admin is logged into their account. Generally, these links are sent through emails under false pretenses such as reporting a broken link or updating facts.
CSRF attacks on WordPress sites can be used to:
- Delete posts from the back-end.
- Remove user accounts permanently.
- Submit bogus values in WordPress forms.
- Tampering with the database values through other user actions.
Implementing WordPress Nonces
Using WordPress nonces is quite simple and you’ll only have to familiarize yourself with a few easy formulas. All you have to do is create it and add it to either a URL or a form and then verify it at the target. Without further ado, let’s begin!
Adding Nonces to URLs
If you’d like to initiate some specific user action through URLs to simplify the process for yourself in the future, adding a nonce is absolutely necessary to prevent malicious attacks. Typically, nonces are passed as query arguments to functions and passing them on (transmitting them) through URLs is entirely possible as well.
Granted this makes the value of the nonce visible in the link but as we discussed above, nonces are specific to user sessions and would be useless to anyone who manages to figure out its value.
To add nonces to URLs, we’ll use the
wp_nonce_url() function and pass the bare URL and a string that denotes the user action as arguments. The string should be as specific to the actual user action as possible to ensure maximum security. For instance, if you wanted to add a nonce for deleting a user from your site you could name it
$complete_url = wp_nonce_url( $bare_url, 'delete-user_'.$user->ID );
By default, WordPress names your nonce
_wpnonce. This is also visible in the URL which you’ll have to remember later on. To improve security even more, you can use the following function call instead to assign a custom nonce variable.
$complete_url = wp_nonce_url( $bare_url, 'delete-user_'.$user->ID, ‘my_nonces’ );
This code will create a URL that might look something like this:
Adding Nonces to Forms
Adding nonces to WordPress forms creates hidden fields for you on the form automatically. The user has to call the function
wp_nonce_field() and pass a string that denotes the user action as an argument. The function will generate two hidden fields:
- The first field’s value is the nonce.
- The second field’s value is the current URL (the referer).
wp_nonce_field( 'remove-comment_'.$comment_id );
This function call will echo something like this:
<input type="hidden" id="_wpnonce" name="_wpnonce" value="807d8877c2" />
<input type="hidden" name="_wp_http_referer" value="/wp-admin/edit-comments.php" />
The function can also be modified to display a different nonce name (similar to what we did above), remove the referer field and have the result be returned instead of being echoed. It can take up to four parameters all of which are optional.
wp_nonce_field( $useraction, $noncename, $referer, $echo );
useractiondenotes the name of the user action the nonce is for.
noncenamedenotes the user-defined name of the nonce. By default it is _wpnonce.
refererholds a Boolean value which determines whether a hidden field for referer should be created or not.
echoholds a Boolean value which determines whether the result should be echoed (on true) or returned (on false).
Verifying WordPress Nonces
It’s important to verify nonces once you’ve created and added them to either URLs or forms in your WordPress site. This step ensures that our implementation and function calls are working properly. There are four ways to verify WordPress nonces and we’ll discuss the first two in the following section. You can verify nonces that were passed:
- Through a URL.
- In a form on the admin screen.
- As an AJAX request.
- In some other context.
Verifying Nonces Passed Through URLs
To verify a nonce that was created, added and passed in a URL you can use the following method:
noncedenotes the name of the nonce that you want to verify e.g. delete-user.
actiondenotes the user action that you specified at the time the nonce was created.
This function call returns false if the nonce you’re trying to verify is invalid. On the other hand, if the nonce is valid it will return either a 1 or a 2. A value equal to 1 means that the nonce was created 12 hours (or less) ago whereas 2 means that it was created more than 12 hours but less than 24 hours ago.
Verifying Nonces Passed Through Forms
In order to verify a nonce that was originally created and added to a hidden field in a WordPress form, you can employ the following method:
actiondenotes the user action that you specified at the time the nonce was created.
noncedenotes the name of the nonce that you want to verify e.g. remove-comment.
If the value of the nonce is valid, the plugin or theme executing it will continue to execute as intended. However, if the nonce isn’t verified i.e. it is invalid, the user will be redirected to a 403 Forbidden error page.
Wrapping It Up
The severity of Cross Site Request Forgery (CSRF) vulnerabilities can range from mild to dangerous and it’s vital that you take necessary measures to prevent any potential attacks on your WordPress site. Employing nonces in user actions is a surefire way to prevent CSRF attacks and make your site more secure.
We featured a quick example to show how it’s possible to leverage the power of nonces for a WordPress site and hopefully you’re in a good position now to carry out more research on these procedures and perhaps take things further or at least talk about this topic more confidently.
Can you think of any other ways nonces can be used to increase your WordPress site’s security? How do you keep your site secure from malicious attacks? Let us know in the comments section below.
Article thumbnail image by Dooder / shutterstock.com