[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fON5cNqw7Brv7afCNn9bA97eUjPLzg-W13nK7ke5uxIM":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":22,"research_verified":23,"research_rounds_completed":20,"research_plan":24,"research_summary":25,"research_vulnerable_code":26,"research_fix_diff":27,"research_exploit_outline":28,"research_model_used":29,"research_started_at":30,"research_completed_at":31,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":32},"CVE-2026-2144","magic-login-mail-or-qr-code-unauthenticated-privilege-escalation-via-insecure-qr-code-file-storage","Magic Login Mail or QR Code \u003C= 2.05 - Unauthenticated Privilege Escalation via Insecure QR Code File Storage","The Magic Login Mail or QR Code plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 2.05. This is due to the plugin storing the magic login QR code image with a predictable, static filename (QR_Code.png) in the publicly accessible WordPress uploads directory during the email sending process. The file is only deleted after wp_mail() completes, creating an exploitable race condition window. This makes it possible for unauthenticated attackers to trigger a login link request for any user, including administrators, and then exploit the race condition between QR code file creation and deletion to obtain the login URL encoded in the QR code, thereby gaining unauthorized access to the targeted user's account.","magic-login-mail",null,"\u003C=2.05","2.06","high",8.1,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Improper Privilege Management","2026-02-13 16:21:07","2026-02-16 22:01:53",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F65066a17-653b-4444-9bd0-894ea8c1acb1?source=api-prod",3,[],"researched",false,"This research plan focuses on exploiting a race condition in the **Magic Login Mail or QR Code** plugin (\u003C= 2.05). The vulnerability stems from the use of a static filename for a sensitive QR code image in a public directory.\n\n---\n\n### 1. Vulnerability Summary\nThe \"Magic Login Mail or QR Code\" plugin allows users to log in via a link sent to their email or by scanning a QR code. When a magic login is requested, the plugin generates a QR code image containing a sensitive login token\u002FURL. \n\nThe plugin saves this image to a predictable path: `wp-content\u002Fuploads\u002FQR_Code.png`. Crucially, this file is created just before `wp_mail()` is called and is deleted immediately after `wp_mail()` returns. Because `wp_mail()` (especially when using SMTP or external handlers) is a relatively slow operation, a race condition window exists where an unauthenticated attacker can download the QR code, decode the login URL, and gain access to the targeted account.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** The magic login request trigger. This is typically a `wp-admin\u002Fadmin-ajax.php` action or a `POST` request to the login page.\n*   **Vulnerable Action:** `magic_login_request` or similar (inferred).\n*   **Target User:** Typically an administrator (User ID 1).\n*   **Payload:** The username or email of the target user sent to the request endpoint.\n*   **Authentication:** Unauthenticated.\n*   **Preconditions:** \n    1.  The \"Magic Login\" and \"QR Code\" features must be enabled in plugin settings.\n    2.  The attacker knows the username or email of an administrator.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** `MagicLogin::trigger_magic_login()` (Action: `wp_ajax_nopriv_magic_login_request` or triggered via `login_form`).\n2.  **QR Generation:** The plugin calls a QR generation library.\n3.  **File Write:** The plugin calls `file_put_contents( $upload_dir['basedir'] . '\u002FQR_Code.png', $qr_data )`.\n4.  **Email Sending:** The plugin calls `wp_mail()`. **\u003C-- Race window starts here.**\n5.  **Cleanup:** The plugin calls `unlink( $upload_dir['basedir'] . '\u002FQR_Code.png' )`. **\u003C-- Race window ends here.**\n\n### 4. Nonce Acquisition Strategy\nLogin-related actions often require a nonce if triggered via AJAX.\n1.  **Locate Nonce:** Check the WordPress login page (`\u002Fwp-login.php`) for enqueued scripts from the plugin.\n2.  **Identify JS Variable:** Look for `wp_localize_script` output. \n    *   *Likely Variable:* `window.magic_login_vars` or `window.magic_login_data`.\n    *   *Likely Key:* `nonce` or `magic_nonce`.\n3.  **Extraction Command:**\n    ```javascript\n    \u002F\u002F Example extraction via browser_eval\n    browser_eval(\"window.magic_login_vars?.nonce\")\n    ```\n4.  **Creation of Test Page:** If the login page doesn't expose it, the plugin might use a shortcode like `[magic_login_form]`.\n    ```bash\n    wp post create --post_type=page --post_status=publish --post_title=\"Login\" --post_content='[magic_login_form]'\n    ```\n\n### 5. Exploitation Strategy\n\n**Step 1: Preparation**\nIdentify the target admin username (defaulting to 'admin'). Determine the upload directory path (usually `\u002Fwp-content\u002Fuploads\u002F`).\n\n**Step 2: Trigger and Capture (The Race)**\nSince `wp_mail` is the bottleneck, we need to send the trigger and immediately poll the static file location.\n\n**Request A (Trigger):**\n*   **Method:** `POST`\n*   **URL:** `http:\u002F\u002Fvulnerable-site.tld\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Body:** `action=magic_login_request&user_login=admin&nonce=[NONCE_OBTAINED_PREVIOUSLY]`\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n\n**Request B (Capture - Concurrent):**\n*   **Method:** `GET`\n*   **URL:** `http:\u002F\u002Fvulnerable-site.tld\u002Fwp-content\u002Fuploads\u002FQR_Code.png`\n\n**Execution Logic:**\n1.  Start a loop or multiple concurrent requests for Request B.\n2.  Fire Request A.\n3.  As soon as Request B returns `200 OK`, download the image.\n\n**Step 3: Decoding**\nThe captured `QR_Code.png` will contain a URL like:\n`http:\u002F\u002Fvulnerable-site.tld\u002F?magic-login=TOKEN_VALUE`\n\n**Step 4: Escalation**\nNavigate to the extracted URL in the browser to be automatically logged in as the administrator.\n\n### 6. Test Data Setup\n1.  **Plugin Config:** Ensure \"QR Code\" is enabled in Magic Login settings.\n2.  **User:** Ensure an admin user exists (e.g., username `admin`).\n3.  **Mail Lag (Optional):** To make the race condition easier to hit in a test environment, one could use a plugin like \"WP Mail Logging\" or configure a slow SMTP server, which increases the execution time of `wp_mail()`.\n\n### 7. Expected Results\n*   **Trigger Response:** A success message indicating a magic link was sent.\n*   **Capture Response:** A binary image file (`image\u002Fpng`) found at `\u002Fwp-content\u002Fuploads\u002FQR_Code.png`.\n*   **Final Result:** The decoded URL redirects the attacker to the WordPress Dashboard with administrator privileges.\n\n### 8. Verification Steps\n1.  **File Existence Check:** Use `ls -l \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002FQR_Code.png` during the request to prove the file is written.\n2.  **Session Verification:** After navigating to the magic link, use `wp-cli` to verify the session:\n    ```bash\n    wp user get admin --field=user_login\n    # Check if the browser session cookies correspond to the admin user\n    ```\n\n### 9. Alternative Approaches\n*   **Inferred Action Names:** If `magic_login_request` is incorrect, grep the plugin source for `wp_ajax_nopriv` to find the correct trigger:\n    ```bash\n    grep -r \"wp_ajax_nopriv\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fmagic-login-mail\u002F\n    ```\n*   **Filename Variations:** If `QR_Code.png` is not found, check if the plugin uses the user ID in the name (e.g., `QR_Code_1.png` - inferred). Grep the source for `.png`:\n    ```bash\n    grep -r \".png\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fmagic-login-mail\u002F | grep \"uploads\"\n    ```\n*   **Direct Pathing:** If `\u002Fwp-content\u002Fuploads\u002F` is protected, check for `wp-content\u002Fuploads\u002Fmagic-login\u002FQR_Code.png` (inferred).","The Magic Login Mail or QR Code plugin (\u003C= 2.05) stores sensitive login QR codes in a publicly accessible directory using a static, predictable filename (QR_Code.png). Because these files exist for the duration of the wp_mail() function call, an unauthenticated attacker can exploit a race condition to download the QR code, decode the magic login URL, and gain administrative access.","\u002F\u002F magic-login-mail\u002Fincludes\u002Fclass-magic-login-request.php (Inferred location)\n\n$upload_dir = wp_upload_dir();\n$file_path = $upload_dir['basedir'] . '\u002FQR_Code.png';\n\n\u002F\u002F Generates the QR code and writes it to a predictable static path\n$renderer->render($qr_code)->save($file_path);\n\n$attachments = array($file_path);\n$sent = wp_mail($user_email, $subject, $message, $headers, $attachments);\n\n\u002F\u002F The file remains accessible until wp_mail completes, which can be delayed by SMTP or external APIs\nif (file_exists($file_path)) {\n    unlink($file_path);\n}","--- a\u002Fincludes\u002Fclass-magic-login-request.php\n+++ b\u002Fincludes\u002Fclass-magic-login-request.php\n@@ -1,6 +1,7 @@\n $upload_dir = wp_upload_dir();\n-$file_path = $upload_dir['basedir'] . '\u002FQR_Code.png';\n+$random_suffix = wp_generate_password(20, false);\n+$file_path = $upload_dir['basedir'] . '\u002FQR_Code_' . $random_suffix . '.png';\n \n $renderer->render($qr_code)->save($file_path);\n \n $attachments = array($file_path);","The exploit targets the predictable file path and the delay inherent in the WordPress mail-sending process. An attacker first determines the target username (e.g., 'admin') and begins a high-frequency polling loop of GET requests to the known path 'wp-content\u002Fuploads\u002FQR_Code.png'. While polling, the attacker triggers the plugin's magic login request for the target user (via wp-admin\u002Fadmin-ajax.php or the login form). If the attacker's GET request occurs after the file is written but before wp_mail() finishes and unlinks the file, the attacker successfully downloads the image. The image is then decoded using any QR reader to extract the unique login token URL, which provides immediate authenticated access to the target account.","gemini-3-flash-preview","2026-04-20 23:37:05","2026-04-20 23:37:26",{"type":33,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":34},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmagic-login-mail\u002Ftags"]