针对未认证的 Hyperswitch Worldpayxml webhook 漏洞(CWE-345/306)的概念验证,该漏洞可伪造 SETTLED XML,从而在未经 PSP 捕获的情况下将支付标记为成功。
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · hyperswitch-unsigned-webhook
Hyperswitch 2026.09.21.0 - Juspay
Worldpayxml::verify_webhook_source 返回 Ok(true),并附有一条注释称验证通过 mTLS 完成。该路由上并没有 mTLS。该函数忽略请求体和请求头。incoming.rs 随后信任 source_verified,并在没有 PSync 的情况下执行 HandleResponse。LastEvent::Settled 映射为 PaymentIntentSuccess。默认的 IncomingWebhook 算法是 NoAlgorithm。BitPay 和 Shift4 继承该行为。Worldpayxml 甚至走不到那一步。它直接短路了。
未认证的伪造 SETTLED XML 即可将支付标记为成功。没有 Worldpay 捕获。没有客户端证书。
| ID | 暂无 CVE |
| CWE | CWE-345、CWE-306 |
| CVSS | 高危:7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N |
| 产品 | Hyperswitch |
| 受影响版本 | 截至 2026.09.21.0 的 Worldpayxml 入站 webhook |
| 认证 | 无需认证;需要 merchant_id 和 orderCode |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅限 127.0.0.1 |
需要 merchant_id(出现在每个 Hyperswitch 仪表盘 URL 中)以及等于该尝试的 connector_transaction_id 的 orderCode。向 /webhooks/{merchant_id}/worldpayxml POST 未签名的 SETTLED。如果 source_verified 为 false,incoming 会执行 Trigger 并对连接器进行 PSync。Worldpayxml 从不走这条路径。支付意图变为 Charged。实验环境:status=succeeded。伪造 XML。没有 PSP。
猜测支付 ID 不是漏洞。为你已经看到的 ID 伪造 SETTLED 才是。不是 shell。不是真实的 Worldpay 结算。
同一产品,不同漏洞:payout confirm unbound client_secret。
我读了 Ok(true),然后是 HandleResponse 与 Trigger 的对比,再是 Settled -> PaymentIntentSuccess。注释说是 mTLS。实验环境的 POST 没有客户端证书。
第一个看到这一点的客户端会针对 requires_confirmation POST webhook。Incoming 不会将尚未离开确认状态的支付变为 Charged。给该尝试打上标记,或者等到 requires_capture / processing。实验环境执行打标记。该标记是实验环境的固定装置。真实尝试已经有连接器 ID。而 webhook 没有。
已记录的弯路:在真正执行验证的连接器上使用签名 HMAC(这条路径不验证);将 webhook HTTP 200 当作判定依据(轮询 GET /payments/{id} 直到 status=succeeded);orderCode 不是 connector_transaction_id;反弹 shell。都是做戏。
然后:商户、API 密钥、worldpayxml MCA、使用 confirm=false 的支付、打上 connector_transaction_id 标记、未签名 SETTLED、检索。
cd lab
./run.sh
目标仅限 http://127.0.0.1:18082。run.sh 将标签 2026.09.21.0 克隆到 lab/hyperswitch-src 以获取配置和迁移。
IOC status_before=requires_confirmation
IOC webhook status=200 unsigned lastEvent=SETTLED
IOC poll status=succeeded
SUCCESS Hyperswitch unsigned Worldpayxml webhook Charged
验证 Worldpay 通知(签名 / 该路由实际终止的 mTLS)。不要对从空操作返回 Ok(true) 的连接器执行 HandleResponse。未签名的 SETTLED 不得将支付意图变为成功。
worldpayxml.rs · transformers.rs · incoming.rs · webhooks.rs · crypto.rsGNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。无担保。