Skip to content
GHSA 5664 H9h4 3gwc

GHSA 5664 H9h4 3gwc

github.com • September 9, 2026

session_start_preload in objects/functionsPHP.php:592 sets a cookie named key with the literal value value for every session. PHP's variables_order=EGPCS makes $_COOKIE override $_GET and $_POST in $_REQUEST , so $_REQUEST['key'] is always the string value for any logged-in user. plugin/Live/saveLive.php:33 calls $l->setKey($_REQUEST['key']) to persist the user's RTMP stream key, so every user who saves their live stream settings gets the key value instead of their chosen key.

The stream key is the secret that authenticates the publisher to the RTMP server. LiveTransmition::setKey at plugin/Live/Objects/LiveTransmition.php stores it in the live_transmitions table, and the nginx-rtmp on_publish callback at plugin/Live/on_publish.php:151 checks it via LiveTransmition::keyExists . When all keys are value , that check still runs but the secret it compares against is a constant known to anyone who reads the source.

An attacker who knows the key is value can publish to any user's RTMP stream without authentication, replacing the victim's live content.

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N

The cookie is set in objects/functionsPHP.php:592 :

This runs inside session_start_preload() , which is called for every request that initializes a session. The cookie named key persists for the session lifetime. The variables_order=EGPCS directive in php.ini makes $_COOKIE the fourth source merged into $_REQUEST , after $_GET and $_POST , so $_COOKIE['key'] overwrites any $_GET['key'] or $_POST['key'] in $_REQUEST['key'] .

plugin/Live/saveLive.php:33 reads the stream key from $_REQUEST :

Even when the user submits key=alice_secret_key via POST, $_REQUEST['key'] resolves to value from the cookie, and the database stores value as the stream key.

The same $_REQUEST['key'] override affects these additional endpoints:

plugin/Live/control.json.php:18 — stream control (record start/stop, drop publisher)

plugin/Live/stopLive.php:29 — stop a live stream

plugin/Live/socketMessageLiveOwner.json.php:10 — send socket messages to stream owner

plugin/Live/keyInfo.php:14 — look up stream info by key

objects/functions.php:7862 — Live::getMediaSession($_REQUEST['key']) for media session metadata

plugin/MobileManager/index.php:27 and plugin/MobileYPT/index.php:30 — mobile live stream key

plugin/CDN/status.json.php:23,29 and plugin/CDN/disable.json.php:22 — CDN key validation

The cookie serves no security purpose. It exists only to test whether the browser accepts cookies, as indicated by the guard at functionsPHP.php:587 that skips re-setting it if already present. Renaming it has no functional impact.

Observed output from the test environment:

The database row after the POST:

Alice submitted key=alice_secret_key but the stored key is value .

The RTMP stream key is the secret that authenticates the publisher to the streaming server. When all users' stream keys are value , anyone who knows this can publish to any user's RTMP stream without authentication. This enables stream hijacking (replacing the victim's live content), content injection (streaming malicious or inappropriate content under the victim's channel), and denial of service (continuously publishing to prevent the victim from going live). The attacker does not need to be logged in or have any account; they only need to know the stream key is value , which is a constant set by the application itself.

AVideo at commit c3edcc274c and earlier versions with variables_order=EGPCS and the key cookie set in session_start_preload .

Unfixed at time of reporting. Commit c3edcc274c .

Extracted Entities

Attack Types (1)

Platforms (1)

Tools (1)