Business logic of the attack: why to fake webhook PayPal
Webhooks - callbacks that the payment gateway notifies the store about changing the status of the transaction. PayPal sends a POST request for a URL registered by the seller, with payment data: amount, status, transaction ID. If the store does not verify that the request came from PayPal - anyone can form a fake webhook with arbitrary data. That's the whole bug.
MOTIVATION of the attacker on MITRE ATT&CK - T1657 (Financial Theft, Impact):
Submit a fake webhook with payment_status=Completedthe website with WPForms
Plugin obediently marks entry as paid
The attacker receives the goods or service free of charge
According to CISA (SSVC Decision: Track*), the attack is automated (Automatable: yes), PoC exists (Exploitation: poc), technical impact partial (Technical Impact: partial). One script goes through thousands of WordPress sites with WPForms and replaces transaction statuses. EPSS at the same time 0.0033 (percentile 0.2398) - the probability of active operation in the next 30 days is below the median. But the very presence of PoC and automation make the threat quite specific to each vulnerable site. Here is not "maybe someday," but "script is already written."
Disassembly of WPForms vulnerability: CVE-2026-4986
WPForms plugin to version 1.10.0.5 does not verify the authenticity of PayPal webhook events before processing. An unauthenticated attacker fakes webhook-payload and changes the status of payment of an arbitrary transaction.
CWE-862 (Missing Authorization) - webhook-endpoint does not authorize the source of the request. By OWASP Top 10 (2021) this A08: Software and Data Integrity Failures - the code does not protect the integrity of payment notifications. In parallel, it is affected A07: Identification and Authentication Failures - there is no verification of the identity of the sender at all.
CVSS vector and severity
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - score 5.3 (MEDIUM).
Let's look at the components:
AV:N (Network) - the attack is remote, enough HTTP request
AC:L (Low Complexity) - no race conditions or pre-preparation
PR:N (No Privileges) - no authentication needed
UI:N (No User Interaction) - the victim does not press anything
S:U (Unchanged Scope) - the attack is limited to the WPForms component
C:N (No Confidentiality) - data does not leak
I:L (Low Integrity) - the status of the transaction changes, but not the whole database
A:N (No Availability) - service works
For triage command key combination - PR:N + UI:N: attack is fully automated without interaction with the user. Formally CVSS MEDIUM, but in conjunction with CISA SSVC (Track*), the vendor is required to release the patch as a priority. I see this gap between the formal near and the real danger constantly - MEDIUM on paper, and in practice thousands of shops distribute goods free of charge.
Place in kill chain
In terms of MITRE ATT&CK, the operation chain is short - from exploration to impact in two steps:
Reconnaissance - T1595.002 (Vulnerability Scanning): Massive scanning of WordPress sites for WPForms with PayPal integration
Resource Development - T1588.006 (Vulnerabilities): Obtaining information about the vulnerability, building payload
Initial Access - T1190 (Exploit Public-Facing Application): sending a fake webhook to a public endpoint
Impact - T1657 (Financial Theft): Receipt of goods or services without payment
No lateral movement, no privilege. The attacker does not need to be fixed in the system. One HTTP request solves the problem.
How to Search for WordPress Plugins Vulnerable: Recon Webhook-Endpoint
The first step is to determine what WPForms is worth with PayPal integration on the site. Signs of Passive Analysis:
HTML form markup contains CSS classes wpforms-*and attributes data-formid
In the source code of the page is connected wpforms.min.jsor wpforms-full.min.js
The version of the plugin is specified in the query parameters of the scripts (?ver=1.9.x) or in /wp-content/plugins/wpforms/readme.txt, if access is not closed
PayPal button or redirect on paypal.comafter submitting the form - means payment integration is active
Versions below 1.10.0.5 are the target. Fingerprinting through readme.txt works in about 40-50% of cases - some administrators close direct access to plugin files. Others have to be determined by indirect grounds (version in JS-files, changelog on the plugin page).
Webhook-listener WPForms registers an endpoint for accepting PayPal IPN/webhook events. A specific URL can be found in two ways: intercept callback-URL when test payment via Burp Suite or analyze the source code of the plugin in the integration directory (wpforms/src/Pro/Integrations/PayPal/). A typical pattern is a GET/POST parameter, routing a request to a PayPal notification handler.
How to Write a bug bounty Report: Reporting Structure
Finding a bug is half the job. The second is to convince the triage team that this is a real problem. On OWASP Vulnerability Disclosure Cheat Sheet, the report should contain enough details to play: HTTP requests and responses, screenshots, proof of concept. But in practice, it is not the volume that decides, but the organization of the material. I saw reports on three pages that were returned for revision, and reports on half pages that passed the triage in an hour.
Report structure for CVE-2026-4986 - six blocks:
Summary (1-2 sentences). What is broken and what impact: "WPForms plugin (< 1.10.0.5) does not verify the authenticity of incoming PayPal webhook events. An unauthenticated attacker can forge webhook payloads to manipulated payment status of transaction any."WPForms plugin (versions below 1.10.0.5) does not verify the authenticity of incoming PayPal webhook events. An unauthorized attacker can forge webhook data to change the status of any transaction.
Affected Component. Plugin version, path to vulnerable code (file and processor function), endpoint URL.
Steps to Reproduce. Step-by-step instructions, which the triager will repeat in 5 minutes: install WPForms of a specific version with PayPal addon, create a form with payment, perform a test payment to receive entry_id, send a curl request with a fake IPN, check the status in the admin panel.
Proof of Concept. HTTP request in its entirety (from Burp) and server response. Screenshots of admin panel "do" and "after." If there is an automation script.
Impact. Specific business damage: "The attacker receives goods/services without payment. The attack is automated, does not require authentication. Touches all sites with WPForms + PayPal to version 1.10.0.5."
CVSS Justification. Vector with the analysis of each component. Triagers appreciate when a researcher justifies a resistance with a reference to context, rather than just writing "Critical."
What convinces the triage team
According to the recommendations of YesWeHack and on the experience of filing on Patchstack - three factors determine whether the bug bounty report will accept the vulnerability from the first time:
Reproducibility in 5 minutes. If the triagenist does not repeat for one approach, the report goes backlog. Steps to Reproduce must be copied, without the assumptions of "you should know how to configure PayPal sandbox""You should know how to set up a PayPal 'sandbox'.". Each step is a specific team or action.
Business in the first paragraph. Not "missing authorization check""stop checking authorization", and "attacker products for free on any WPForms+PayPal site""The attacker receives products for free on any WPForms+PayPal site". Triagers are often not security specialists. As OWASP notes: "security reports may be handled by developers or IT staff who do not have a security background""Reports on security issues can be handled by developers or IT professionals who have no experience in the field of information security.". Language language language of business speeds up acceptance.
Visual evidence. Screenshot from Burp Repeater with request and response, screenshot admin panel with changed status - more convincing than any text description. Video-PoC in 30 seconds closes questions about playability. I usually write a report like this: first I take screenshots, then I build a text around them.
From report to CVE: responsible disclosure in practice
For WordPress plugins, several disclosure channels are available:
Patchstack is the largest vulnerability information platform for WordPress. Accredited CNA (CVE Numbering Authority), takes reports through a web form and coordinates with the developer
Direct to the developer - through security@or contact in readme.txt plugin. If there is no clear policy, it is worth looking for /.well-known/security.txt(RFC 9116)
HackerOne/Bugcrowd - if the vendor has a program on these platforms
The standard model is coordinated disclosure: the primary report is submitted privately, the full details are published after the patch is released. Google Project Zero gives 90 days to fix, then 30 days after the release of the patch before the technical details are published. Bentley Systems in its program indicates similar 90 days.
Typical timeline for WordPress plugin:
Day 0 - sending the report
Day 1-3 - confirmation of receipt (SLA of most programs - 2-3 working days)
Day 7-14 - confirmation of vulnerability, assignment of severity
Day 30-60 - Patch release
After the patch - request CVE, publication of the advisory
According to the study with arxiv (analysis 3798 security advisories and 4033 bug bounty reports), CVE assignments is a system problem in OSS. The researchers found 47 CVE-assigned vulnerabilities that were not in the NVD at the time. The delay between patching and appearing in the NVD is weeks, sometimes months. Dependent projects do not receive notifications on time. This should be considered when planning the disclosure.
For Russian researchers there is a nuance: WPForms - the product Awesome Motive (US). The report is in English. Bounty payments go through PayPal or bank transfer. The sanctions restrictions make it more difficult to receive remuneration for residents of the Russian Federation - KYC-procedures on foreign platforms require verification of documents, and not all platforms process Russian data. The alternative is Russian platforms (BI.ZONE Bug Bounty, Standoff 365), but for foreign WordPress plugins they are usually not applicable. Disclosure without bounty - for the sake of CVE and reputation - remains a working option. In my practice, about a third of reports on foreign products are submitted this way.
Webhooks - callbacks that the payment gateway notifies the store about changing the status of the transaction. PayPal sends a POST request for a URL registered by the seller, with payment data: amount, status, transaction ID. If the store does not verify that the request came from PayPal - anyone can form a fake webhook with arbitrary data. That's the whole bug.
MOTIVATION of the attacker on MITRE ATT&CK - T1657 (Financial Theft, Impact):
Submit a fake webhook with payment_status=Completedthe website with WPForms
Plugin obediently marks entry as paid
The attacker receives the goods or service free of charge
According to CISA (SSVC Decision: Track*), the attack is automated (Automatable: yes), PoC exists (Exploitation: poc), technical impact partial (Technical Impact: partial). One script goes through thousands of WordPress sites with WPForms and replaces transaction statuses. EPSS at the same time 0.0033 (percentile 0.2398) - the probability of active operation in the next 30 days is below the median. But the very presence of PoC and automation make the threat quite specific to each vulnerable site. Here is not "maybe someday," but "script is already written."
Disassembly of WPForms vulnerability: CVE-2026-4986
WPForms plugin to version 1.10.0.5 does not verify the authenticity of PayPal webhook events before processing. An unauthenticated attacker fakes webhook-payload and changes the status of payment of an arbitrary transaction.
CWE-862 (Missing Authorization) - webhook-endpoint does not authorize the source of the request. By OWASP Top 10 (2021) this A08: Software and Data Integrity Failures - the code does not protect the integrity of payment notifications. In parallel, it is affected A07: Identification and Authentication Failures - there is no verification of the identity of the sender at all.
CVSS vector and severity
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - score 5.3 (MEDIUM).
Let's look at the components:
AV:N (Network) - the attack is remote, enough HTTP request
AC:L (Low Complexity) - no race conditions or pre-preparation
PR:N (No Privileges) - no authentication needed
UI:N (No User Interaction) - the victim does not press anything
S:U (Unchanged Scope) - the attack is limited to the WPForms component
C:N (No Confidentiality) - data does not leak
I:L (Low Integrity) - the status of the transaction changes, but not the whole database
A:N (No Availability) - service works
For triage command key combination - PR:N + UI:N: attack is fully automated without interaction with the user. Formally CVSS MEDIUM, but in conjunction with CISA SSVC (Track*), the vendor is required to release the patch as a priority. I see this gap between the formal near and the real danger constantly - MEDIUM on paper, and in practice thousands of shops distribute goods free of charge.
Place in kill chain
In terms of MITRE ATT&CK, the operation chain is short - from exploration to impact in two steps:
Reconnaissance - T1595.002 (Vulnerability Scanning): Massive scanning of WordPress sites for WPForms with PayPal integration
Resource Development - T1588.006 (Vulnerabilities): Obtaining information about the vulnerability, building payload
Initial Access - T1190 (Exploit Public-Facing Application): sending a fake webhook to a public endpoint
Impact - T1657 (Financial Theft): Receipt of goods or services without payment
No lateral movement, no privilege. The attacker does not need to be fixed in the system. One HTTP request solves the problem.
How to Search for WordPress Plugins Vulnerable: Recon Webhook-Endpoint
The first step is to determine what WPForms is worth with PayPal integration on the site. Signs of Passive Analysis:
HTML form markup contains CSS classes wpforms-*and attributes data-formid
In the source code of the page is connected wpforms.min.jsor wpforms-full.min.js
The version of the plugin is specified in the query parameters of the scripts (?ver=1.9.x) or in /wp-content/plugins/wpforms/readme.txt, if access is not closed
PayPal button or redirect on paypal.comafter submitting the form - means payment integration is active
Versions below 1.10.0.5 are the target. Fingerprinting through readme.txt works in about 40-50% of cases - some administrators close direct access to plugin files. Others have to be determined by indirect grounds (version in JS-files, changelog on the plugin page).
Webhook-listener WPForms registers an endpoint for accepting PayPal IPN/webhook events. A specific URL can be found in two ways: intercept callback-URL when test payment via Burp Suite or analyze the source code of the plugin in the integration directory (wpforms/src/Pro/Integrations/PayPal/). A typical pattern is a GET/POST parameter, routing a request to a PayPal notification handler.
How to Write a bug bounty Report: Reporting Structure
Finding a bug is half the job. The second is to convince the triage team that this is a real problem. On OWASP Vulnerability Disclosure Cheat Sheet, the report should contain enough details to play: HTTP requests and responses, screenshots, proof of concept. But in practice, it is not the volume that decides, but the organization of the material. I saw reports on three pages that were returned for revision, and reports on half pages that passed the triage in an hour.
Report structure for CVE-2026-4986 - six blocks:
Summary (1-2 sentences). What is broken and what impact: "WPForms plugin (< 1.10.0.5) does not verify the authenticity of incoming PayPal webhook events. An unauthenticated attacker can forge webhook payloads to manipulated payment status of transaction any."WPForms plugin (versions below 1.10.0.5) does not verify the authenticity of incoming PayPal webhook events. An unauthorized attacker can forge webhook data to change the status of any transaction.
Affected Component. Plugin version, path to vulnerable code (file and processor function), endpoint URL.
Steps to Reproduce. Step-by-step instructions, which the triager will repeat in 5 minutes: install WPForms of a specific version with PayPal addon, create a form with payment, perform a test payment to receive entry_id, send a curl request with a fake IPN, check the status in the admin panel.
Proof of Concept. HTTP request in its entirety (from Burp) and server response. Screenshots of admin panel "do" and "after." If there is an automation script.
Impact. Specific business damage: "The attacker receives goods/services without payment. The attack is automated, does not require authentication. Touches all sites with WPForms + PayPal to version 1.10.0.5."
CVSS Justification. Vector with the analysis of each component. Triagers appreciate when a researcher justifies a resistance with a reference to context, rather than just writing "Critical."
What convinces the triage team
According to the recommendations of YesWeHack and on the experience of filing on Patchstack - three factors determine whether the bug bounty report will accept the vulnerability from the first time:
Reproducibility in 5 minutes. If the triagenist does not repeat for one approach, the report goes backlog. Steps to Reproduce must be copied, without the assumptions of "you should know how to configure PayPal sandbox""You should know how to set up a PayPal 'sandbox'.". Each step is a specific team or action.
Business in the first paragraph. Not "missing authorization check""stop checking authorization", and "attacker products for free on any WPForms+PayPal site""The attacker receives products for free on any WPForms+PayPal site". Triagers are often not security specialists. As OWASP notes: "security reports may be handled by developers or IT staff who do not have a security background""Reports on security issues can be handled by developers or IT professionals who have no experience in the field of information security.". Language language language of business speeds up acceptance.
Visual evidence. Screenshot from Burp Repeater with request and response, screenshot admin panel with changed status - more convincing than any text description. Video-PoC in 30 seconds closes questions about playability. I usually write a report like this: first I take screenshots, then I build a text around them.
From report to CVE: responsible disclosure in practice
For WordPress plugins, several disclosure channels are available:
Patchstack is the largest vulnerability information platform for WordPress. Accredited CNA (CVE Numbering Authority), takes reports through a web form and coordinates with the developer
Direct to the developer - through security@or contact in readme.txt plugin. If there is no clear policy, it is worth looking for /.well-known/security.txt(RFC 9116)
HackerOne/Bugcrowd - if the vendor has a program on these platforms
The standard model is coordinated disclosure: the primary report is submitted privately, the full details are published after the patch is released. Google Project Zero gives 90 days to fix, then 30 days after the release of the patch before the technical details are published. Bentley Systems in its program indicates similar 90 days.
Typical timeline for WordPress plugin:
Day 0 - sending the report
Day 1-3 - confirmation of receipt (SLA of most programs - 2-3 working days)
Day 7-14 - confirmation of vulnerability, assignment of severity
Day 30-60 - Patch release
After the patch - request CVE, publication of the advisory
According to the study with arxiv (analysis 3798 security advisories and 4033 bug bounty reports), CVE assignments is a system problem in OSS. The researchers found 47 CVE-assigned vulnerabilities that were not in the NVD at the time. The delay between patching and appearing in the NVD is weeks, sometimes months. Dependent projects do not receive notifications on time. This should be considered when planning the disclosure.
For Russian researchers there is a nuance: WPForms - the product Awesome Motive (US). The report is in English. Bounty payments go through PayPal or bank transfer. The sanctions restrictions make it more difficult to receive remuneration for residents of the Russian Federation - KYC-procedures on foreign platforms require verification of documents, and not all platforms process Russian data. The alternative is Russian platforms (BI.ZONE Bug Bounty, Standoff 365), but for foreign WordPress plugins they are usually not applicable. Disclosure without bounty - for the sake of CVE and reputation - remains a working option. In my practice, about a third of reports on foreign products are submitted this way.