WordPress Plugin Vulnerabilities

PeproDev WooCommerce Receipt Uploader <= 2.8.0 - Unauthenticated Order Receipt Tampering via IDOR

Description

PeproDev WooCommerce Receipt Uploader (plugin slug: pepro-bacs-receipt-upload-for-woocommerce), all versions up to and including 2.8.0 (latest on wordpress.org; no fixed version available at the time of writing), is vulnerable to unauthenticated missing-authorization / IDOR write. Requires WooCommerce.

The plugin exposes its receipt-upload AJAX action to unauthenticated users via wp_ajax_nopriv_upload-payment-receipt (wc-upload-reciept.php:120). The only gate on the handler handel_ajax_req() is a static WordPress nonce: :1057 wp_verify_nonce($_POST['nonce'], 'wcuploadrcp') (db_slug at :37). That nonce is emitted to the unauthenticated customer via wp_nonce_field('wcuploadrcp','uniqnonce') at :379 inside the receipt-upload form; for a logged-out user it is a uid-0 nonce - a site-wide constant for the nonce window, harvestable by any anonymous visitor (place a throwaway guest order and read it from your own order page) and replayable. A nonce is a CSRF token, not authorization.

There is NO ownership check on the target order: :1069 sanitize_text_field($_POST['order']); :1070 wc_get_order(order); only the order's existence is checked (:1071). No is_user_logged_in / current_user_can / customer-ownership check. (is_payment_method_allowed gates only form RENDERING at :961/:279/:329, not the AJAX handler - so the handler accepts any order regardless of payment method.)

Sinks write to the attacker-chosen order: :1073 media_handle_upload('file', order) stores an attacker-supplied file and attaches it to that order; :1077-1079 set receipt_uploaded_attachment_id and receipt_upload_status = "pending"; :1082-1083 if ("none" != status_receipt_awaiting_approval) order->set_status(...) changes the order's MAIN status when the documented peprobacsru_status_on_receipt_awaiting_approval mapping is configured.

Impact: an unauthenticated attacker attaches arbitrary (whitelisted-image) files to, and tampers the receipt-workflow metadata of, ANY WooCommerce order they do not own. When the approval-status mapping is configured, the same request also flips that order's main status (demonstrated processing -> on-hold), disrupting fulfilment/accounting. WooCommerce order ids are sequential integers, so this is store-wide in principle (theoretical amplifier, not exercised).

Not RCE: file type is checked by mime_content_type() against an admin whitelist (default image/jpeg, image/png, image/bmp - :768; PDF is not a default) and WordPress core wp_handle_upload blocks executable extensions; impact is unauthenticated data tampering + arbitrary file attachment, not code execution.

CWE-862 (Missing Authorization) + CWE-639 (IDOR / authorization bypass through user-controlled key). Proposed severity: CVSS 3.1 5.3 Medium (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N) in the default configuration; conditional High 7.5 (I:H) only when the approval-status mapping is configured (which adds the order main-status flip).

Remediation: after the nonce check, enforce authorization on the target order - require the requester to be the order's customer (compare wc_get_order(id)->get_customer_id() to get_current_user_id()) or present a valid per-order token. Do not treat a public nonce as authorization.

Proof of Concept

Affects Plugins

References

Classification

Type
IDOR
CWE

Miscellaneous

Original Researcher
Lyris Vale
Submitter
Lyris Vale
Submitter website
Verified
Yes

Timeline

Publicly Published
2026-07-29 (about 7 days ago)
Added
2026-07-22 (about 14 days ago)
Last Updated
2026-07-22 (about 14 days ago)

Other