Skip to main content

AVideo CVE-2026-33731

| EUVDEUVD-2026-45041 MEDIUM
Insufficient Verification of Data Authenticity (CWE-345)
2026-06-22 https://github.com/WWBN/AVideo GHSA-95jh-7r58-xmxw
6.5
CVSS 3.1 · Vendor: https://github.com/WWBN/AVideo
Share

Severity by source

Vendor (https://github.com/WWBN/AVideo) PRIMARY
6.5 MEDIUM
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
vuln.today AI
6.5 MEDIUM

Network-accessible endpoint requires only a low-privileged account (one real purchase); no confidentiality or availability impact, but complete wallet-integrity bypass.

3.1 AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
4.0 AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/WWBN/AVideo).

CVSS VectorVendor: https://github.com/WWBN/AVideo

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 22, 2026 - 20:18 vuln.today
Analysis Generated
Jun 22, 2026 - 20:18 vuln.today

DescriptionCVE.org

Summary

The Authorize.Net webhook handler at plugin/AuthorizeNet/webhook.php contains a signature verification bypass that allows an attacker to forge webhook requests with arbitrary payment amounts and target user IDs. By supplying a valid transaction ID from a small legitimate purchase, the attacker bypasses signature validation and credits arbitrary wallet balances to any user account via attacker-controlled payload fields.

Details

Three flaws combine into an exploit chain:

1. Signature Bypass via OR Logic (webhook.php:33)

php
if (!$parsed['signatureValid'] && (empty($txnInfo) || !empty($txnInfo['error']))) {
    http_response_code(401);
    echo 'invalid signature';
    exit;
}

The webhook is rejected only when both conditions are true: the signature is invalid AND the transaction lookup fails. If the attacker supplies a real transaction ID (e.g., from their own $1 purchase), getTransactionDetails() succeeds and returns valid data, so the second condition is false. The invalid signature is silently ignored.

2. Payload Values Override API-Fetched Values (AuthorizeNet.php:169-171, webhook.php:44-48)

In analyzeTransactionFromWebhook(), users_id and amount are extracted from the attacker-controlled webhook payload first:

php
$users_id = isset($metadata['users_id']) ? (int)$metadata['users_id'] : null;
$amount   = isset($payload['amount']) ? (float)$payload['amount'] : ...;

The fallback logic in webhook.php only applies when the analysis values are empty/falsy:

php
if (!$analysis['users_id'] && !empty($txnInfo['users_id'])) {
    $analysis['users_id'] = (int)$txnInfo['users_id'];
}
if (!$analysis['amount'] && isset($txnInfo['amount'])) {
    $analysis['amount'] = (float)$txnInfo['amount'];
}

Since the forged payload already provides both values, the authoritative API-fetched values are never used.

3. Missing Approval Check (webhook.php:61-75)

The code checks only that users_id and amount are non-empty before calling processSinglePayment(). The isApproved field is computed in analyzeTransactionFromWebhook() (line 222-228) but never verified before crediting the wallet at line 68-75.

PoC

Prerequisites: Attacker has a low-privileged account on the AVideo instance and has made at least one legitimate small Authorize.Net purchase (e.g., $1.00), noting the transaction ID (e.g., 60123456789).

  1. Immediately after the purchase completes (to race the legitimate webhook), send a forged webhook:
bash
curl -X POST https://target.com/plugin/AuthorizeNet/webhook.php \
  -H 'Content-Type: application/json' \
  -d '{
    "eventType": "net.authorize.payment.authcapture.created",
    "payload": {
      "id": "60123456789",
      "amount": 99999.99,
      "responseCode": 1,
      "metadata": {
        "users_id": 2
      }
    }
  }'
  1. The signature check fails (no X-ANET-Signature header), but getTransactionDetails('60123456789') succeeds because it is a real transaction. The OR condition on line 33 is not fully satisfied, so execution continues.
  2. analyzeTransactionFromWebhook() uses the forged payload's amount: 99999.99 and metadata.users_id: 2.
  3. processSinglePayment() credits $99,999.99 to user ID 2's wallet via addBalance().
  4. The dedup key is sha1('net.authorize.payment.authcapture.created' . '60123456789'), so the legitimate webhook arriving later is silently discarded as a duplicate.
  5. The attacker can repeat with new transaction IDs from additional small purchases for cumulative balance inflation.

Impact

  • Wallet balance inflation: Attacker credits arbitrary amounts to any user's wallet without corresponding payment, bypassing the payment gateway's actual charge amount.
  • Premium content access: Inflated wallet balance allows purchasing all paid/premium video content without real payment.
  • Subscription fraud: By including plans_id in forged metadata, the attacker can activate premium subscriptions (webhook.php:86-134) without corresponding payment.
  • Financial loss: Platform owner loses revenue from fraudulently accessed premium content and services.

Recommended Fix

1. Reject webhooks with invalid signatures unconditionally - the transaction lookup should only be used for data enrichment *after* signature validation passes:

php
// webhook.php line 33 - FIX: reject on invalid signature alone
if (!$parsed['signatureValid']) {
    _error_log('[Authorize.Net webhook] Bad signature');
    http_response_code(401);
    echo 'invalid signature';
    exit;
}

2. Use API-fetched values as authoritative - in webhook.php lines 44-55, invert the precedence so $txnInfo values always override payload values:

php
// Always prefer API-fetched values over payload values
if (!empty($txnInfo['users_id'])) {
    $analysis['users_id'] = (int)$txnInfo['users_id'];
}
if (isset($txnInfo['amount'])) {
    $analysis['amount'] = (float)$txnInfo['amount'];
}

3. Check isApproved before processing - add a gate before processSinglePayment():

php
if (!$analysis['isApproved']) {
    _error_log('[Authorize.Net webhook] Transaction not approved');
    http_response_code(400);
    echo 'transaction not approved';
    exit;
}

AnalysisAI

Wallet balance inflation in AVideo's Authorize.Net payment plugin (versions <= 28.0) allows a low-privileged attacker to credit arbitrary amounts to any user account by forging webhook requests. Three code flaws chain together: a logical OR in the signature check lets a real transaction ID bypass HMAC validation entirely, attacker-controlled payload fields take precedence over authoritative API-fetched amounts and user IDs, and the payment approval status is never verified before crediting the wallet. A detailed proof-of-concept with working curl commands is publicly documented in GitHub Advisory GHSA-95jh-7r58-xmxw. No confirmed active exploitation (CISA KEV) at time of analysis, but the PoC lowers the bar to exploitation significantly.

Technical ContextAI

AVideo is a self-hosted PHP video platform (pkg:composer/wwbn/avideo). Its Authorize.Net payment plugin exposes a public-facing webhook endpoint at plugin/AuthorizeNet/webhook.php that receives payment event callbacks. Webhook authenticity is supposed to be enforced via HMAC-SHA512 over the raw request body using the Authorize.Net Signature Key, transmitted in the X-ANET-Signature header. CWE-345 (Insufficient Verification of Data Authenticity) describes all three root causes: (1) the rejection gate at webhook.php:33 uses AND logic rather than OR - a missing or invalid signature is only fatal when combined with a failed transaction lookup, meaning a real transaction ID silently neutralizes the signature check; (2) analyzeTransactionFromWebhook() at AuthorizeNet.php:169-171 extracts users_id and amount from the untrusted JSON payload before falling back to the Authorize.Net API response, so attacker-supplied values are always used; (3) the isApproved flag computed at line 222-228 is never evaluated as a gate before processSinglePayment() is called at lines 68-75, allowing credits for declined or pending transactions. The affected CPE is pkg:composer/wwbn/avideo up to and including version 28.0.

RemediationAI

Upgrade AVideo to version 29.0 or later, which resolves all three flaws via commit 033e83ae904cacb99495dbea7cbcfb3738cf42e4 (https://github.com/WWBN/AVideo/commit/033e83ae904cacb99495dbea7cbcfb3738cf42e4). The patch unconditionally rejects webhooks with invalid HMAC-SHA512 signatures before any transaction lookup occurs, inverts value precedence so API-fetched amounts and user IDs always override payload values, and fixes case-insensitive status string comparison for the approval check. If immediate upgrade is not feasible, the highest-value compensating control is to block external access to plugin/AuthorizeNet/webhook.php via web server ACLs or firewall rules, restricting inbound requests to Authorize.Net's published webhook source IP ranges only - this prevents forged webhooks entirely but requires ongoing maintenance as Authorize.Net's IP list changes. Alternatively, disabling the Authorize.Net plugin entirely stops exploitation at the cost of halting payment processing. There is no known safe workaround that preserves full payment functionality without upgrading. See the full advisory at https://github.com/WWBN/AVideo/security/advisories/GHSA-95jh-7r58-xmxw.

More in PHP

View all
CVE-2019-11043 CRITICAL POC
9.8 Oct 28

In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 in certain configurations of FPM setup it

CVE-2012-1823 CRITICAL POC
9.8 May 11

sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not

CVE-2016-1555 CRITICAL POC
9.8 Apr 21

(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear

CVE-2018-11138 CRITICAL POC
9.8 May 31

The '/common/download_agent_installer.php' script in the Quest KACE System Management Appliance 8.0.318 is accessible by

CVE-2024-11680 CRITICAL POC
9.8 Nov 26

ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C

CVE-2025-49113 CRITICAL POC
9.9 Jun 02

Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au

CVE-2017-9841 CRITICAL POC
9.8 Jun 27

Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP c

CVE-2025-0108 HIGH POC
8.8 Feb 12

Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers

CVE-2021-25298 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2021-25296 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2013-4983 CRITICAL POC
10.0 Sep 10

The get_referers function in /opt/ws/bin/sblistpack in Sophos Web Appliance before 3.7.9.1 and 3.8 before 3.8.1.1 allows

CVE-2023-6553 CRITICAL POC
9.8 Dec 15

The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1

Share

CVE-2026-33731 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy