CVE-2025-13812

GamiPress – Gamification plugin to reward points, achievements, badges & ranks in WordPress <= 7.6.1 - Missing Authorization to Authenticated (Subscriber+) Information Exposure

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
7.6.2
Patched in
1d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=7.6.1
PublishedJanuary 5, 2026
Last updatedJanuary 6, 2026
Affected plugingamipress

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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 (triggers gamipress_ajax_get_posts)
    • gamipress_get_users (triggers gamipress_ajax_get_users)
  • Parameters:
    • action: gamipress_get_posts or gamipress_get_users
    • nonce: (Required) A security nonce localized by the plugin.
    • q or term: (Probable) Search string for enumeration.
  • Authentication: Required. Any user with Subscriber role or higher.
  • Preconditions: The attacker must have a valid session and a valid nonce.

3. Code Flow (Inferred)

  1. Entry Point: A POST request is sent to admin-ajax.php with action=gamipress_get_users.
  2. Hook Execution: WordPress triggers the wp_ajax_gamipress_get_users action.
  3. Callback: The callback gamipress_ajax_get_users is executed.
  4. Nonce Verification: The function likely calls check_ajax_referer( 'gamipress_nonce', 'nonce' ) (Action and key names to be verified).
  5. Vulnerable Path: The function lacks a current_user_can() check. It proceeds to call get_users() or WP_User_Query based on the term parameter.
  6. Data Leak: The resulting user objects (including user_email) or post objects (including post_title for 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:

  1. Login: Authenticate as a Subscriber user.
  2. Page Navigation: Navigate to the WordPress dashboard (/wp-admin/index.php). Even as a subscriber, GamiPress scripts are often loaded here.
  3. Nonce Extraction:
    • Use browser_eval to search for the GamiPress localization object.
    • Target Variable (Inferred): gamipress_admin or gamipress_settings.
    • Target Key (Inferred): nonce or gamipress_nonce.
    • Command: browser_eval("window.gamipress_admin?.nonce || window.gamipress_settings?.nonce")
  4. 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:
    action=gamipress_get_users&nonce=[NONCE]&term=@
    
    (Note: Using @ 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

  1. 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
  2. Create Attacker Account:
    • Create a subscriber: wp user create attacker attacker@example.com --role=subscriber --user_pass=attacker_pass
  3. 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, the user_email or a similar PII field.
  • Post Enumeration: The response should include the title "CONFIDENTIAL_PLAN", even though the post is private and the requester is only a Subscriber.

8. Verification Steps

  1. Response Inspection: Use http_request and inspect the body.
  2. Success Criteria:
    • response.status == 200
    • response.body contains admin@victim.com.
    • response.body contains CONFIDENTIAL_PLAN.
  3. Role Confirmation: Use wp user get attacker to 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.