The OpenID plugin for WordPress allows users to log into WordPress using OpenID rather than a username and password. The login procedure has three stages; first, the user provides their “identity URL” on the blog login page, and the OpenID plugin generates a nonce (secret authentication value) and redirects the user to the identity URL they provided. Once authentication succeeds, the user is redirected back to the blog by their identity provider, and then they are redirected back to the login page – but now with the nonce. Finally, the third stage allows them to login as the user which is associated with the given identity URL.

This is secure since the nonce is not provided to the user until they have successfully authenticated; any attempt to perform the third stage of the authentication without providing the nonce produces an error. Unfortunately, while the code did produce an error in this case, this did not stop users from logging in, since the authentication function looked like this:

if (!wp_verify_nonce(... $_REQUEST['identity_url'])) {
    $user = new WP_Error("invalid nonce");
}
if ($_REQUEST['identity_url']) {
    $user = new WP_User($user_id);
}
return $user;

As you can see, if an attacker provides a valid identity URL, then the error stored in the $user variable is lost due to being overwritten; this means they can login directly via the third stage, without needing to provide a valid nonce.

Adding a ‘return $user;’ after the error is generated is sufficient to solve the problem. The plugin is used on many Canonical blogs, who merged my fix in July after I reported it to them directly; my upstream patch was finally merged in November, soon after I pinged one of the upstream developers about it.