Title: Authentication bypass on What.CD's Gazelle
Date: 2023-10-13 19:45

[What.CD](https://en.wikipedia.org/wiki/What.CD) has been dead since 2016, and
hopefully [nobody]( https://github.com/OPSnet/Gazelle/blob/master/app/Util/Crypto.php )
is using [Gazelle](https://github.com/WhatCD/Gazelle),
their "web framework geared towards private BitTorrent tracker" anymore.
I've been sitting on this one for years, I know I wasn't the only one,
and it's not the only low-hanging vulnerability lurking there.

Rolling your own blunt is alright, rolling your own authentication scheme
less so: there is a trivial [padding oracle](https://en.wikipedia.org/wiki/Padding_oracle_attack)
in the [homegrown crypto scheme](https://github.com/WhatCD/Gazelle/blob/master/classes/encrypt.class.php#L24):

```php
public function decrypt($CryptStr, $Key = ENCKEY) {
	if ($CryptStr != '') {
		$IV = substr(base64_decode($CryptStr), 0, 16);
		$CryptStr = substr(base64_decode($CryptStr), 16);
		return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $Key, $CryptStr, MCRYPT_MODE_CBC, $IV));
	} else {
		return '';
	}
}
```

leading to an [authentication bypass via a SQL injection]( https://github.com/WhatCD/Gazelle/blob/master/classes/ajax_start.php#L23-L31):

```php
if (isset($_COOKIE['session'])) {
	$LoginCookie = $Enc->decrypt($_COOKIE['session']);
}
if (isset($LoginCookie)) {
	list($SessionID, $UserID) = explode("|~|", $Enc->decrypt($LoginCookie));

	if (!$UserID || !$SessionID) {
		die('Not logged in!');
	}

	if (!$Enabled = $Cache->get_value("enabled_$UserID")) {
		require(SERVER_ROOT.'/classes/mysql.class.php'); //Require the database wrapper
		$DB = NEW DB_MYSQL; //Load the database wrapper
		$DB->query("
			SELECT Enabled
			FROM users_main
			WHERE ID = '$UserID'");
		list($Enabled) = $DB->next_record();
		$Cache->cache_value("enabled_$UserID", $Enabled, 0);
	}
} else {
	die('Not logged in!');
}
```

Conveniently, the oracle doesn't touch the database, is completely stateless,
and only shows up in the httpd/reverse-proxy's logs, which shouldn't log the cookies'
content, making forensic analysis nigh impossible. Once you're admin, there are
a bunch of available SQL injections, like in
[`takerevolve.php`](https://github.com/WhatCD/Gazelle/blob/master/sections/reportsv2/takeresolve.php).
From there, remote code execution is doable, but left as an exercise for the
reader.
