Cryptography: What is a Nonce ???

What Is A Nonce?

Bender from Futurama spray painting binary code graffiti

The term ‘nonce’ is one you are likely to hear when reading about web application security. It also is a term used incorrectly by WordPress.

Historically, a ‘nonce’ is a word created for a single occasion to solve an immediate communication problem. Both parties know what it refers to but do not know an existing word in their lexicon to use to refer to it, so they make up a word to use to refer to it so they can communicate about it.

In Cryptography, the term I suspect is related to the historic use because there are some parallels, but the defined meaning is “Number used only Once”.

There are two types of nonces. Once type is used when creating a cypher text. The secret (sometimes called the encryption key) is used repeatedly but the nonce is used only once and then discarded and never used again with the same secret. In that context, the nonce itself does not need to be secret, in fact in AEAD encryption, the nonce is often publicly disclosed unencrypted as part of the Associated Data (the AD part of AEAD). Since the nonce itself does not need to be secret, it is okay if it is predictable, and often for each encrypted message it is simply incremented.

The other type of nonce, it is not used in association with a cypher text but instead is used as a secret for validation. In this use, the nonce is a secret, and as a secret, it should not be predictable.

This second type of nonce is what is used for a CSRF token.

With the second type of nonce, since it is used for authentication, it really needs to be at least 128 bits (16 bytes) and generated by a quality Crytpographically Secure pRNG. And of course, to be a nonce it needs to be used only once.

WordPress does not create their CSRF tokens in an appropriate manner. They call them a nonce but they are not a nonce. They are created in a very predictable fashion without any random component at all, and then reused for twelve hours while remaining valid for an additional twelve hours after that.

Whoever wrote that part of the WordPress core code simply did not know what the fuck they were doing. It needs to be completely rewritten and written correctly.

Here is the WordPress code for it:

if ( !function_exists('wp_create_nonce') ) :
/**
 * Creates a cryptographic token tied to a specific action, user, user session,
 * and window of time.
 *
 * @since 2.0.3
 * @since 4.0.0 Session tokens were integrated with nonce creation
 *
 * @param string|int $action Scalar value to add context to the nonce.
 * @return string The token.
 */
function wp_create_nonce($action = -1) {
        $user = wp_get_current_user();
        $uid = (int) $user->ID;
        if ( ! $uid ) {
                /** This filter is documented in wp-includes/pluggable.php */
                $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
        }

        $token = wp_get_session_token();
        $i = wp_nonce_tick();

        return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
}
endif;

The return part of the function: The $i has nothing random about it and is predictable by an outside attacker. That only changes every 12 hours. The $action has nothing random about it and is predictable by an outside attacker. The $uid has nothing random about it and is predictable by an outside attacker. The $token is not random and while not easily predictable by an outside attacker, it can be discovered by an outside attacker.

The wp_hash() function uses a salt defined in wp-config.php which is not predictable by an outside attacker if the system administrator set a decent one, but since the web server has read permission to that file, it is possible that at some point the contents of that file has been compromised revealing the salts used. It’s also possible a really poor salt was defined that is predictable.

Nothing about the generation of a nonce by the wp_create_nonce() function is random. Not a damn thing. It’s like the developer heard that a nonce is what is needed for a CSRF token but did not care what a nonce actually is, so he created his own definition of a what a nonce is.

Even worse, only ten characters of what is generated is used. That is 5 bytes (80 bits). I do not understand the logic of why the call to substr() is even there.

PluggableUnplugged

In the PluggableUnplugged plugin, I partially fixed what WordPress does. It can not be completely fixed without rewriting parts of core that can not (at least not easily) be replaced with plugins.

I also provide the correct way for creating and validating a nonce that other plugins can potentially use instead of the WordPress core provided functions, but unfortunately there does not seem to be a mechanism to have one plugin require another and define the required plugin be loaded first, so it may not be of much use.

WordPress does provide something called a “Must Use Plugin” that would work to make sure the needed class from PluggableUnpluffed was loaded first, but a plugin can only be installed as a “Must Use Plugin” manually by the system administrator, so it is not really a solution.

I am looking into it more, maybe there is a way. But for now, any plugin that needs a CSRF token has to implement the proper itself if it does not want to use the incorrect WordPress implementation.

2 thoughts on “Cryptography: What is a Nonce ???

Leave a Reply

Your email address will not be published. Required fields are marked *

Anonymity protected with AWM Pluggable Unplugged