[wp-trac] [WordPress Trac] #46130: Only pause extensions for users with recovery access
WordPress Trac
noreply at wordpress.org
Mon Jan 28 21:34:14 UTC 2019
#46130: Only pause extensions for users with recovery access
--------------------------+------------------------------------------------
Reporter: flixos90 | Owner: TimothyBlynJacobs
Type: defect (bug) | Status: assigned
Priority: highest omg | Milestone: 5.1
bbq |
Component: | Version: trunk
Bootstrap/Load |
Severity: normal | Keywords: needs-patch servehappy 2nd-opinion
Focuses: |
--------------------------+------------------------------------------------
After introduction of the fatal error recovery mechanism in #44458,
several follow-up tickets were opened. While some were regarding regular
bugs, quite a few included security concerns, particularly about how a
malicious attack could cause even safe plugins and themes to be paused.
Security researchers outside of the WordPress space have already published
about the problems as well: https://medium.com/websec/wordpress-serve-
happy-ffd93c94f5ac
While we have since investigated reducing the attack vectors by pausing
extensions less aggressively (see #45888, #45940, #46066), it appears that
it is impossible to reliably prevent all loopholes there.
In today's PHP meeting, an alternative approach came up:
* Instead of pausing extensions globally on certain protected endpoints,
extensions should only be paused for specific users.
* An admin user could receive a "recovery link" with a secret code, for
example with an email.
* When opening the recovery link, the secret code is verified, and then a
"recovery cookie" is stored on the user's machine, containing a nonce.
* Whenever such a recovery cookie is present and valid, extension pausing
is enabled.
This approach allows reusing most logic that is already in place. Instead
of pausing on protected endpoints, pausing will happen whenever the cookie
is present, in any area. In other words, the protected endpoint logic can
be removed and instead be replaced by the recovery mode check.
More concrete suggestions regarding the implementation:
* To generate a new recovery link, use something like
`wp_generate_password( 20, false )`, and store a hashed version of that
value as `recovery_key` in the `wp_user_meta` table. Include the raw value
in the recovery link as a query parameter to be given to the user.
* When a user clicks the link, check the query parameter. Hash it in the
same process, then query the user by that `recovery_key` meta value. If no
user is found, the recovery key is invalid. If one is found, delete the
key so that it is no longer valid and set a cookie on the device. The
cookie should use some of the `*_KEY` constants from `wp-config.php` to
have an unpredictable name.
* After setting the cookie and deleting the recovery key, the user should
be redirected to the admin. At this point, the cookie is already placed,
so recovery mode is de-facto active.
* Introduce `wp_is_recovery_mode()` or similar. This function should check
if the cookie exists and is valid. We can then replace all checks for
`is_protected_endpoint()` with checks for this new function.
Considerations:
* What should we store in the cookie? Should the existence of the cookie
limited to a few minutes/hours/days? Should there be a nonce in the cookie
value (that itself restricts duration already)?
* How would an administrator get a recovery link? Should the fatal error
handler send an email when it detects an error? Should there be an area in
the admin where a user can request one that is then displayed to them just
once so that they can copy/paste it?
We need to find a good measure here that is both secure but also stable
enough for users. For example consider that, when a site is broken and
nobody has a valid recovery link, the site is still as inaccessible as
before, so that should be mitigated.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/46130>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list