From 3e7d29dc0ca6c054a6d6e211f32dae89078594c1 Mon Sep 17 00:00:00 2001 From: Alexander Diebler Date: Mon, 8 Aug 2016 20:29:51 +0200 Subject: [PATCH] Fixed timing attack vulnerability --- src/Middleware.php | 26 ++++++++++++++++++++++++++ src/Webhook.php | 2 +- tests/MiddlewareTest.php | 24 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/Middleware.php b/src/Middleware.php index ff3e7ec..ba981bc 100644 --- a/src/Middleware.php +++ b/src/Middleware.php @@ -30,4 +30,30 @@ public static function generateSignature($host, $method, $path, $query, $date, $ return hash_hmac('sha256', $signatureString, $key); } + + /** + * @param string $first + * @param string $second + * @return boolean + * + * Workaround for PHP < 5.6 by: asphp at dsgml dot com + * Source: https://php.net/manual/en/function.hash-equals.php#115635 + */ + public static function stringsEqual($first, $second) + { + if (function_exists('hash_equals')) { + return hash_equals($first, $second); + } + + if (strlen($first) != strlen($second)) { + return false; + } + + $res = $first ^ $second; + $ret = 0; + for ($i = strlen($res) - 1; $i >= 0; $i--) { + $ret |= ord($res[$i]); + } + return !$ret; + } } diff --git a/src/Webhook.php b/src/Webhook.php index 556a326..a862814 100644 --- a/src/Webhook.php +++ b/src/Webhook.php @@ -36,6 +36,6 @@ public function verify($header, $body) $this->paymentKey ); - return $header['HTTP_BZ_SIGNATURE'] == 'BZ1-HMAC-SHA256 ' . $signature; + return Middleware::stringsEqual($header['HTTP_BZ_SIGNATURE'], 'BZ1-HMAC-SHA256 ' . $signature); } } \ No newline at end of file diff --git a/tests/MiddlewareTest.php b/tests/MiddlewareTest.php index e77f1f3..bc4d68b 100644 --- a/tests/MiddlewareTest.php +++ b/tests/MiddlewareTest.php @@ -21,4 +21,28 @@ public function testGenerateSignature() $this->assertEquals('35764655afcf2121602a5493b58020d3b6b9d75b4150c7395acf6114ae0ba49c', $signature); } + + public function testStringsEqualInvalidLength() + { + $first = 'thisisarandomstring123'; + $second = 'thisisanotherrandomstring123'; + + $this->assertFalse(Middleware::stringsEqual($first, $second)); + } + + public function testStringsEqualInvalidContent() + { + $first = 'thisisarandomstring123'; + $second = 'thisisarandomstring124'; + + $this->assertFalse(Middleware::stringsEqual($first, $second)); + } + + public function testStringsEqualValid() + { + $first = 'thismustbeavalidhash'; + $second = 'thismustbeavalidhash'; + + $this->assertTrue(Middleware::stringsEqual($first, $second)); + } }