[wp-trac] [WordPress Trac] #53994: REST API requests with session cookies but an invalid/missing nonce are considered authenticated for most of the request

WordPress Trac noreply at wordpress.org
Tue Aug 24 17:29:08 UTC 2021


#53994: REST API requests with session cookies but an invalid/missing nonce are
considered authenticated for most of the request
--------------------------+-----------------------------
 Reporter:  mboynes       |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  Security      |    Version:
 Severity:  normal        |   Keywords:
  Focuses:  rest-api      |
--------------------------+-----------------------------
 **Note: the security team reviewed this and asked that I post a public
 report as a hardening issue.**

 If a REST API request has valid session cookies but does not include a
 nonce, there is a significant portion of the process where the user is
 considered validly authenticated and signed in until the nonce is finally
 checked and the user account is nulled out. This period of the request is,
 practically speaking, the entire portion of the request where a plugin or
 theme would perform any operations before the REST response was sent (the
 obvious exception is if the REST endpoint were a custom one created by the
 theme or plugin, in which case, any code in direct service of dispatching
 the response would be after the nonce was checked). Therefore, if a
 request contains valid session cookies but an invalid or absent nonce,
 plugins and themes will almost always treat the request as if the user
 were validly authenticated, potentially voiding the purpose of the nonces.

 In WordPress Core, the first place the user account is accessed is in
 `\WP::init()`. After that, the init action fires, which of course, is a
 common hook for plugins and themes. In addition, there is nothing stopping
 a plugin or theme from accessing the user account well before
 `\WP::init()`, e.g. immediately as it is loaded. In other words, a user
 session is validated as early as an mu-plugin loading. Out-of-the-box,
 WordPress does make some decisions based on the user's logged-in status
 and capabilities, e.g. which mime types are allowed for an attachments
 REST request and how widget content is processed. In fact, even the REST
 API code itself decides whether or not to send nocache headers based on
 the user's authentication state before the nonce is checked.

 The request isn't de-authenticated again until the nonce is checked when
 `\WP_REST_Server::check_authentication()` runs, which is immediately
 before the response is dispatched in `\WP_REST_Server::serve_request()`.

 === Steps To Reproduce:

 1. Sign into a WordPress site
 2. Add the following code to your theme/plugin to confirm that you are
 considered "signed in", even though you didn't provide a nonce
 {{{#!php
 <?php
 add_action( 'init', function() { die( is_user_logged_in() ? 'You are
 signed in' : 'You are not signed in' ); } );
 }}}
 3. Make a REST API request from the same browser, without a nonce present

 === Recommendations

 My best suggestion for resolving the issue is to check the nonce as part
 of the `determine_current_user` filter. However, this would require that
 WordPress make some assumptions about the request and infer that it is a
 REST request before that decision is officially made, since at this point,
 the `REST_REQUEST` constant might not have been defined. Potentially, that
 makes #42061 a pre-requisite.

 === Impact

 I don't believe this to be a significant security vulnerability; after
 all, the user would still have to be validly authenticated. But it is
 certainly a vector for a CSRF attack, as it can potentially circumvent
 nonces. As far as I can tell, nothing in WordPress core is critically
 impacted out-of-the-box. The real impact I can foresee is that a plugin or
 theme performs an action for authenticated users during the request chain,
 and that action is exploited in a CSRF attack.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/53994>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list