From 6142ce88cc71037ba0cd23113eb6082fa91346ac Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Wed, 13 Apr 2022 15:31:52 -0700 Subject: [PATCH] s3api: Use constant-time string comparisons in check_signature Change-Id: Ibe514a7ab22d475517b1efc50de676f47d741a4c --- swift/common/middleware/s3api/s3request.py | 7 ++++--- test/unit/common/middleware/s3api/test_s3request.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/swift/common/middleware/s3api/s3request.py b/swift/common/middleware/s3api/s3request.py index e0bd434fe2..f53d12b127 100644 --- a/swift/common/middleware/s3api/s3request.py +++ b/swift/common/middleware/s3api/s3request.py @@ -25,7 +25,8 @@ import six from six.moves.urllib.parse import quote, unquote, parse_qsl import string -from swift.common.utils import split_path, json, close_if_possible, md5 +from swift.common.utils import split_path, json, close_if_possible, md5, \ + streq_const_time from swift.common.registry import get_swift_info from swift.common import swob from swift.common.http import HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED, \ @@ -160,7 +161,7 @@ class SigV4Mixin(object): derived_secret, scope_piece.encode('utf8'), sha256).digest() valid_signature = hmac.new( derived_secret, self.string_to_sign, sha256).hexdigest() - return user_signature == valid_signature + return streq_const_time(user_signature, valid_signature) @property def _is_query_auth(self): @@ -559,7 +560,7 @@ class S3Request(swob.Request): secret, self.string_to_sign, sha1).digest()).strip() if not six.PY2: valid_signature = valid_signature.decode('ascii') - return user_signature == valid_signature + return streq_const_time(user_signature, valid_signature) @property def timestamp(self): diff --git a/test/unit/common/middleware/s3api/test_s3request.py b/test/unit/common/middleware/s3api/test_s3request.py index 26a4bee3cb..51eec08482 100644 --- a/test/unit/common/middleware/s3api/test_s3request.py +++ b/test/unit/common/middleware/s3api/test_s3request.py @@ -834,6 +834,11 @@ class TestRequest(S3ApiTestCase): self.assertEqual(expected_sts, sigv2_req._string_to_sign()) self.assertTrue(sigv2_req.check_signature(secret)) + with patch('swift.common.middleware.s3api.s3request.streq_const_time', + return_value=True) as mock_eq: + self.assertTrue(sigv2_req.check_signature(secret)) + mock_eq.assert_called_once() + def test_check_signature_sigv2(self): self._test_check_signature_sigv2( 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY') @@ -874,6 +879,12 @@ class TestRequest(S3ApiTestCase): self.assertFalse(sigv4_req.check_signature( u'\u30c9\u30e9\u30b4\u30f3')) + with patch('swift.common.middleware.s3api.s3request.streq_const_time', + return_value=False) as mock_eq: + self.assertFalse(sigv4_req.check_signature( + u'\u30c9\u30e9\u30b4\u30f3')) + mock_eq.assert_called_once() + @patch.object(S3Request, '_validate_dates', lambda *a: None) def test_check_signature_sigv4_unsigned_payload(self): environ = {