GHSA-9392-PJ54-QQF8
Vulnerability from github – Published: 2026-06-04 18:47 – Updated: 2026-06-04 18:47Summary
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.phpif it is obsolete. - Never credit wallet balance from client-supplied
amountalone. - 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.
{
"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"
}
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.