{"id":"CVE-2026-40907","aliases":["EUVD-2026-24284","GHSA-gpgp-w4x2-h3h7"],"status":"published","title":"WWBN AVideo has IDOR in Live Restreams list.json.php that Exposes Other Users' Stream Keys and OAuth Tokens","description":"WWBN AVideo is an open source video platform. In versions 29.0 and prior, the endpoint `plugin/Live/view/Live_restreams/list.json.php` contains an Insecure Direct Object Reference (IDOR) vulnerability that allows any authenticated user with streaming permission to retrieve other users' live restream configurations, including third-party platform stream keys and OAuth tokens (access_token, refresh_token) for services like YouTube Live, Facebook Live, and Twitch. Commit d5992fff2811df4adad1d9fc7d0a5837b882aed7 fixes the issue.","severity":{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00269,"percentile":0.19186,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-639"],"published":"2026-04-14T22:49:05Z","modified":"2026-10-28T02:30:55Z","affected":[{"source":"ghsa","ecosystem":"Packagist","package":"wwbn/avideo","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"29.0"}]}]},{"source":"osv","ecosystem":"Packagist","package":"wwbn/avideo","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"29.0"}]}],"versions":["10.4","10.8","11","11.1","11.1.1","11.5","11.6","12.4","14.3","14.3.1","14.4","18.0","21.0","22.0","24.0","25.0","26.0","29.0"]}],"products":[{"vendor":"wwbn","product":"avideo"}],"references":[{"url":"https://github.com/WWBN/AVideo/security/advisories/GHSA-gpgp-w4x2-h3h7","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/WWBN/AVideo/commit/d5992fff2811df4adad1d9fc7d0a5837b882aed7","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-40907","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-gpgp-w4x2-h3h7"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/40xxx/CVE-2026-40907.json","tags":["advisory"]},{"url":"https://github.com/WWBN/AVideo","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-40907","title":"WWBN AVideo has IDOR in Live Restreams list.json.php that Exposes Other Users' Stream Keys and OAuth Tokens","description":"WWBN AVideo is an open source video platform. In versions 29.0 and prior, the endpoint `plugin/Live/view/Live_restreams/list.json.php` contains an Insecure Direct Object Reference (IDOR) vulnerability that allows any authenticated user with streaming permission to retrieve other users' live restream configurations, including third-party platform stream keys and OAuth tokens (access_token, refresh_token) for services like YouTube Live, Facebook Live, and Twitch. Commit d5992fff2811df4adad1d9fc7d0a5837b882aed7 fixes the issue.","status":"published","published":"2026-04-21T19:50:10.257Z","modified":"2026-04-21T20:06:56.844Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-639"],"updated_at":"2026-11-02T13:43:11.445168Z"}],"euvd":[{"id":"EUVD-2026-24284","description":"WWBN AVideo is an open source video platform. In versions 29.0 and prior, the endpoint `plugin/Live/view/Live_restreams/list.json.php` contains an Insecure Direct Object Reference (IDOR) vulnerability that allows any authenticated user with streaming permission to retrieve other users' live restream configurations, including third-party platform stream keys and OAuth tokens (access_token, refresh_token) for services like YouTube Live, Facebook Live, and Twitch. Commit d5992fff2811df4adad1d9fc7d0a5837b882aed7 fixes the issue.","status":"published","published":"2026-04-21T19:50:10Z","modified":"2026-04-21T20:06:56Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T19:24:21.512647Z"}],"ghsa":[{"id":"GHSA-gpgp-w4x2-h3h7","title":"WWBN AVideo has an IDOR in Live Restreams list.json.php Exposes Other Users' Stream Keys and OAuth Tokens","description":"## Summary\n\nThe endpoint `plugin/Live/view/Live_restreams/list.json.php` contains an Insecure Direct Object Reference (IDOR) vulnerability that allows any authenticated user with streaming permission to retrieve other users' live restream configurations, including third-party platform stream keys and OAuth tokens (access_token, refresh_token) for services like YouTube Live, Facebook Live, and Twitch.\n\n## Details\n\nThe authorization logic in `list.json.php` is intended to restrict non-admin users to viewing only their own restream records. However, the implementation at lines 10-14 only enforces this when the `users_id` GET parameter is absent:\n\n```php\n// plugin/Live/view/Live_restreams/list.json.php:6-19\nif (!User::canStream()) {\n    die('{\"data\": []}');\n}\n\nif (empty($_GET['users_id'])) {       // Line 10: only triggers when param is MISSING\n    if (!User::isAdmin()) {\n        $_GET['users_id'] = User::getId();  // Line 12: force to own ID\n    }\n}\n\nif (empty($_GET['users_id'])) {\n    $rows = Live_restreams::getAll();\n} else {\n    $rows = Live_restreams::getAllFromUser($_GET['users_id'], \"\");  // Line 19: attacker-controlled ID\n}\n```\n\nWhen a non-admin user explicitly supplies `?users_id=\u003cvictim_id\u003e`, the value is non-empty, so the override at line 12 is never reached. The attacker-controlled ID passes directly to `getAllFromUser()`, which executes:\n\n```php\n// plugin/Live/Objects/Live_restreams.php:90\n$sql = \"SELECT * FROM live_restreams WHERE users_id = $users_id\";\n```\n\nThis returns all columns from the `live_restreams` table, including:\n- `stream_key` (VARCHAR 500) — the victim's RTMP stream key for third-party platforms\n- `stream_url` (VARCHAR 500) — the RTMP ingest endpoint\n- `parameters` (TEXT) — JSON blob containing OAuth credentials (`access_token`, `refresh_token`, `expires_at`) obtained via the restream.ypt.me OAuth flow\n\nOther endpoints in the same directory correctly validate ownership. For example, `delete.json.php:19`:\n```php\nif (!User::isAdmin() \u0026\u0026 $row-\u003egetUsers_id() != User::getId()) {\n    $obj-\u003emsg = \"You are not admin\";\n    die(json_encode($obj));\n}\n```\n\nThis ownership check is missing from `list.json.php`.\n\n## PoC\n\n**Prerequisites:** Two user accounts — attacker (user ID 2, streaming permission) and victim (user ID 1, has configured restreams with third-party platform keys).\n\n**Step 1:** Attacker authenticates and retrieves their session cookie.\n\n**Step 2:** Attacker requests victim's restream list:\n```bash\ncurl -s -b 'PHPSESSID=\u003cattacker_session\u003e' \\\n  'https://target.com/plugin/Live/view/Live_restreams/list.json.php?users_id=1'\n```\n\n**Expected response (normal behavior):** Empty data or error.\n\n**Actual response:** Full restream records for user ID 1:\n```json\n{\n  \"data\": [\n    {\n      \"id\": 1,\n      \"name\": \"YouTube Live\",\n      \"stream_url\": \"rtmp://a.rtmp.youtube.com/live2\",\n      \"stream_key\": \"xxxx-xxxx-xxxx-xxxx-xxxx\",\n      \"parameters\": \"{\\\"access_token\\\":\\\"ya29.a0A...\\\",\\\"refresh_token\\\":\\\"1//0e...\\\",\\\"expires_at\\\":1712600000}\",\n      \"users_id\": 1,\n      \"status\": \"a\"\n    }\n  ]\n}\n```\n\n**Step 3:** Attacker can enumerate all user IDs (1, 2, 3, ...) to harvest all configured restream credentials across the platform.\n\n## Impact\n\n- **Credential theft:** Attacker obtains third-party platform stream keys and OAuth tokens (access_token, refresh_token) for all users who have configured live restreaming.\n- **Unauthorized broadcasting:** Stolen RTMP stream keys allow the attacker to broadcast arbitrary content to the victim's YouTube, Facebook, or Twitch channels.\n- **OAuth token abuse:** Stolen refresh tokens can be used to obtain new access tokens, providing persistent access to the victim's third-party accounts within the scope of the original OAuth grant.\n- **Full enumeration:** User IDs are sequential integers, enabling trivial enumeration of all platform users' restream credentials.\n\n## Recommended Fix\n\nAdd an ownership check in `list.json.php` consistent with the pattern used in `delete.json.php` and `add.json.php`:\n\n```php\n// plugin/Live/view/Live_restreams/list.json.php — replace lines 10-14\nif (!User::isAdmin()) {\n    $_GET['users_id'] = User::getId();\n}\n```\n\nThis unconditionally forces non-admin users to their own user ID, regardless of whether the `users_id` parameter was supplied. The `empty()` check should be removed so that the parameter cannot be used to bypass the restriction.","status":"published","published":"2026-04-14T22:49:05Z","modified":"2026-04-24T20:29:54Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-639"],"updated_at":"2026-11-02T14:39:56.453138Z"}],"nvd":[{"id":"CVE-2026-40907","description":"WWBN AVideo is an open source video platform. In versions 29.0 and prior, the endpoint `plugin/Live/view/Live_restreams/list.json.php` contains an Insecure Direct Object Reference (IDOR) vulnerability that allows any authenticated user with streaming permission to retrieve other users' live restream configurations, including third-party platform stream keys and OAuth tokens (access_token, refresh_token) for services like YouTube Live, Facebook Live, and Twitch. Commit d5992fff2811df4adad1d9fc7d0a5837b882aed7 fixes the issue.","status":"published","published":"2026-04-21T20:17:03.08Z","modified":"2026-10-26T22:10:00.163Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-639"],"updated_at":"2026-11-02T14:12:15.493943Z"}],"osv":[{"id":"CVE-2026-40907","title":"WWBN AVideo has IDOR in Live Restreams list.json.php that Exposes Other Users' Stream Keys and OAuth Tokens","description":"WWBN AVideo is an open source video platform. In versions 29.0 and prior, the endpoint `plugin/Live/view/Live_restreams/list.json.php` contains an Insecure Direct Object Reference (IDOR) vulnerability that allows any authenticated user with streaming permission to retrieve other users' live restream configurations, including third-party platform stream keys and OAuth tokens (access_token, refresh_token) for services like YouTube Live, Facebook Live, and Twitch. Commit d5992fff2811df4adad1d9fc7d0a5837b882aed7 fixes the issue.","status":"published","published":"2026-04-21T19:50:10.257Z","modified":"2026-10-28T02:30:55.19757306Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-639"],"updated_at":"2026-11-02T15:45:03.424067Z"},{"id":"GHSA-gpgp-w4x2-h3h7","title":"WWBN AVideo has an IDOR in Live Restreams list.json.php Exposes Other Users' Stream Keys and OAuth Tokens","description":"## Summary\n\nThe endpoint `plugin/Live/view/Live_restreams/list.json.php` contains an Insecure Direct Object Reference (IDOR) vulnerability that allows any authenticated user with streaming permission to retrieve other users' live restream configurations, including third-party platform stream keys and OAuth tokens (access_token, refresh_token) for services like YouTube Live, Facebook Live, and Twitch.\n\n## Details\n\nThe authorization logic in `list.json.php` is intended to restrict non-admin users to viewing only their own restream records. However, the implementation at lines 10-14 only enforces this when the `users_id` GET parameter is absent:\n\n```php\n// plugin/Live/view/Live_restreams/list.json.php:6-19\nif (!User::canStream()) {\n    die('{\"data\": []}');\n}\n\nif (empty($_GET['users_id'])) {       // Line 10: only triggers when param is MISSING\n    if (!User::isAdmin()) {\n        $_GET['users_id'] = User::getId();  // Line 12: force to own ID\n    }\n}\n\nif (empty($_GET['users_id'])) {\n    $rows = Live_restreams::getAll();\n} else {\n    $rows = Live_restreams::getAllFromUser($_GET['users_id'], \"\");  // Line 19: attacker-controlled ID\n}\n```\n\nWhen a non-admin user explicitly supplies `?users_id=\u003cvictim_id\u003e`, the value is non-empty, so the override at line 12 is never reached. The attacker-controlled ID passes directly to `getAllFromUser()`, which executes:\n\n```php\n// plugin/Live/Objects/Live_restreams.php:90\n$sql = \"SELECT * FROM live_restreams WHERE users_id = $users_id\";\n```\n\nThis returns all columns from the `live_restreams` table, including:\n- `stream_key` (VARCHAR 500) — the victim's RTMP stream key for third-party platforms\n- `stream_url` (VARCHAR 500) — the RTMP ingest endpoint\n- `parameters` (TEXT) — JSON blob containing OAuth credentials (`access_token`, `refresh_token`, `expires_at`) obtained via the restream.ypt.me OAuth flow\n\nOther endpoints in the same directory correctly validate ownership. For example, `delete.json.php:19`:\n```php\nif (!User::isAdmin() \u0026\u0026 $row-\u003egetUsers_id() != User::getId()) {\n    $obj-\u003emsg = \"You are not admin\";\n    die(json_encode($obj));\n}\n```\n\nThis ownership check is missing from `list.json.php`.\n\n## PoC\n\n**Prerequisites:** Two user accounts — attacker (user ID 2, streaming permission) and victim (user ID 1, has configured restreams with third-party platform keys).\n\n**Step 1:** Attacker authenticates and retrieves their session cookie.\n\n**Step 2:** Attacker requests victim's restream list:\n```bash\ncurl -s -b 'PHPSESSID=\u003cattacker_session\u003e' \\\n  'https://target.com/plugin/Live/view/Live_restreams/list.json.php?users_id=1'\n```\n\n**Expected response (normal behavior):** Empty data or error.\n\n**Actual response:** Full restream records for user ID 1:\n```json\n{\n  \"data\": [\n    {\n      \"id\": 1,\n      \"name\": \"YouTube Live\",\n      \"stream_url\": \"rtmp://a.rtmp.youtube.com/live2\",\n      \"stream_key\": \"xxxx-xxxx-xxxx-xxxx-xxxx\",\n      \"parameters\": \"{\\\"access_token\\\":\\\"ya29.a0A...\\\",\\\"refresh_token\\\":\\\"1//0e...\\\",\\\"expires_at\\\":1712600000}\",\n      \"users_id\": 1,\n      \"status\": \"a\"\n    }\n  ]\n}\n```\n\n**Step 3:** Attacker can enumerate all user IDs (1, 2, 3, ...) to harvest all configured restream credentials across the platform.\n\n## Impact\n\n- **Credential theft:** Attacker obtains third-party platform stream keys and OAuth tokens (access_token, refresh_token) for all users who have configured live restreaming.\n- **Unauthorized broadcasting:** Stolen RTMP stream keys allow the attacker to broadcast arbitrary content to the victim's YouTube, Facebook, or Twitch channels.\n- **OAuth token abuse:** Stolen refresh tokens can be used to obtain new access tokens, providing persistent access to the victim's third-party accounts within the scope of the original OAuth grant.\n- **Full enumeration:** User IDs are sequential integers, enabling trivial enumeration of all platform users' restream credentials.\n\n## Recommended Fix\n\nAdd an ownership check in `list.json.php` consistent with the pattern used in `delete.json.php` and `add.json.php`:\n\n```php\n// plugin/Live/view/Live_restreams/list.json.php — replace lines 10-14\nif (!User::isAdmin()) {\n    $_GET['users_id'] = User::getId();\n}\n```\n\nThis unconditionally forces non-admin users to their own user ID, regardless of whether the `users_id` parameter was supplied. The `empty()` check should be removed so that the parameter cannot be used to bypass the restriction.","status":"published","published":"2026-04-14T22:49:05Z","modified":"2026-05-05T16:11:42.324166Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-639"],"updated_at":"2026-11-02T15:46:48.191583Z"}]}}
