diff options
author | Fabien Potencier <fabien.potencier@gmail.com> | 2014-09-10 15:18:42 +0200 |
---|---|---|
committer | Fabien Potencier <fabien.potencier@gmail.com> | 2014-09-10 15:18:42 +0200 |
commit | eea4a9bdfa0930002b9a4de65e3e6e7fd95941a1 (patch) | |
tree | 53601695555388dc3012a3f669004318f6e0ca7f | |
parent | aee2d201bfe01008d293b85af075040aebeb2eac (diff) | |
parent | 6695a8e284aa75cfa2be1b1825367924febb3953 (diff) | |
download | symfony-security-eea4a9bdfa0930002b9a4de65e3e6e7fd95941a1.zip symfony-security-eea4a9bdfa0930002b9a4de65e3e6e7fd95941a1.tar.gz symfony-security-eea4a9bdfa0930002b9a4de65e3e6e7fd95941a1.tar.bz2 |
minor #11822 [Security] Use hash_equals for constant-time string comparison (again) (dunglas)
This PR was merged into the 2.3 branch.
Discussion
----------
[Security] Use hash_equals for constant-time string comparison (again)
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | n/a
| License | MIT
| Doc PR | n/a
Use the `hash_equals` function (introduced in PHP 5.6) for timing attack safe string comparison when available.
Add in the DocBlock that length will leak (https://github.com/symfony/symfony/pull/11797#issuecomment-53990712).
Commits
-------
3071557 [Security] Add more tests for StringUtils::equals
03bd74b [Security] Use hash_equals for constant-time string comparison
-rw-r--r-- | Core/Util/StringUtils.php | 10 | ||||
-rw-r--r-- | Tests/Core/Util/StringUtilsTest.php | 44 |
2 files changed, 50 insertions, 4 deletions
diff --git a/Core/Util/StringUtils.php b/Core/Util/StringUtils.php index 5e13037..acf8e9e 100644 --- a/Core/Util/StringUtils.php +++ b/Core/Util/StringUtils.php @@ -27,6 +27,7 @@ class StringUtils * Compares two strings. * * This method implements a constant-time algorithm to compare strings. + * Regardless of the used implementation, it will leak length information. * * @param string $knownString The string of known length to compare against * @param string $userInput The string that the user can control @@ -35,6 +36,13 @@ class StringUtils */ public static function equals($knownString, $userInput) { + $knownString = (string) $knownString; + $userInput = (string) $userInput; + + if (function_exists('hash_equals')) { + return hash_equals($knownString, $userInput); + } + $knownLen = strlen($knownString); $userLen = strlen($userInput); @@ -45,7 +53,7 @@ class StringUtils $result = $knownLen - $userLen; // Note that we ALWAYS iterate over the user-supplied length - // This is to prevent leaking length information + // This is to mitigate leaking length information for ($i = 0; $i < $userLen; $i++) { $result |= (ord($knownString[$i]) ^ ord($userInput[$i])); } diff --git a/Tests/Core/Util/StringUtilsTest.php b/Tests/Core/Util/StringUtilsTest.php index aac4139..b16cbac 100644 --- a/Tests/Core/Util/StringUtilsTest.php +++ b/Tests/Core/Util/StringUtilsTest.php @@ -13,11 +13,49 @@ namespace Symfony\Component\Security\Tests\Core\Util; use Symfony\Component\Security\Core\Util\StringUtils; +/** + * Data from PHP.net's hash_equals tests + */ class StringUtilsTest extends \PHPUnit_Framework_TestCase { - public function testEquals() + public function dataProviderTrue() + { + return array( + array('same', 'same'), + array('', ''), + array(123, 123), + array(null, ''), + array(null, null), + ); + } + + public function dataProviderFalse() + { + return array( + array('not1same', 'not2same'), + array('short', 'longer'), + array('longer', 'short'), + array('', 'notempty'), + array('notempty', ''), + array(123, 'NaN'), + array('NaN', 123), + array(null, 123), + ); + } + + /** + * @dataProvider dataProviderTrue + */ + public function testEqualsTrue($known, $user) + { + $this->assertTrue(StringUtils::equals($known, $user)); + } + + /** + * @dataProvider dataProviderFalse + */ + public function testEqualsFalse($known, $user) { - $this->assertTrue(StringUtils::equals('password', 'password')); - $this->assertFalse(StringUtils::equals('password', 'foo')); + $this->assertFalse(StringUtils::equals($known, $user)); } } |