WordPress caching and nonce lifespan

Mike Green
Jun 18, 2012 · 4 min read
Image for post
Image for post

A security feature available in WordPress is a “nonce”. Generally, a “nonce” is a token that can only be used once and are often used to prevent unauthorised people from submitting data on behalf of another person. Let’s simplify that:

  • Person A is given nonce “A”
  • Person B is given nonce “B”
  • Person B attempts to submit data to the server on behalf of person A
  • The server reads the submitted data from person B as “Person A with nonce ‘B’ is submitting data”. Knowing that Person A does not have nonce ‘B’, it ignores/denies the submitted data.

WordPress differs by giving it a lifespan and allowing the nonce to be used more than once within that lifespan by the same person. And by the ‘same person’ it is meant a logged in WordPress user, or an anonymous user (visitor not logged in).

The benefit is that the server does not need to keep track what nonce it has given to any particular user. It just needs to know the user returning the nonce and the current time; based on that information, it creates another nonce and checks if it matches the one returned.

As time varies, WordPress needs to allow for a nonce generated at 10:01 AM to be valid at 10:02 AM. It does this by using a time “tick” instead of the actual time, which is generated in two steps:

  1. First divide the lifespan of a nonce, in seconds, by two
  2. Divide the Unix timestamp by the above value, and round it up using ceil()

By default, the lifespan is 86400 seconds, or 24 hours (and can be adjusted with the nonce_life filter). Half this, 12 hours, is 43200.

So at 10:01 AM on 18/06/2012, the Unix timestamp is 1340031660. Dividing that by 43200, rounded we get 31019. A minute later (10:02 AM), the timestamp is 1340031720. Dividing and rounding, we also end up with 31019. In fact, for the first 12 hours of the day this value will be the resulting “tick”.

The reason WordPress divides the timespan in two, is that it can determine if a nonce was created in the first or second half of its full lifespan, simply by incrementing a “tick” by one.

Based on a 24-hour lifespan, a “tick” as calculated above is the same for each 12-hour span of a day. At 07:45 AM the “tick” is the same as 9:30 AM and 11:59 AM. But it will be one less than a “tick” created at 12:01 PM (a new 12-hour span within the day) or 15:30 PM.

Because of this, a WordPress nonce is not valid for exactly 24-hours from the moment that it was created, but up to 24 hours, depending how far into a 12-hour period a nonce was created.

Nonces can also be used on the “public” side of WordPress, and can help reduce abuse of data submissions. My WordPress plugins use this, as do some others like Contact Form 7.

As a nonce is often added as a (hidden) form element or using JavaScript, this means that it will also end up being cached by a WordPress plugin such as WP Super Cache or W3 Total Cache. This can cause some issues with nonce verification.

The main issue is how long a page is cached and how most caching plugins determine the age of a cached page. As mentioned earlier, a nonce “tick” is not valid for exactly 24 hours. On the other hand, the age of a cached page is determined from when it was first cached. So if a page is cached for 24 hours (or more), it allows the possibility for a nonce to expire and thus become invalid.

For example: a page is cached at 10:01 AM on 18/06/2012. The “tick” of used for the nonce at this time was 31019. 24 hours from that time, at 10:01 AM on 19/06/2012, the server calculates a “tick” to be 31021. But as the cached nonce was based on a “tick” of 31019, any attempt to use it for data submission would fail.

To avoid this, a page should be cached for at most 12 hours, provided the life-span for a nonce has not been changed from its default 24 hours. The author of WP Super Cache also provides an alternative solution, though that may not be a suitable solution in all cases (ie., in AJAX that uses nonce on all pages).

In WP Super Cache’s case, by default a cached page becomes stale after an hour, which is well less than the 12 hours. But for the stale page to be refreshed using its Garbage Collection feature (see the Advanced tab), the collection has to be done in time as well. For instance, if the cached page has become stale after an hour, but garbage collection is done every 24 hours, the stale page will still be used for up to 23 hours.

This is further complicated because the WordPress Cron (the scheduler for performing tasks) usually checks its schedule whenever a visitor accesses the website. On low-traffic websites, this could give large variations between the scheduled time versus actual time a task is performed (such as the garbage collection). In these instances, it would make better sense to use a UNIX Cron Job to call wp-cron.php, or to reduce the garbage collection time as much as possible.

Myatu’s

Myatu’s Tech Blog, from the site that has been wasting bits…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store