CVE-2026-33661: 
PHP vulnerability analysis and mitigation

Overview

CVE-2026-33661 is an authentication bypass vulnerability in the yansongda/pay PHP payment SDK that allows unauthenticated attackers to forge WeChat Pay callback notifications by manipulating the HTTP Host header. The verify_wechat_sign() function in src/Functions.php unconditionally skips RSA signature verification when the PSR-7 request's host resolves to localhost, a value fully controlled by the attacker via the Host HTTP header. The same bypass also affects verify_paypal_webhook_sign() and verify_stripe_webhook_sign() in the same library. All versions up to and including 3.7.19 are affected; version 3.7.20 contains the fix. The GitHub Advisory Database rates this High (CVSS v3.1 score 7.5 per NVD/Feedly; the vendor's own advisory scores it Moderate at 5.3) (GitHub Advisory, Security Advisory).

Technical details

The root cause is CWE-290 (Authentication Bypass by Spoofing): the library contains a hardcoded development shortcut that skips all cryptographic verification when the request host equals localhost (GitHub Advisory). In PSR-7 implementations such as Nyholm and Guzzle PSR-7, $request->getUri()->getHost() reads directly from the attacker-supplied Host HTTP header, making the bypass trivially exploitable over the network with no privileges required. The vulnerable code block in src/Functions.php (lines 243–246 pre-patch) is:

if ($message instanceof ServerRequestInterface && 'localhost' === $message->getUri()->getHost()) {
    return; // No signature verified!
}

The fix (commit 26987eb) removes this conditional entirely, ensuring openssl_verify() is always called (Patch Commit).

Impact

Successful exploitation enables payment fraud: an attacker can send a crafted HTTP POST to a merchant's WeChat Pay (or PayPal/Stripe) callback endpoint with a forged Host: localhost header and a fabricated TRANSACTION.SUCCESS payload, causing the application to mark orders as paid without any actual payment being made (GitHub Advisory). The integrity impact is high — order and payment state can be manipulated — while confidentiality and availability are unaffected. Real-world exposure is partially mitigated in environments where Nginx, Ingress controllers, Cloudflare, or WAFs strip or reject non-canonical Host headers before the request reaches the application (Security Advisory).

Exploitability

A public proof-of-concept exploit (a single curl command) is included in the official security advisory and requires no authentication, special tools, or prior access (Security Advisory). The EPSS score is approximately 0.017% (4th percentile), indicating low current exploitation probability. There is no evidence of in-the-wild exploitation or threat actor attribution at this time, and the vulnerability is not listed in the CISA KEV catalog (GitHub Advisory).

Exploitation steps

  1. Identify target: Locate a merchant application using yansongda/pay ≤ 3.7.19 with an exposed WeChat Pay callback endpoint (e.g., /payment/wechat/callback).
  2. Craft the request: Construct an HTTP POST request to the callback URL with the Host header set to localhost to trigger the bypass condition in verify_wechat_sign().
  3. Forge the payload: Include arbitrary values for Wechatpay-Serial, Wechatpay-Timestamp, Wechatpay-Nonce, and Wechatpay-Signature headers — their values are irrelevant since verification is skipped.
  4. Send the forged callback: Execute the request:
curl -X POST https://merchant.example.com/payment/wechat/callback \
  -H "Host: localhost" \
  -H "Content-Type: application/json" \
  -H "Wechatpay-Serial: any" \
  -H "Wechatpay-Timestamp: 1234567890" \
  -H "Wechatpay-Nonce: abc" \
  -H "Wechatpay-Signature: AAAA" \
  -d '{"id":"fake-order","event_type":"TRANSACTION.SUCCESS"}'
  1. Achieve fraud: verify_wechat_sign() returns immediately without RSA verification; the application processes the fake notification and marks the order as paid (Security Advisory).

Indicators of compromise

  • Network: Inbound HTTP POST requests to WeChat Pay/PayPal/Stripe callback endpoints containing a Host: localhost header while the actual destination IP/domain is a public-facing server; requests with arbitrary or obviously invalid Wechatpay-Signature values (e.g., single characters like AAAA).
  • Logs: Web server access logs showing POST requests to callback paths (e.g., /payment/wechat/callback) with Host: localhost from external IP addresses; application logs recording successful payment callback processing for orders with no corresponding upstream payment record.
  • Application: Orders marked as paid in the database without a matching transaction ID verifiable against the WeChat Pay API; duplicate or replayed callback events for the same order ID with differing source IPs (GitHub Advisory).

Mitigation and workarounds

Upgrade yansongda/pay to version 3.7.20 or later, which removes the localhost bypass from verify_wechat_sign(), verify_paypal_webhook_sign(), and verify_stripe_webhook_sign() (Release v3.7.20, Patch Commit). As a temporary workaround, configure Nginx, a WAF, or an API gateway to reject or rewrite requests where the Host header does not match the expected merchant domain before they reach the application. Additionally, implement independent server-side order verification against the WeChat Pay API to confirm payment status rather than relying solely on callback data (GitHub Advisory).

Community reactions

The vulnerability received coverage from The Hacker Wire and Yazoul security advisory sites shortly after disclosure (The Hacker Wire, Yazoul Advisory). Community reaction has been measured; the advisory itself notes that most production environments using Nginx, Cloudflare, or WAFs are naturally protected, which has tempered alarm. The fix was released the same day as the advisory (March 23, 2026), limiting the window of exposure (Release v3.7.20).

Additional resources


Source: This report was generated using AI

Related PHP vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-55224HIGH8.7
  • PHP logoPHP
  • mineadmin/mineadmin
NoYesSep 30, 2026
CVE-2026-103111HIGH7.6
  • MariaDB Server logoMariaDB Server
  • mariadb11.8-server
NoYesSep 30, 2026
GHSA-3q6v-r5mr-hxv8HIGH7.5
  • PHP logoPHP
  • league/commonmark
NoYesSep 30, 2026
GHSA-97jj-33gv-5xf9MEDIUM6.1
  • PHP logoPHP
  • league/commonmark
NoYesSep 30, 2026
CVE-2026-104181MEDIUM5.4
  • PHP logoPHP
  • filament/filament
NoYesOct 01, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management