
PoC exploit for CVE-2025-68999 - Second-Order SQL Injection in Happy Addons for Elementor <= 3.20.4
| CVSS | 8.5 HIGH |
| Affected | <= 3.20.4 |
| Patched | 3.20.6 |
| Min. role | Contributor (edit_posts) |
| Vector | Network / Low complexity / Low privileges |
duplicate_meta_entries() in classes/clone-handler.php copies post meta rows to a cloned post using a hand-rolled bulk INSERT. It fetches the rows safely with $wpdb->prepare(), but then drops $entry->meta_key straight into the SQL string without escaping:
$_records[] = "( $duplicated_post_id, '{$entry->meta_key}', '{$_value}' )";
// ...
$wpdb->query( $query );
Because meta_key comes from the database, the code treats it as trusted. But Contributors can set arbitrary field names via the Custom Fields panel — so they control what's in that column.
The attack is two steps:
add_post_meta() handles this safely — the payload lands in the DB without executing anything.duplicate_meta_entries() reads the key back and concatenates it into the raw INSERT. MySQL executes the injected subquery.Static analysis misses this because the source of dangerous data is a DB read ($wpdb->get_results()), which taint engines mark as sanitized. The storage boundary breaks the taint chain.
Any Contributor can extract:
wp_options (API keys, payment credentials)400K+ active installs were affected at disclosure time.
pip install requests
python3 poc.py https://target.com contributor p4ss
The script authenticates over HTTP, stores the injection payload as a custom field name, triggers the Happy Clone action, and reads the leaked hash from the cloned post's meta fields. Output is saved to hash.txt.
hashcat -m 400 hash.txt rockyou.txt
| Date | Event |
|---|---|
| December 2025 | Discovered via SVN diff. PoC confirmed. |
| December 2025 | Reported to Patchstack Alliance with full writeup and PoC. |
| January 2026 | weDevs shipped the fix in v3.20.6. |
| January 23, 2026 | CVE-2025-68999 published. CVSS 8.5 HIGH assigned. |
weDevs replaced the entire hand-rolled INSERT with:
foreach ( $entries as $entry ) {
update_post_meta( $duplicated_post_id, $entry->meta_key, $entry->meta_value );
}
update_post_meta() internally calls $wpdb->update() with prepared statements for both key and value.