wp2shell: Pre Authentication RCE in WordPress Core

2 min read Original article ↗

wp2shell

Searchlight Cyber's security research team has discovered a pre-authentication RCE in WordPress Core. The attack has no preconditions and can be exploited by an anonymous user in a stock install of WordPress with no plugins.

It is estimated that over 500 million websites use WordPress. Given the severity of the bug and to give defenders time to patch, we are not releasing technical details at this time. We are, however, releasing a checker so you can determine whether your instance is vulnerable. Check your site directly below.

wp2shell checker

Versions Affected

< 6.9.0not affected
6.9.0 - 6.9.4affected, fixed in 6.9.5
7.0.0 - 7.0.1affected, fixed in 7.0.2

Mitigation

The best way to protect yourself is to update WordPress immediately. WordPress 7.0.2 contains the fix (or 6.9.5 if you are on the 6.9 branch). Until you can update, there are multiple mitigation options:

  1. Install the plugin Disable WP REST API to disable unauthenticated users from using the WordPress API. This is the easiest option but does have a possible low risk of breaking existing functionality.
  2. Use a WAF to block the path /wp-json/batch/v1 and the query parameter rest_route=/batch/v1 (both of these patterns must be blocked to secure your instance).
  3. Drop the following custom plugin into wp-content/plugins/disable-batch-api-for-unauth.php on the filesystem for your WordPress instance via SSH or FTP and enable it from Plugins in the admin panel:
    <?php
    /**
     * Plugin Name: Disable Unauthenticated REST Batch API
     * Description: Requires an authenticated WordPress user for REST batch requests.
     * Version: 1.0.0
     * Requires at least: 5.6
     * License: GPL-2.0-or-later
     */
    
    defined( 'ABSPATH' ) || exit;
    
    /**
     * Reject anonymous requests to the core REST batch endpoint.
     *
     * @param mixed           $result  Pre-calculated dispatch result.
     * @param WP_REST_Server  $server  REST server instance.
     * @param WP_REST_Request $request Current REST request.
     * @return mixed|WP_Error
     */
    function wporg_require_authentication_for_rest_batch( $result, $server, $request ) {
        $route = untrailingslashit( $request->get_route() );
    
        if ( '/batch/v1' !== $route || is_user_logged_in() ) {
            return $result;
        }
    
        return new WP_Error(
            'rest_batch_authentication_required',
            'Authentication is required to use the batch API.',
            array( 'status' => 401 )
        );
    }
    
    add_filter( 'rest_pre_dispatch', 'wporg_require_authentication_for_rest_batch', -1000, 3 );

Note that these solutions may have impact on legitimate use of the site and should only be considered emergency temporary measures until you can update.

Credits

Discovered and authored by Adam Kues of Searchlight Cyber.