WordPress.org

Make WordPress Core

Opened 3 months ago

Last modified 3 months ago

#42481 new defect (bug)

Test cookie secure flag prevents non-secure login

Reported by: RavanH Owned by:
Milestone: Awaiting Review Priority: low
Severity: normal Version: 4.9
Component: Login and Registration Keywords:
Focuses: Cc:

Description

Once a user has accessed the login form over https (possible without a valid ssl license, ignoring the browser warning) the WordPress TEST_COOKIE will have the secure flag set https://core.trac.wordpress.org/browser/trunk/src/wp-login.php#L433

When that user goes back to login over http, this will no longer be possible. The test cookie will be ignored by the browser because of the secure flag.

Without the test cookie, all login attempts will be redirected back to the login form with a warning about cookies not being set by the browser. Most users will not know why this happens and will no longer be able to log in.

The user will have to go back to https, open the developer toolbar, delete the cookie and then back to http. Only then the test cookie will be set again, this time without the secure flag.

A work-around to prevent users from being locked out like this, is to make the test cookie name "http/s aware" with something like this in wp-config.php:

$secure = ( isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS'] ) ? '_sec' : '';
define( 'TEST_COOKIE', 'wordpress' . $secure . '_test_cookie' );

(using wordpress_sec for secure cookie similar to the auth cookie)

But... the real question is:

Why does the test cookie need the secure flag at all?

There is no sensitive information passed and it's only there to (as the name suggests) test for cookie unaware or blocking browsers. At least as far as I can tell, there would be no possible problem with simply removing this cookies secure flag. This will not affect any sensitive login/session cookies secure flags.

Or am I mistaken? Are there use cases where the browser can be set to accept cookies over https while blocking them over http?

Change History (5)

#1 @RavanH
3 months ago

  • Component changed from General to Login and Registration

#2 @johnbillion
3 months ago

  • Keywords close added
  • Priority changed from normal to low
  • Version trunk deleted

Thanks for the report.

This strikes me as an edge case and something that doesn't really need fixing. It requires a server which responds over HTTPS but which is not configured to serve a particular domain over HTTPS, and a user who manually navigates to an HTTPS login URL, and who then subsequently intentionally ignores the security roadblocks presented by the browser.

If your server is set up to serve HTTPS for the requested domain, WordPress will allow you to log in over HTTPS regardless of the scheme set in the site's URL settings. Therefore, if any one of the three prerequisites above don't apply, then the issue won't occur.

The test cookie is a session cookie. If the user closes their browser, the cookie will be removed.

Regarding the question Why does the test cookie need the secure flag at all?, the answer is that there is no need for it to not use the secure flag when logging in over HTTPS.

#3 @RavanH
3 months ago

Hi @johnbillion it happens also with a valid license (no browser warning) where the admin can be accessed over https but front end is not set to use https by default. Then, on the front end over http, the user cannot log in anymore.

#4 @RavanH
3 months ago

  • Keywords close removed

Hmmm, it seems the issue goes deeper than the test cookie alone. Here https://status301.net/wp-content/uploads/2017/11/login-http.webm is a 1 minute screen cast taken from a multi-site where the primary site (front and admin) is on https but the sub-domain site has both site_url and home set to http.

Video description:

Logged in on the main site on https, from the My Sites page I follow the Visit link of a sub-site on http. This leads me to the front end of the subdomain where I'm not logged in (as expected). I then follow the Log In link in the Meta widget and try to log in. This results in a redirect back to the login form with the fore-mentioned cookie warning.

However, when I then manually type the /wp-admin/ url in the browser, it shows I am logged in after all.

But when I then go to the theme customizer, it will show the login form in the preview pane, this time with an "expired" message. Logging in again will redirect back to the same expired message...

The screen cast stops here but if I use the browser back button, I can get back to the admin without having to log in again. The session has not expired at all!

Hope this demonstrates how annoying this can be, occurring in one singe session without ever having to visit a https page without valid ssl license. Specially lesser gods like sub-site owners that already freak out at the first cookie warning. They might give up there and then, closing the browser. Come back later (session cookie cleared) and be able to log in but then still not be able to use the Theme Customizer or even be logged in on the front-end at the same time (no admin bar).

There really is something wrong in the whole ssl versus non-ssl logic here.

#5 @RavanH
3 months ago

  • Version set to 4.9

Take for instance the LOGGED_IN_COOKIE secure flag handling. In pluggable.php line 833 it sais:

// Front-end cookie is secure when the auth cookie is secure and the site's home URL is forced HTTPS.
$secure_logged_in_cookie = $secure && 'https' === parse_url( get_option( 'home' ), PHP_URL_SCHEME );

Although this seems perfectly logical, there is a problem when on multisite the primary site is on https, but when a new subdomain blog is created it uses http. The new site owner will then visit his new blog but no be logged in on the front end because the logged_in_cookie has the secure flag set when the user logged in on the main site (when creating his/her new account)

This problem is similar to the test_cookie but more persistent because the logged in cookie does not expire after one session. A nasty result of this what can be seen in the second half of the screen cast posted above.

The user will first have to go back to the main site, log out there, then go back to his sub-site, and log back in there... Not very intuitive.

Note: See TracTickets for help on using tickets.