GitHub Security Advisory: GHSA-q4x6-6mm2-crg9
Package: WWBN/AVideo (COMPOSER)
Severity: MODERATE (CVSS 6.5)
CWE: CWE-918: Server-Side Request Forgery (SSRF)
Vulnerable versions: <= 26.0
Patched in: unpatched

Summary: WWBN AVideo has a Live restream log callback flow enabling stored SSRF to internal services

Details:
## Summary

The Live restream log callback flow accepted an attacker-controlled `restreamerURL` and later fetched that stored URL server-side, enabling stored SSRF for authenticated streamers.

The vulnerable flow allowed a low-privilege user with streaming permission to store an arbitrary callback URL and trigger server-side requests to loopback or internal HTTP services through the restream log feature.

## Details

The vulnerable chain was:

1. `plugin/Live/view/getRestream.json.php` exposed a fresh `tokenForAction`
2. `plugin/Live/view/Live_restreams/verifyTokenForAction.json.php` exchanged it for a valid `responseToken`
3. `plugin/Live/view/Live_restreams_logs/add.json.php` accepted attacker-controlled `restreamerURL`
4. `plugin/Live/view/getRestream.json.php` and `plugin/Live/view/Live_restreams/getAction.json.php` later fetched that stored URL server-side

The original issue existed because the `responseToken` was accepted, but the callback destination was not tightly constrained to trusted restreamer endpoints.

The maintainer confirmed the vulnerability and stated that the fix was applied by validating `restreamerURL` at storage time and re-validating the log-entry branch before use. The maintainer also noted that the `m3u8` field follows the same general pattern but is not server-fetched in the current flow.

## Proof of concept

1. Log in as a non-admin user with streaming permission.
2. Create a normal restream destination.
3. Trigger `plugin/Live/view/Live_restreams/testRestreamer.json.php` to create a live transmission history row.
4. Call:

```text
GET /plugin/Live/view/getRestream.json.php?live_transmitions_history_id=<id>&restreams_id=<id>
```

5. Extract `tokenForAction` from the returned URL.
6. Exchange it for `responseToken` via:

```text
POST /plugin/Live/view/Live_restreams/verifyTokenForAction.json.php
```

7. Store a loopback callback URL:

```text
POST /plugin/Live/view/Live_restreams_logs/add.json.php
restreamerURL=http://127.0.0.1:9999/index.php
```

8. Trigger `getRestream.json.php` again.
9. Observe that the returned response now contains the JSON body from the loopback-only service.

## Impact

An authenticated streamer can cause the AVideo server to send HTTP requests to loopback or internal services and return the response through normal application endpoints by storing a malicious `restreamerURL` in the restream log flow. Because the callback destination was not constrained to trusted restreamer endpoints, the application could be used as a proxy to internal-only services that trust network locality. Successful exploitation can expose local admin panels, internal-only APIs, cloud metadata services if reachable, or other sensitive internal responses available from the application host.


## Recommended fix

- Validate `restreamerURL` against explicitly configured restreamer endpoints at storage time
- Re-validate the stored callback URL before server-side fetch
- Bind `responseToken` to the expected restream row a