From f5bb3f9c15d1a940d484cc8d172d5d908a4bf75d Mon Sep 17 00:00:00 2001 From: Kyle Marsh Date: Wed, 10 Aug 2011 11:27:06 -0700 Subject: [PATCH] S3 Fuzzer: implemented decision expansion Decision reached by descending the graph describing the attack surface can be expanded to fill in all the placeholders --- s3tests/functional/test_fuzzer.py | 29 ++++++++++++++++++++++++++++- s3tests/fuzz_headers.py | 20 +++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/s3tests/functional/test_fuzzer.py b/s3tests/functional/test_fuzzer.py index b8393fb..031e59f 100644 --- a/s3tests/functional/test_fuzzer.py +++ b/s3tests/functional/test_fuzzer.py @@ -107,6 +107,33 @@ def test_assemble_decision(): eq(decision['path'], '/{bucket_readable}') assert_raises(KeyError, lambda x: decision[x], 'key3') +def test_expand_key(): + prng = random.Random(1) + test_decision = { + 'key1': 'value1', + 'randkey': 'value-{random 10-15 printable}', + 'indirect': '{key1}', + 'dbl_indirect': '{indirect}' + } + decision = SpecialVariables(test_decision, prng) + + randkey = expand_key(decision, 'randkey') + indirect = expand_key(decision, 'indirect') + dbl_indirect = expand_key(decision, 'dbl_indirect') + + eq(indirect, 'value1') + eq(dbl_indirect, 'value1') + eq(randkey, 'value-[/pNI$;92@') + +def test_expand_loop(): + prng = random.Random(1) + test_decision = { + 'key1': '{key2}', + 'key2': '{key1}', + } + decision = SpecialVariables(test_decision, prng) + assert_raises(RuntimeError, expand_key, decision, 'key1') + def test_expand_decision(): graph = build_graph() prng = random.Random(1) @@ -119,6 +146,6 @@ def test_expand_decision(): eq(request['key1'], 'value1') eq(request['indirect_key1'], 'value1') eq(request['path'], '/my-readable-bucket') - eq(request['randkey'], 'value-?') #FIXME: again, how to handle the pseudorandom content? + eq(request['randkey'], 'value-NI$;92@H/0I') #FIXME: again, how to handle the pseudorandom content? assert_raises(KeyError, lambda x: decision[x], 'key3') diff --git a/s3tests/fuzz_headers.py b/s3tests/fuzz_headers.py index 3ac6464..54095b6 100644 --- a/s3tests/fuzz_headers.py +++ b/s3tests/fuzz_headers.py @@ -4,6 +4,7 @@ from boto import UserAgent from . import common import traceback +import itertools import random import string import yaml @@ -44,7 +45,24 @@ def expand_decision(decision, prng): decision's values and headers until all values are fully expanded and build a request out of the information """ - raise NotImplementedError + special_decision = SpecialVariables(decision, prng) + for key in special_decision: + decision[key] = expand_key(special_decision, key) + + return decision + + +def expand_key(decision, key): + c = itertools.count() + fmt = string.Formatter() + old = decision[key] + while True: + new = fmt.vformat(old, [], decision) + if new == old: + return old + if next(c) > 5: + raise RuntimeError + old = new class SpecialVariables(dict):