SECURITY ADVISORY / 01

CVE-2023-6567 Exploit & Vulnerability Analysis

Complete CVE-2023-6567 security advisory with proof of concept (PoC), exploit details, and patch analysis for learnpress.

learnpress products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An unauthenticated attacker can inject time-based SQL via the order_by parameter in any LearnPress API endpoint or frontend handler that accepts course filtering.

GET /wp-json/lp/v1/courses?order_by=post_date AND SLEEP(5) HTTP/1.1
Host: target.local
User-Agent: curl/7.85.0
Accept: */*

On vulnerable versions (≤4.2.5.7), the server pauses for 5 seconds before responding, confirming blind SQL injection. The attacker observes a delayed HTTP 200 response with course data; on fixed versions, the request either returns immediately with an error or a 400 Bad Request if the order_by value fails stricter validation.

What the Patch Did

Before

$filter->order_by = LP_Helper::sanitize_params_submitted( ! empty( $param['order_by'] ) ? $param['order_by'] : 'post_date' );
$filter->order    = LP_Helper::sanitize_params_submitted( ! empty( $param['order'] ) ? $param['order'] : 'DESC' );

After

$filter->order_by = LP_Helper::sanitize_params_submitted( ! empty( $param['order_by'] ) ? $param['order_by'] : 'post_date', 'key' );
$filter->order    = LP_Helper::sanitize_params_submitted( ! empty( $param['order'] ) ? $param['order'] : 'DESC', 'key' );

The patch adds a second parameter 'key' to both LP_Helper::sanitize_params_submitted() calls. This parameter instructs the helper function to validate the input as a SQL identifier (column name or sort direction) rather than as generic text. The security control being enforced is whitelist validation of SQL column identifiers — the function now rejects any value that does not match a predefined set of safe column names (e.g., post_date, post_title, post_modified) or sort keywords (e.g., ASC, DESC). Without the 'key' parameter, the old code performed only basic escaping, which is insufficient to prevent ORDER BY clause injection.

Root Cause

CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection').

The vulnerable dataflow begins when a user-controlled order_by parameter arrives via the HTTP request (GET or POST). The parameter is extracted into $param['order_by'] by the request handler. It is then passed to LP_Helper::sanitize_params_submitted() without the 'key' type hint. The function applies only generic sanitization (likely stripslashes or basic escaping), which does not prevent SQL metacharacters from being interpreted as query syntax. The unsanitized value flows directly into a SQL ORDER BY clause, crossing the query builder trust boundary unchecked. Because ORDER BY accepts column identifiers without quotes, an attacker can inject boolean operators (AND, OR), timing functions (SLEEP(), BENCHMARK()), or subqueries to leak data or exhaust resources.

Why It Works

The load-bearing line is the addition of the 'key' parameter to the sanitize_params_submitted() call. Removing it restores the vulnerability because the helper function requires this hint to know which validation ruleset to apply. Without it, the function falls back to a permissive text sanitizer that allows most characters. The patch adds the parameter to both order_by and order because SQL injection can occur in either position — an attacker might inject via order=post_date UNION SELECT … just as easily as via order_by. The engineer added both fixes to ensure defence-in-depth across all ORDER-related parameters; patching only one would leave a second injection point open. The fix is effective because it replaces output escaping (insufficient for identifiers) with input validation against a whitelist — the only reliable defence for SQL syntax elements that cannot be quoted.

Hardening Checklist

  • Enumerate SQL column names at class initialization and validate order_by against an explicit whitelist (e.g., $allowed_order_by = array('post_date', 'post_title', 'post_modified') and in_array($param['order_by'], $allowed_order_by, true)). Do not rely on helper functions without verifying their implementation.

  • Use parameterized queries or query builder APIs for all ORDER BY and GROUP BY clauses if the underlying database library supports them (e.g., Doctrine, Eloquent, or WordPress's $wpdb->prepare() for the WHERE clause, though ORDER BY still requires manual whitelisting).

  • Add a unit test that confirms malicious SQL is rejected. For example, test that order_by=post_date AND SLEEP(5) returns 400 Bad Request, not a delayed 200 response. Include tests for common injection vectors: boolean operators, aggregate functions, subqueries.

  • Audit all other user-supplied parameters that touch SQL syntax (LIMIT offset, GROUP BY, HAVING, JOIN ON). If any parameter influences SQL structure rather than values, apply whitelist validation with the same rigor as order_by.

  • Document which parameters are safe and which are risky in inline code comments. Mark any parameter that reaches $wpdb->query() or custom query construction as "must be whitelisted" to prevent future developers from making the same mistake.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2023-6567

Frequently asked questions about CVE-2023-6567

What is CVE-2023-6567?

CVE-2023-6567 is a security vulnerability identified in learnpress. 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-2023-6567?

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

How does CVE-2023-6567 get exploited?

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

What products and versions are affected by CVE-2023-6567?

CVE-2023-6567 affects learnpress. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2023-6567?

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

What is the CVSS score for CVE-2023-6567?

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