[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fb9VlGg6ElqWP796fDpxmMpN6tUeF9vLK2Jz2soKqHoA":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":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":32,"research_vulnerable_code":33,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"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":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":39},"CVE-2026-49064","payment-forms-buy-now-buttons-and-invoicing-system-getpaid-unauthenticated-information-exposure","Payment forms, Buy now buttons, and Invoicing System | GetPaid \u003C= 2.8.49 - Unauthenticated Information Exposure","The Payment forms, Buy now buttons, and Invoicing System | GetPaid plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.8.49. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.","invoicing",null,"\u003C=2.8.49","2.8.50","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Exposure of Sensitive Information to an Unauthorized Actor","2026-06-08 00:00:00","2026-06-18 13:40:56",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fb83e3fdc-6d16-48c5-8773-f2d053944584?source=api-prod",11,[22,23,24,25,26,27],"includes\u002Fclass-wpinv-ajax.php","includes\u002Fwpinv-template-functions.php","invoicing.php","languages\u002Finvoicing-en_US.po","languages\u002Finvoicing.pot","readme.txt","researched",false,3,"# Vulnerability Research Plan: CVE-2026-49064 (GetPaid Information Exposure)\n\n## 1. Vulnerability Summary\nThe **Payment forms, Buy now buttons, and Invoicing System | GetPaid** plugin (\u003C= 2.8.49) contains an unauthenticated information exposure vulnerability. The plugin's AJAX handler routing logic in `WPInv_Ajax::do_wpinv_ajax` allows unauthenticated users to trigger specific internal actions via the `wpinv-ajax` query parameter. \n\nSeveral actions, specifically `get_payment_form` and `payment_form`, are registered as unauthenticated hooks (`$nopriv => true` in `WPInv_Ajax::add_ajax_events`). When these actions are called for an existing invoice ID, the plugin renders a payment form pre-filled with the customer's sensitive billing information (First Name, Last Name, Email, Address, Phone, VAT Number) without verifying that the requester is the owner of the invoice or an authorized administrator.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: Frontend root with query parameter `\u002F?wpinv-ajax=ACTION` (handled by `WPInv_Ajax::do_wpinv_ajax` on the `template_redirect` hook).\n- **Action**: `get_payment_form`\n- **Method**: `GET` or `POST` (GetPaid typically uses `$_REQUEST`).\n- **Required Parameters**:\n    - `wpinv-ajax`: `get_payment_form`\n    - `invoice_id`: The ID of the invoice to exploit.\n    - `_wpnonce`: The `wpinv-nonce` (required by GetPaid's AJAX handlers).\n- **Authentication**: Unauthenticated.\n- **Preconditions**: An invoice must exist in the system, and the attacker must obtain a valid `wpinv-nonce` (which is publicly exposed on pages containing GetPaid shortcodes).\n\n## 3. Code Flow\n1.  **Entry Point**: A request is made to `\u002F?wpinv-ajax=get_payment_form`.\n2.  **Trigger**: `WPInv_Ajax::init()` hooks `do_wpinv_ajax()` to `template_redirect`.\n3.  **Routing**: `do_wpinv_ajax()` reads `$_GET['wpinv-ajax']`, sets the query var, and executes `do_action( 'wpinv_ajax_get_payment_form' )`.\n4.  **Hook Registration**: In `WPInv_Ajax::add_ajax_events()`, the loop identifies `get_payment_form` as a `$nopriv` action and adds:\n    `add_action( 'wpinv_ajax_get_payment_form', array( __CLASS__, 'get_payment_form' ) );`\n5.  **Execution**: `WPInv_Ajax::get_payment_form()` (not fully shown in snippet, but inferred) retrieves the invoice object using the provided `invoice_id` and calls `wpinv_get_payment_form()` or a similar template function.\n6.  **Information Leak**: The template functions (e.g., `getpaid_invoice_details_main` in `includes\u002Fwpinv-template-functions.php`) render the invoice data. When rendering a payment form for an existing invoice, the customer's billing metadata (stored in `wp_postmeta`) is extracted and placed into the `value` attributes of the HTML form inputs.\n\n## 4. Nonce Acquisition Strategy\nThe `wpinv-nonce` is required for AJAX requests but is available to unauthenticated users on any page that initializes GetPaid scripts.\n\n1.  **Identify Trigger**: GetPaid enqueues `wpinv_vars` (containing the nonce) on pages using the `[getpaid_payment_form]` shortcode.\n2.  **Setup Page**: Create a public page containing the shortcode.\n    ```bash\n    wp post create --post_type=page --post_title=\"Payment Page\" --post_status=publish --post_content='[getpaid_payment_form]'\n    ```\n3.  **Navigate**: Use `browser_navigate` to visit the newly created page.\n4.  **Extract**: Use `browser_eval` to extract the nonce from the localized JavaScript variable.\n    - **Variable**: `wpinv_vars`\n    - **Key**: `nonce`\n    - **JS Command**: `window.wpinv_vars?.nonce`\n\n## 5. Exploitation Strategy\n### Step 1: Discover Target Invoice ID\nInvoices are a custom post type (`wpinv_invoice`). An attacker can enumerate IDs or look for existing IDs in the environment.\n\n### Step 2: Perform the Information Leak Request\nOnce the `wpinv-nonce` is obtained, send a request to the `wpinv-ajax` endpoint.\n\n- **Request Type**: `http_request`\n- **Method**: `GET`\n- **URL**: `http:\u002F\u002Fvulnerable.test\u002F?wpinv-ajax=get_payment_form&invoice_id=\u003CTARGET_ID>&_wpnonce=\u003CNONCE>`\n- **Note**: If `invoice_id` fails, try `post_id` as the parameter name (used interchangeably in some GetPaid versions).\n\n### Step 3: Parse Response\nThe response will be HTML. The attacker looks for input fields containing customer data:\n- `\u003Cinput ... name=\"first_name\" value=\"[SENSITIVE]\">`\n- `\u003Cinput ... name=\"email\" value=\"[SENSITIVE]\">`\n- `\u003Cinput ... name=\"address\" value=\"[SENSITIVE]\">`\n\n## 6. Test Data Setup\n1.  **Create a Customer User**:\n    ```bash\n    wp user create victim victim@example.com --role=subscriber --","The GetPaid plugin for WordPress is vulnerable to unauthenticated sensitive information exposure via the 'get_payment_form' AJAX action. An attacker can provide an arbitrary invoice ID to retrieve a payment form pre-filled with a customer's billing details, including their name, email, physical address, and phone number, without authorization.","\u002F\u002F includes\u002Fclass-wpinv-ajax.php (~line 118 in add_ajax_events)\n'get_payment_form'              => true,\n\n\u002F\u002F ... \n\n\u002F\u002F includes\u002Fclass-wpinv-ajax.php (~line 333 in get_payment_form)\n} elseif ( ! empty( $_GET['invoice'] ) ) {\n\tgetpaid_display_invoice_payment_form( (int) urldecode( $_GET['invoice'] ) );\n} else {\n\n---\n\n\u002F\u002F includes\u002Fwpinv-template-functions.php (~line 1286)\nfunction getpaid_display_invoice_payment_form( $invoice_id ) {\n\n    $invoice = wpinv_get_invoice( $invoice_id );\n\n    if ( empty( $invoice ) ) {\n\t\taui()->alert(\n\t\t\tarray(\n\t\t\t\t'type'    => 'warning',\n\t\t\t\t'content' => __( 'Invoice not found', 'invoicing' ),\n            ),\n            true\n        );\n        return;\n    }\n\n    if ( $invoice->is_paid() ) {\n\t\taui()->alert(\n\t\t\tarray(\n\t\t\t\t'type'    => 'warning',\n\t\t\t\t'content' => __( 'Invoice has already been paid', 'invoicing' ),\n            ),\n            true\n        );\n        return;\n    }\n\n    $form = new GetPaid_Payment_Form( wpinv_get_default_payment_form() );\n    $form->invoice = $invoice;\n    $form->set_items( $invoice->get_items() );\n\n    $form->display();\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.49\u002Fincludes\u002Fclass-wpinv-ajax.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.50\u002Fincludes\u002Fclass-wpinv-ajax.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.49\u002Fincludes\u002Fclass-wpinv-ajax.php\t2025-11-27 14:43:32.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.50\u002Fincludes\u002Fclass-wpinv-ajax.php\t2026-06-05 11:09:32.000000000 +0000\n@@ -328,10 +328,21 @@\n \t\t\t} else {\n \t\t\t\tgetpaid_display_payment_form( $form );\n \t\t\t}\n-} elseif ( ! empty( $_GET['invoice'] ) ) {\n-\t\t    getpaid_display_invoice_payment_form( (int) urldecode( $_GET['invoice'] ) );\n-        } else {\n+\t\t} else if ( ! empty( $_GET['invoice'] ) ) {\n+\t\t\tif ( ! ( ! empty( $_REQUEST['_ajax_nonce'] ) && wp_verify_nonce( sanitize_text_field( $_REQUEST['_ajax_nonce'] ), 'getpaid_form_nonce' ) ) ) {\n+\t\t\t\taui()->alert(\n+\t\t\t\t\tarray(\n+\t\t\t\t\t\t'type'    => 'warning',\n+\t\t\t\t\t\t'content' => __( 'You are not allowed to perform this action.', 'invoicing' ),\n+\t\t\t\t\t),\n+\t\t\t\t\ttrue\n+\t\t\t\t);\n+\n+\t\t\t\texit;\n+\t\t\t}\n+\n+\t\t\tgetpaid_display_invoice_payment_form( (int) urldecode( $_GET['invoice'] ) );\n+\t\t} else {\n \t\t\t$items = getpaid_convert_items_to_array( sanitize_text_field( urldecode( $_GET['item'] ) ) );\n \t\t    getpaid_display_item_payment_form( $items );\n-        }\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.49\u002Fincludes\u002Fwpinv-template-functions.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.50\u002Fincludes\u002Fwpinv-template-functions.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.49\u002Fincludes\u002Fwpinv-template-functions.php\t2026-06-04 14:56:46.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Finvoicing\u002F2.8.50\u002Fincludes\u002Fwpinv-template-functions.php\t2026-06-05 11:09:32.000000000 +0000\n@@ -1284,36 +1284,46 @@\n  * Helper function to display an invoice payment form on the frontend.\n  *\u002F\n function getpaid_display_invoice_payment_form( $invoice_id ) {\n-\n-    $invoice = wpinv_get_invoice( $invoice_id );\n-\n-    if ( empty( $invoice ) ) {\n+\t$invoice = wpinv_get_invoice( $invoice_id );\n \n+\tif ( empty( $invoice ) ) {\n \t\taui()->alert(\n \t\t\tarray(\n \t\t\t\t'type'    => 'warning',\n \t\t\t\t'content' => __( 'Invoice not found', 'invoicing' ),\n-            ),\n-            true\n-        );\n-        return;\n-    }\n+\t\t\t),\n+\t\t\ttrue\n+\t\t);\n+\t\treturn;\n+\t}\n+\n+\tif ( ! wpinv_user_can_view_invoice( $invoice ) ) {\n+\t\taui()->alert(\n+\t\t\tarray(\n+\t\t\t\t'type'    => 'warning',\n+\t\t\t\t'content' => __( 'You are not allowed to view this invoice.', 'invoicing' ),\n+\t\t\t),\n+\t\t\ttrue\n+\t\t);\n+\t\treturn;\n+\t}\n \n-    if ( $invoice->is_paid() ) {\n+\tif ( $invoice->is_paid() ) {\n \t\taui()->alert(\n \t\t\tarray(\n \t\t\t\t'type'    => 'warning',\n \t\t\t\t'content' => __( 'Invoice has already been paid', 'invoicing' ),\n-            ),\n-            true\n-        );\n-        return;\n-    }\n-\n-    $form = new GetPaid_Payment_Form( wpinv_get_default_payment_form() );\n-    $form->invoice = $invoice;\n-    $form->set_items( $invoice->get_items() );\n+\t\t\t),\n+\t\t\ttrue\n+\t\t);\n+\t\treturn;\n+\t}\n+\n+\t$form = new GetPaid_Payment_Form( wpinv_get_default_payment_form() );\n+\t$form->invoice = $invoice;\n+\t$form->set_items( $invoice->get_items() );\n \n-    $form->display();\n+\t$form->display();\n }","The exploit involves three main steps: nonce acquisition, invoice discovery, and data extraction. An attacker first obtains a valid 'wpinv-nonce' (or 'wpinv_vars.nonce' in newer JS localization) by visiting any public page on the target site that uses a GetPaid shortcode, such as [getpaid_payment_form]. Next, the attacker identifies a target invoice ID, which can be discovered via ID enumeration or other leaks. Finally, the attacker sends an unauthenticated GET or POST request to the root frontend URL with the query parameters 'wpinv-ajax=get_payment_form', 'invoice=\u003CTARGET_ID>', and the obtained nonce. The server's response contains the HTML for a payment form where customer billing metadata (Name, Email, Address, Phone, VAT number) is automatically populated into the 'value' attributes of form input fields, allowing the attacker to harvest the sensitive data from the response body.","gemini-3-flash-preview","2026-06-26 02:50:59","2026-06-26 02:51:52",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","2.8.49","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Finvoicing\u002Ftags\u002F2.8.49","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Finvoicing.2.8.49.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Finvoicing\u002Ftags\u002F2.8.50","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Finvoicing.2.8.50.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Finvoicing\u002Ftags"]