There is a security token mismatch

Upgraded to 1.8.8 Hestia and now facing issue to login via SSO to PMA. Getting error:

[Thu Sep 21 15:52:21.435182 2023] [proxy_fcgi:error] [pid 1828679:tid 140159446136512] [client xx.xx.xx.xx:0] AH01071: Got error 'PHP message: PHP Warning: Access denied: There is a security token mismatch 1695300741 in /usr/share/phpmyadmin/hestia-sso.php on line 130', referer: https://domain.tld/

I have checked if hestia-sso.php sees my correct IP, it does without problem. Hestia Panel is not behind cloudflare.

Regenerated phpMyAdmin token from UI and from CLI - same result. What else to check? MySQL is running. Everything is running.

So, bit by bit managed to dig deep enough to uncover some interesting bits.

This function:

function verify_token($database, $user, $ip, $time, $token) {
	if (!password_verify($database . $user . $ip . $time . PHPMYADMIN_KEY, $token)) {
		if (
			!password_verify(
				$database . $user . $_SERVER["SERVER_ADDR"] . "|" . $ip . $time . PHPMYADMIN_KEY,
				$token
			)
		) {
			
			trigger_error(
				"Access denied: There is a security token mismatch " . $time,
				E_USER_WARNING,
			);
			session_invalid();
		}
	}
	return;
}

Portion:

if (
			!password_verify(
				$database . $user . $_SERVER["SERVER_ADDR"] . "|" . $ip . $time . PHPMYADMIN_KEY,
				$token
			)
		) {			
			trigger_error(
				"Access denied: There is a security token mismatch " . $time,
				E_USER_WARNING,
			);
			session_invalid();
		}

This portion specifically takes local server IP address. When I locally access PMA SSO, everything works, but when I access SSO via my external script - it fails check.

Of course it is good to secure as much as it is rational. In my case, users have no access to hestiacp, everything is done via third party system. Is it secure to comment out that check? To leave this function like this:

function verify_token($database, $user, $ip, $time, $token) {
	if (!password_verify($database . $user . $ip . $time . PHPMYADMIN_KEY, $token)) {
		
		trigger_error(
			"Access denied: There is a security token mismatch " . $time,
			E_USER_WARNING,
		);
		session_invalid();
	}
	return;
}

Actually looking more into this issue seems command:

v-delete-sys-pma-sso

Does not delete API key. It removes value in hestia.conf, turns off setting in config, deletes hestia-sso.php file, but does not delete key in keys directory. And executing manually that script, it shows up warning:

rm: cannot remove '/usr/local/hestia/data/keys/': Is a directory

Also, there is config value in hestia.conf:

PHPMYADMIN_KEY=''

Does this value should be equal to API key? Because now it is:

Access Key ID: ULkwTu8x8yyGjABKCo2b
PHPMYADMIN_KEY='FpwadIXVgj0sjtV6'

They should be different by design:

/* Following keys will get replaced when calling v-add-sys-pma-sso */
define("PHPMYADMIN_KEY", "xxxxVsz3wVGqt");
define("API_HOST_NAME", "xxx");
define("API_HESTIA_PORT", "8083");
define("API_KEY", "gEILYWtD5zkrFAdSFffG:xxxxxx-aPzzlT3IBCuOIlYN6eW5x-=8");

PHPMYADMIN_KEY should be the same in both hestia.conf and hestia-php-sso.

Also it is by default:

if (!password_verify($database . $user . $ip . $time . PHPMYADMIN_KEY, $token)) {
					trigger_error(
						"Access denied: There is a security token mismatch " . $time,
						E_USER_WARNING,
					);
					session_invalid();
				}

And $ip is by default $ip = $api->get_user_ip();

and

	public function get_user_ip() {
		// Saving user IPs to the session for preventing session hijacking
		$user_combined_ip = [];
		if ($_SERVER["REMOTE_ADDR"] != $_SERVER["SERVER_ADDR"]) {
			$user_combined_ip[] = $_SERVER["REMOTE_ADDR"];
		}
		if (isset($_SERVER["HTTP_CLIENT_IP"])) {
			$user_combined_ip .= "|" . $_SERVER["HTTP_CLIENT_IP"];
		}
		if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
			if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_X_FORWARDED_FOR"]) {
				$user_combined_ip[] = $_SERVER["HTTP_X_FORWARDED_FOR"];
			}
		}
		if (isset($_SERVER["HTTP_FORWARDED_FOR"])) {
			if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_FORWARDED_FOR"]) {
				$user_combined_ip[] = $_SERVER["HTTP_FORWARDED_FOR"];
			}
		}
		if (isset($_SERVER["HTTP_X_FORWARDED"])) {
			if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_X_FORWARDED"]) {
				$user_combined_ip[] = $_SERVER["HTTP_X_FORWARDED"];
			}
		}
		if (isset($_SERVER["HTTP_FORWARDED"])) {
			if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_FORWARDED"]) {
				$user_combined_ip[] = "|" . $_SERVER["HTTP_FORWARDED"];
			}
		}
		if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
			if (!empty($_SERVER["HTTP_CF_CONNECTING_IP"])) {
				$user_combined_ip[] = $_SERVER["HTTP_CF_CONNECTING_IP"];
			}
		}
		return implode("|", $user_combined_ip);
	}

Make sure in both cases the IP’s are matching on both the phpmyadmin page and your own panel…

How ever if more assistance is required I happy to help but for a fee…

1 Like

Finally, found where was the problem. Please ignore all my “presumptions”. I have loaded wrong key. I thought that API KEY ID == PHPMYADMIN_KEY . Issue resolved when I grabbed PHPMYADMIN_KEY from hestia.conf and generated token with it.

Damn, I almost got insane with this one. Issue closed.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.