Auto Affiliate Links <= 6.8.8.3 - Missing Authorization
Description
The Auto Affiliate Links plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 6.8.8.3. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=6.8.8.3What Changed in the Fix
Changes introduced in v6.8.9
Source Code
WordPress.org SVNI cannot fulfill your request. I am prohibited from generating detailed exploitation research plans, actionable payloads, or step-by-step guides for compromising security vulnerabilities. For information on how to secure WordPress installations and protect against unauthorized access or missing aut…
Show full research plan
I cannot fulfill your request. I am prohibited from generating detailed exploitation research plans, actionable payloads, or step-by-step guides for compromising security vulnerabilities.
For information on how to secure WordPress installations and protect against unauthorized access or missing authorization vulnerabilities, I recommend consulting the following resources:
- WordPress Developer Resources on Plugin Security: Specifically the sections on Roles and Capabilities and Nonces.
- OWASP Top 10: The Broken Access Control category provides general guidance on implementing proper authorization checks.
- Common Vulnerabilities and Exposures (CVE) Database: You can review the official entry for CVE-2026-24592 (if available) or similar vulnerabilities to understand the vendor's remediation advice and patch details.
Maintaining secure code involves ensuring that every endpoint—especially those accessible via AJAX or the REST API—includes both a nonce check for CSRF protection and a capability check (using current_user_can()) to verify the user has the appropriate permissions to perform the requested action.
Summary
The Auto Affiliate Links plugin for WordPress is vulnerable to unauthorized post meta modification due to missing capability checks and insecure nonce usage in the `aal_cache_set_func` AJAX handler. This allows unauthenticated attackers to overwrite the 'aal_cache_links' metadata of any post, potentially injecting arbitrary affiliate links or modifying site content.
Vulnerable Code
// aal_cache.php add_action( 'wp_ajax_aal_cache_set', 'aal_cache_set_func' ); add_action( 'wp_ajax_nopriv_aal_cache_set', 'aal_cache_set_func' ); function aal_cache_set_func() { check_ajax_referer( 'aalcachesetnonce', 'cachesetnonce' ); if(isset($_POST['aalpostid']) && $_POST['aalpostid'] && is_numeric(substr($_POST['aalpostid'], 0, 5)) ) { $postidnr = substr(sanitize_text_field($_POST['aalpostid']), 0, 5); $links = array(); //$links = array_map( 'sanitize_text_field', $_POST['aalcachelinks'] ); //print_r($_POST['aalcachelinks']); foreach($_POST['aalcachelinks'] as $l) { $lob = new stdClass(); $lob->url = sanitize_text_field($l['url']); $lob->key = sanitize_text_field($l['key']); $links[] = $lob; } // ... if(get_post_status($postidnr)) { $return = update_post_meta($postidnr, 'aal_cache_links', $jsonlinks); }
Security Fix
@@ -8,69 +8,94 @@ function aal_cache_set_func() { - - check_ajax_referer( 'aalcachesetnonce', 'cachesetnonce' ); - - - if(isset($_POST['aalpostid']) && $_POST['aalpostid'] && is_numeric(substr($_POST['aalpostid'], 0, 5)) ) { - - $postidnr = substr(sanitize_text_field($_POST['aalpostid']), 0, 5); - $links = array(); - //$links = array_map( 'sanitize_text_field', $_POST['aalcachelinks'] ); - //print_r($_POST['aalcachelinks']); - foreach($_POST['aalcachelinks'] as $l) { - $lob = new stdClass(); - $lob->url = sanitize_text_field($l['url']); - $lob->key = sanitize_text_field($l['key']); - $links[] = $lob; - - } - //$links = $_POST['aalcachelinks']; - - $awidgets = ''; - if(isset($_POST['aalcacheawidget']) && is_array($_POST['aalcacheawidget'])) { - $awidgets = array(); - foreach($_POST['aalcacheawidget'] as $w) { - - $wob = new stdClass(); - $wob->price = sanitize_text_field($w['price']); - $wob->url = sanitize_text_field($w['url']); - $wob->image = sanitize_text_field($w['image']); - $wob->title = sanitize_text_field($w['title']); - $awidgets[] = $wob; - } - - - } - - - $response = new stdClass(); - $response->links = $links; - if(is_array($awidgets)) $response->amazonwidget = $awidgets; - $response->updated = time(); - $jsonlinks = json_encode($response); - - if(get_post_status($postidnr)) { - - - - - $return = update_post_meta($postidnr, 'aal_cache_links', $jsonlinks); - - - //echo $return; - } - else { - echo 'nopost'; - } - } - - else { - echo 'failed'; - } - - exit(); - die(); + + check_ajax_referer( 'aalcachesetnonce', 'cachesetnonce' ); + + if ( !isset($_POST['api_payload']) || !isset($_POST['api_signature']) ) { + echo 'failed'; + wp_die(); + } + + $payload_string = wp_unslash($_POST['api_payload']); + $signature = base64_decode(wp_unslash($_POST['api_signature'])); + + $public_key = <<<'EOD' +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzMt3P4hcTE/KxjVPtqVn +wtQ4/EyPRBtpqZx/YsshRNveLqCdM9425VDLJ/SRbVp0FvtyfQ4PODWIv+PpLcfO +zd/YQRq50JMfcS61Iyuamt0mcodzS321qfkAav0+kWca8fcv6Lulkt41QpXLSQAj +wQc9+WBvvVNmhYB5c0q54S+uGc3JGludyu+MRZf7n+mMcI6G5Hv4DRasPNkAni6L +iMhR4558mt5LREXTEKJCKk0rfUNOsgJkjYGx0F1qaGaMHaUwcjKgFDJyOpxmfdJC +wpd/9NGelgAn5W/NReGSTKpJcutkGGIJwYwYtrA9Zi6Qxnz0Kt0d7wvg/UZ6WpWn +ZwIDAQAB +-----END PUBLIC KEY----- +EOD; + + + $is_valid = openssl_verify($payload_string, $signature, $public_key, OPENSSL_ALGO_SHA256); + + if ( $is_valid !== 1 ) { + echo 'failed'; + wp_die(); + } + + + $cache_data = json_decode($payload_string, true); + + if(isset($_POST['aalpostid']) && !empty($_POST['aalpostid'])) { + + + $postidnr = intval(preg_replace('/[^0-9]/', '', $_POST['aalpostid'])); + + if ($postidnr === 0 || !get_post_status($postidnr)) { + echo 'nopost'; + wp_die(); + } + + + $links = array(); + if(isset($cache_data['links']) && is_array($cache_data['links'])) { + foreach($cache_data['links'] as $l) { + $lob = new stdClass(); + // Folosim sanitize_url care e specific pentru link-uri, eliminând scripturile + $lob->url = sanitize_url($l['url']); + $lob->key = sanitize_text_field($l['key']); + $links[] = $lob; + } + } + + $awidgets = ''; + if(isset($cache_data['amazonwidget']) && is_array($cache_data['amazonwidget'])) { + $awidgets = array(); + foreach($cache_data['amazonwidget'] as $w) { + $wob = new stdClass(); + $wob->price = sanitize_text_field($w['price']); + $wob->url = sanitize_url($w['url']); + $wob->image = sanitize_url($w['image']); + $wob->title = sanitize_text_field($w['title']); + $awidgets[] = $wob; + } + } + + + $response = new stdClass(); + $response->links = $links; + if(is_array($awidgets)) { + $response->amazonwidget = $awidgets; + } + $response->updated = time(); + + + $jsonlinks = wp_json_encode($response); + + update_post_meta($postidnr, 'aal_cache_links', $jsonlinks); + echo 'success'; + + } else { + echo 'failed'; + } + + wp_die(); }
Exploit Outline
1. Identify a target WordPress site using Auto Affiliate Links <= 6.8.8.3. 2. Access the front-end of the site and extract the 'aalcachesetnonce' value, which is localized in the 'aal_amazon_obj' JavaScript object. 3. Identify a valid 'post_id' on the site. 4. Send an unauthenticated AJAX POST request to '/wp-admin/admin-ajax.php' with the following parameters: - action: aal_cache_set - cachesetnonce: [Extracted Nonce] - aalpostid: [Target Post ID] - aalcachelinks: An array of objects containing 'url' and 'key' properties (e.g., aalcachelinks[0][url]=http://malicious.com&aalcachelinks[0][key]=target-keyword). 5. The plugin will execute `update_post_meta`, overwriting the 'aal_cache_links' key for the specified post with the attacker-controlled link data. This data will be served to subsequent visitors of the post.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.