GitHub Security Advisory: GHSA-5w8w-26ch-v5cw
Package: wwbn/avideo (COMPOSER)
Severity: MODERATE (CVSS 6.8)
CWE: CWE-598: Use of GET Request Method With Sensitive Query Strings
Vulnerable versions: <= 29.0
Patched in: unpatched

Summary: AVideo: Password Hash Leak in MobileManager OAuth Redirect URL Enables Account Takeover

Details:
## Summary

`plugin/MobileManager/oauth2.php` completes an OAuth login by sending an HTTP 302 `Location: oauth2Success.php?user=<email>&pass=<HASH>` where `<HASH>` is the victim's stored password hash (`md5(hash("whirlpool", sha1(password)))`) read directly from the `users` table. AVideo's own login endpoint (`objects/login.json.php`) accepts an `encodedPass=1` flag that bypasses hashing and performs a direct string comparison between the supplied value and the stored hash. Anyone who captures the redirect URL — via server logs, referrer leakage, or browser history — therefore obtains a credential equivalent to the plaintext password and can fully take over the account, including admin accounts.

## Details

### Sink: hash inlined in a GET redirect

`plugin/MobileManager/oauth2.php:98-102`:

```php
$pass = rand();
$users_id = User::createUserIfNotExists($user, $pass, $name, $email, $photoURL);
$adapter->disconnect();
$userObject = new User($users_id);
header("Location: oauth2Success.php?user=" . $userObject->getUser() . "&pass=" . $userObject->getPassword());
```

`$userObject->getPassword()` returns the raw database column (`objects/user.php:159-162`):

```php
public function getPassword()
{
    return strip_tags($this->password);
}
```

The returned value is the stored password hash for the account (existing or freshly-created). It is transported to the browser as a query-string parameter in the `Location:` header, so it is written to:

* Web-server access logs (`combined` / `main` log formats record the full request line including query string).
* Upstream proxy / CDN / WAF logs.
* Any error monitoring / APM that captures request URLs (Sentry, Datadog, New Relic defaults).
* The victim's browser history (persistent local artifact).
* The `Referer` header on subsequent navigation from the rendered `oauth2Success.php` page if the page or its assets load any external origin and the browser's `Referrer-Policy` is not strict.

### Hash equals plaintext for login

`objects/login.json.php:182-209`:

```php
if (!empty($_GET['user'])) {
    $_POST['user'] = $_GET['user'];
}
if (!empty($_GET['pass'])) {
    $_POST['pass'] = $_GET['pass'];
}
if (!empty($_GET['encodedPass'])) {
    $_POST['encodedPass'] = $_GET['encodedPass'];
}
...
$user = new User(0, $_POST['user'], $_POST['pass']);
...
$resp = $user->login(false, @$_POST['encodedPass']);
```

`objects/user.php:1272-1279` passes `$encodedPass` to `find()`:

```php
if (strtolower($encodedPass) === 'false') {
    $encodedPass = false;
}
...
$user = $this->find($this->user, $this->password, true, $encodedPass);
```

`objects/user.php:1785-1794`:

```php
if ($pass !== false) {
    if (!encryptPasswordVerify($pass, $result['password'], $encodedPass)) {
        ...
        return false;
    }
}
```

`objects/functions.php:2312-2331`:

```php
function encryptPasswordVerify(#[\SensitiveParameter] $password, $hash, $encodedPass = false)
{
    global $advancedCustom, $global;
    if (!$encodedPass || $encodedPass