From 0a14248cea24876d885f0a0c819a9e54f6026b9e Mon Sep 17 00:00:00 2001 From: Dolph Mathews Date: Wed, 2 Sep 2015 13:43:01 +0000 Subject: [PATCH] Test token validation using manipulated tokens This test manipulates UUID, PKI, PKIz, and Fernet tokens by incrementing and decrementing individual bytes. This illustrates that the resulting tokens cannot be validated online against keystone. Change-Id: I633c4932d04ce490e5fc84e75dc227a39e486ee3 Related-Bug: 1490804 --- keystone/tests/unit/test_v3_auth.py | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/keystone/tests/unit/test_v3_auth.py b/keystone/tests/unit/test_v3_auth.py index 96f0ff1..c91798c 100644 --- a/keystone/tests/unit/test_v3_auth.py +++ b/keystone/tests/unit/test_v3_auth.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import base64 import copy import datetime import json @@ -421,6 +422,54 @@ class TokenAPITests(object): headers={'X-Subject-Token': v3_token}) self.assertValidProjectScopedTokenResponse(r, require_catalog=False) + def _preprocess_manipulation(self, token): + """Process a token prior to further manipulation.""" + # By default, do not manipulate the token at all. + return token + + def _postprocess_manipulation(self, token): + """Process a token after it has been manipulated.""" + return token + + def test_manipulated_token_fails_validation(self): + v3_token = self._preprocess_manipulation(self.v3_token) + + # This illustrates that _preprocess_manipulation and + # _postprocess_manipulation are inverses of each other which produce + # the original, valid token. + manipulated_token = self._postprocess_manipulation(v3_token) + self.head( + '/auth/tokens', + headers={'X-Subject-Token': manipulated_token}, + expected_status=200) + + # Manipulating every single character takes a lot of CPU time. Instead, + # we can concentrate on the beginning and end of longer tokens. For + # shorter tokens, this set of indexes will include every index. + indexes = list(range(len(v3_token))) + # indexes = set(indexes[:20] + indexes[-20:]) + + for i in indexes: + manipulated_token = self._postprocess_manipulation( + v3_token[:i] + + chr((ord(v3_token[i]) + 1) % 256) + + v3_token[i + 1:]) + + self.head( + '/auth/tokens', + headers={'X-Subject-Token': manipulated_token}, + expected_status=404) + + manipulated_token = self._postprocess_manipulation( + v3_token[:i] + + chr((ord(v3_token[i]) - 1) % 256) + + v3_token[i + 1:]) + + self.head( + '/auth/tokens', + headers={'X-Subject-Token': manipulated_token}, + expected_status=404) + class AllowRescopeScopedTokenDisabledTests(test_v3.RestfulTestCase): def config_overrides(self): @@ -561,6 +610,14 @@ class TestPKITokenAPIs(test_v3.RestfulTestCase, TokenAPITests): self.assertEqual(v2_token['access']['user']['roles'][0]['id'], token_data['token']['roles'][0]['id']) + def _preprocess_manipulation(self, token): + """Allow each token test to process tokens prior to manipulation.""" + return base64.b64decode(token.replace('-', '/')) + + def _postprocess_manipulation(self, token): + """Allow each token test to process tokens after manipulation.""" + return base64.b64encode(token).replace('/', '-') + class TestPKIZTokenAPIs(TestPKITokenAPIs): def config_overrides(self): @@ -570,6 +627,14 @@ class TestPKIZTokenAPIs(TestPKITokenAPIs): def verify_token(self, *args, **kwargs): return cms.pkiz_verify(*args, **kwargs) + def _preprocess_manipulation(self, token): + """Allow each token test to process tokens prior to manipulation.""" + return base64.urlsafe_b64decode(token[len('PKIZ_'):]) + + def _postprocess_manipulation(self, token): + """Allow each token test to process tokens after manipulation.""" + return 'PKIZ_' + base64.urlsafe_b64encode(token) + class TestUUIDTokenAPIs(test_v3.RestfulTestCase, TokenAPITests): def config_overrides(self): -- 2.1.4