GHSA-9392-PJ54-QQF8

Vulnerability from github – Published: 2026-06-04 18:47 – Updated: 2026-06-04 18:47
VLAI
Summary
WWBN AVideo: Authenticated wallet credit bypass in AuthorizeNet processPayment endpoint
Details

Summary

plugin/AuthorizeNet/processPayment.json.php credits the logged-in user's wallet based only on the attacker-controlled amount POST parameter.

The endpoint contains a TODO for real Authorize.Net charging, hardcodes $paymentSuccess = true, and then calls YPTWallet::addBalance() without validating any Authorize.Net transaction, webhook signature, hosted payment token, nonce, or server-side payment record.

This allows any logged-in user to add arbitrary funds to their own AVideo wallet when the AuthorizeNet and YPTWallet plugins are enabled.

### Details

Affected file:

plugin/AuthorizeNet/processPayment.json.php

Relevant code:

```php $amount = isset($_POST['amount']) ? floatval($_POST['amount']) : 0; $userData = isset($_POST['userData']) ? $_POST['userData'] : [];

if ($amount <= 0) { echo json_encode(['error' => 'Invalid amount']); exit; }

// TODO: Implement payment logic using Authorize.Net API // Example: Call Authorize.Net API here // $result = $plugin->chargePayment($amount, $userData);

// Simulate payment success for now $paymentSuccess = true; $users_id = @User::getId();

if ($paymentSuccess && !empty($users_id)) { $walletPlugin = AVideoPlugin::loadPluginIfEnabled("YPTWallet"); if ($walletPlugin) { $walletPlugin->addBalance($users_id, $amount, 'Authorize.Net one-time payment'); echo json_encode(['success' => true, 'result' => 'Payment processed and wallet updated']); exit; } }

  Vulnerable flow:

  1. `$_POST['amount']` is read from the client.
  2. The endpoint only checks that the amount is greater than zero.
  3. The real Authorize.Net charge is not performed.
  4. `$paymentSuccess` is hardcoded to true.
  5. The logged-in user's wallet is credited with the client-supplied amount.

  There is no verification of:

  - Authorize.Net transaction ID
  - payment token
  - webhook signature
  - pending payment record
  - expected server-side amount
  - currency
  - duplicate transaction/replay state

  ### PoC

  Prerequisites:

  - AVideo with AuthorizeNet plugin enabled
  - YPTWallet plugin enabled
  - Attacker has any valid user account

  Steps:

  1. Log in as a low-privileged user.
  2. Open the wallet page and record the current balance.
  3. Send the following request with the user's authenticated session cookie:

curl -i -s -b 'PHPSESSID=' \ -X POST 'https://target.example/plugin/AuthorizeNet/processPayment.json.php' \ --data 'amount=9999&userData[note]=poc'

  4. The endpoint returns:

{"success":true,"result":"Payment processed and wallet updated"} ``` 5. Refresh the wallet page. 6. The wallet balance is increased by 9999.

No Authorize.Net hosted payment page, card payment, transaction confirmation, webhook, or server-side payment validation is required.

Impact

A normal authenticated user can mint arbitrary wallet balance.

Depending on the target site's configuration, this may allow the attacker to:

  • purchase paid videos or subscriptions without payment
  • abuse any feature backed by YPTWallet
  • transfer fake funds to other users
  • manipulate accounting or payout-related workflows
  • bypass monetization controls

Recommended fix

  • Remove or disable processPayment.json.php if it is obsolete.
  • Never credit wallet balance from client-supplied amount alone.
  • Use the existing Authorize.Net hosted token / webhook / transaction reconciliation flow.
  • Require a verified Authorize.Net transaction ID and server-side amount lookup before calling addBalance().
  • Add regression tests proving arbitrary POSTs cannot credit a wallet.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "WWBN/AVideo"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "29.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47696"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-345"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-04T18:47:35Z",
    "nvd_published_at": "2026-05-29T14:16:32Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\n  `plugin/AuthorizeNet/processPayment.json.php` credits the logged-in user\u0027s wallet based only on the attacker-controlled `amount` POST parameter.\n\n  The endpoint contains a TODO for real Authorize.Net charging, hardcodes `$paymentSuccess = true`, and then calls `YPTWallet::addBalance()` without validating\n  any Authorize.Net transaction, webhook signature, hosted payment token, nonce, or server-side payment record.\n\n  This allows any logged-in user to add arbitrary funds to their own AVideo wallet when the `AuthorizeNet` and `YPTWallet` plugins are enabled.\n\n  ### Details\n\n  Affected file:\n\n  `plugin/AuthorizeNet/processPayment.json.php`\n\n  Relevant code:\n\n  ```php\n  $amount = isset($_POST[\u0027amount\u0027]) ? floatval($_POST[\u0027amount\u0027]) : 0;\n  $userData = isset($_POST[\u0027userData\u0027]) ? $_POST[\u0027userData\u0027] : [];\n\n  if ($amount \u003c= 0) {\n      echo json_encode([\u0027error\u0027 =\u003e \u0027Invalid amount\u0027]);\n      exit;\n  }\n\n  // TODO: Implement payment logic using Authorize.Net API\n  // Example: Call Authorize.Net API here\n  // $result = $plugin-\u003echargePayment($amount, $userData);\n\n  // Simulate payment success for now\n  $paymentSuccess = true;\n  $users_id = @User::getId();\n\n  if ($paymentSuccess \u0026\u0026 !empty($users_id)) {\n      $walletPlugin = AVideoPlugin::loadPluginIfEnabled(\"YPTWallet\");\n      if ($walletPlugin) {\n          $walletPlugin-\u003eaddBalance($users_id, $amount, \u0027Authorize.Net one-time payment\u0027);\n          echo json_encode([\u0027success\u0027 =\u003e true, \u0027result\u0027 =\u003e \u0027Payment processed and wallet updated\u0027]);\n          exit;\n      }\n  }\n```\n  Vulnerable flow:\n\n  1. `$_POST[\u0027amount\u0027]` is read from the client.\n  2. The endpoint only checks that the amount is greater than zero.\n  3. The real Authorize.Net charge is not performed.\n  4. `$paymentSuccess` is hardcoded to true.\n  5. The logged-in user\u0027s wallet is credited with the client-supplied amount.\n\n  There is no verification of:\n\n  - Authorize.Net transaction ID\n  - payment token\n  - webhook signature\n  - pending payment record\n  - expected server-side amount\n  - currency\n  - duplicate transaction/replay state\n\n  ### PoC\n\n  Prerequisites:\n\n  - AVideo with AuthorizeNet plugin enabled\n  - YPTWallet plugin enabled\n  - Attacker has any valid user account\n\n  Steps:\n\n  1. Log in as a low-privileged user.\n  2. Open the wallet page and record the current balance.\n  3. Send the following request with the user\u0027s authenticated session cookie:\n```\n  curl -i -s -b \u0027PHPSESSID=\u003cuser_session\u003e\u0027 \\\n    -X POST \u0027https://target.example/plugin/AuthorizeNet/processPayment.json.php\u0027 \\\n    --data \u0027amount=9999\u0026userData[note]=poc\u0027\n```\n  4. The endpoint returns:\n```\n  {\"success\":true,\"result\":\"Payment processed and wallet updated\"}\n```\n  5. Refresh the wallet page.\n  6. The wallet balance is increased by 9999.\n\n  No Authorize.Net hosted payment page, card payment, transaction confirmation, webhook, or server-side payment validation is required.\n\n### Impact\n\n  A normal authenticated user can mint arbitrary wallet balance.\n\n  Depending on the target site\u0027s configuration, this may allow the attacker to:\n\n  - purchase paid videos or subscriptions without payment\n  - abuse any feature backed by YPTWallet\n  - transfer fake funds to other users\n  - manipulate accounting or payout-related workflows\n  - bypass monetization controls\n\n### Recommended fix\n\n- Remove or disable `processPayment.json.php` if it is obsolete.\n- Never credit wallet balance from client-supplied `amount` alone.\n- Use the existing Authorize.Net hosted token / webhook / transaction reconciliation flow.\n- Require a verified Authorize.Net transaction ID and server-side amount lookup before calling `addBalance()`.\n- Add regression tests proving arbitrary POSTs cannot credit a wallet.",
  "id": "GHSA-9392-pj54-qqf8",
  "modified": "2026-06-04T18:47:35Z",
  "published": "2026-06-04T18:47:35Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/WWBN/AVideo/security/advisories/GHSA-9392-pj54-qqf8"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47696"
    },
    {
      "type": "WEB",
      "url": "https://github.com/WWBN/AVideo/commit/822402444b4db4e9442779c8c789ffe5312b3627"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/WWBN/AVideo"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "WWBN AVideo: Authenticated wallet credit bypass in AuthorizeNet processPayment endpoint"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…