SECURITY ADVISORY / 01

CVE-2025-10488 Exploit & Vulnerability Analysis

Complete CVE-2025-10488 security advisory with proof of concept (PoC), exploit details, and patch analysis for directorist.

directorist products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

Unauthenticated attacker. An AJAX POST to the add_listing_action endpoint with a crafted $image parameter containing path traversal sequences will move an arbitrary file on the server to a web-accessible location, or overwrite it entirely.

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.wordpress.local
Content-Type: application/x-www-form-urlencoded

action=add_listing_action&image=../../../wp-config.php

The server responds with HTTP 200 and silently moves wp-config.php from the WordPress root into the temp directory used by the plugin. An attacker observing the filesystem or making a subsequent request can confirm the file has been relocated. If the temp directory is world-readable or web-accessible, the attacker can then download the file and extract database credentials, auth salts, and other secrets needed for account takeover or remote code execution.

What the Patch Did

Before:

$filepath = $temp_dir . $image;

if ( is_dir( $filepath ) || ! file_exists( $filepath ) ) {

After:

$image    = sanitize_file_name( $image );
$filepath = $temp_dir . $image;

if ( is_dir( $filepath ) || ! file_exists( $filepath ) ) {

The patch adds a call to WordPress's sanitize_file_name() function before the $image variable is concatenated into the filepath. This function strips directory traversal sequences (../, ..\\) and other dangerous characters from the input, ensuring the resulting filename cannot reference parent directories or absolute paths. It transforms ../../../wp-config.php into wp-config.php — a safe, relative filename within the intended scope.

Root Cause

CWE-22: Improper Limitation of a Pathname to a Restricted Directory ("Path Traversal").

The $image parameter arrives from the AJAX request unsanitized. It flows directly into the $filepath variable via string concatenation at the vulnerable line, then is used in filesystem operations (implied by the context: if ( is_dir( $filepath ) || ! file_exists( $filepath ) )). Because no validation occurs between the request boundary and the filesystem sink, an attacker can inject path traversal sequences that escape the intended $temp_dir scope and reference any file on the system readable or writable by the web server user. The lack of a capability check (current_user_can()) means this sink is reachable without authentication.

Why It Works

The single load-bearing line is $image = sanitize_file_name( $image );. Removing it restores the vulnerability immediately — an attacker can again pass ../../../wp-config.php and have it treated as a valid path segment.

The engineer added this line, not a whitelist or regex filter, because sanitize_file_name() is WordPress's idiomatic, battle-tested API for this exact problem: it handles Unicode normalization, strips null bytes, removes OS-specific dangerous characters (:, ", <, > on Windows; null bytes everywhere), and crucially, removes forward and backward slashes used in traversal attacks. It returns a string safe for use as a filename within a single directory — not across multiple levels.

Why not also add a capability check or nonce verification at the AJAX endpoint? The patch doesn't; it focuses on the input vector. A belt-and-suspenders approach would add both, but this plugin's threat model may be "a listing upload endpoint should accept files from anonymous users" (e.g., public classifieds submissions). The patch trusts that decision and makes the input handling bulletproof instead. This is a reasonable choice provided the temp directory itself has correct permissions and the file operations that follow do not introduce new risks.

Hardening Checklist

  • Use sanitize_file_name() on all user-supplied filenames before filesystem operations. This is non-negotiable for any plugin accepting file uploads or names. Test with inputs like ../../etc/passwd to confirm traversal is blocked.

  • Validate file operation inputs with wp_safe_remote_fopen() or wp_remote_get() if fetching remote files, and use realpath() post-operation to confirm the resolved path remains within the intended base directory — catching symlink attacks and race conditions the sanitizer alone cannot prevent.

  • Add current_user_can( 'upload_files' ) or equivalent capability checks to AJAX actions that modify the filesystem, even if the plugin's business logic permits public uploads. This creates an audit trail and raises the bar for anonymous exploitation.

  • Apply wp_verify_nonce() to all AJAX actions, regardless of authentication level. It does not require login but does bind the request to a specific user session, preventing CSRF and making exploitation require active user interaction or session hijacking.

  • Log all filesystem operations (move, copy, delete, rename) with error_log() or a proper audit plugin. When exploitation occurs, forensics depend on visibility.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2025-10488

Frequently asked questions about CVE-2025-10488

What is CVE-2025-10488?

CVE-2025-10488 is a security vulnerability identified in directorist. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2025-10488?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2025-10488. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2025-10488 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting directorist. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2025-10488?

CVE-2025-10488 affects directorist. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2025-10488?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for directorist.

What is the CVSS score for CVE-2025-10488?

The severity rating and CVSS scoring for CVE-2025-10488 affecting directorist is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.