diff options
Diffstat (limited to 'src/scripts')
-rw-r--r-- | src/scripts/fuzzer.xml | 17 | ||||
-rwxr-xr-x | src/scripts/run_tls_attacker.py | 138 | ||||
-rw-r--r-- | src/scripts/tls_scanner/policy.txt | 19 | ||||
-rw-r--r-- | src/scripts/tls_scanner/readme.txt | 5 | ||||
-rwxr-xr-x | src/scripts/tls_scanner/tls_scanner.py | 60 | ||||
-rw-r--r-- | src/scripts/tls_scanner/urls.txt | 61 |
6 files changed, 300 insertions, 0 deletions
diff --git a/src/scripts/fuzzer.xml b/src/scripts/fuzzer.xml new file mode 100644 index 000000000..9c3d86551 --- /dev/null +++ b/src/scripts/fuzzer.xml @@ -0,0 +1,17 @@ +<!-- This is a template for a config file for fuzzing with TLS-Attacker --> + +<startupCommandsHolder> + <serverCommand>$botan_cli </serverCommand> + <serverPort>$tls_port</serverPort> + <workflowFolder>$workflow_dir</workflowFolder> + <modifiedVariableTypes>TLS_CONSTANT,LENGTH,COUNT,PUBLIC_KEY,PADDING,SIGNATURE,PLAIN_PROTOCOL_MESSAGE</modifiedVariableTypes> + <outputFolder>/tmp/</outputFolder> + <startupCommandsList> + <startupCommands> + <fuzzerCommand>simple_fuzzer -connect localhost:$PORT</fuzzerCommand> + <serverCommandParameters>tls_server $rsa_cert $rsa_key --port=$PORT --policy=$fuzz_policy --output=/tmp/botan_output.log --error-output=/tmp/botan_error_output.log </serverCommandParameters> + <shortName>botan-rsa</shortName> + </startupCommands> + <!-- TODO ECDSA --> + </startupCommandsList> +</startupCommandsHolder> diff --git a/src/scripts/run_tls_attacker.py b/src/scripts/run_tls_attacker.py new file mode 100755 index 000000000..a77364633 --- /dev/null +++ b/src/scripts/run_tls_attacker.py @@ -0,0 +1,138 @@ +#!/usr/bin/python + +import os +import sys +import subprocess +import tempfile +import time +import random +import optparse +import string + +def run_subprocess(cmd): + print("Running '%s'" % (' '.join(cmd))) + + proc = subprocess.Popen(cmd, bufsize=-1) + proc.communicate() + + if proc.returncode != 0: + print('Running "%s" failed rc %d' % (' '.join(cmd), proc.returncode)) + sys.exit(proc.returncode) + +def spawn_server(cmd): + print("Spawning '%s'" % (' '.join(cmd))) + return subprocess.Popen(cmd, bufsize=-1)#,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + +def main(args=None): + if args is None: + args = sys.argv + + parser = optparse.OptionParser() + + parser.add_option('--type', default='tests', + help='Which TLS-Attacker tests to run (tests, policy, fuzzer)') + parser.add_option('--src-dir', metavar='DIR', default='./src', + help='Specify path to botan sources (default "%default")') + parser.add_option('--verbose', action='store_true', + help='Be noisy') + + (options, args) = parser.parse_args(args) + + if len(args) != 3: + print("Usage: %s botan_cli_exe botan_ci_tools" % (args[0])) + return 1 + + cli_exe = args[1] + ci_tools = args[2] + test_type = options.type + src_dir = options.src_dir + + if test_type not in ['tests', 'policy', 'fuzzer']: + print("Unknown --type %s" % (options.test_type)) + return 1 + + if os.access(cli_exe, os.X_OK) != True: + print("Unable to find CLI tool at %s" % (cli_exe)) + return 1 + + if os.access(src_dir, os.X_OK) != True: + print("Unable to find src dir at %s" % (src_dir)) + return 1 + + test_data_dir = os.path.join(src_dir, 'tests/data') + + lax_policy_txt = os.path.join(test_data_dir, 'tls-policy/compat.txt') + bsi_policy_txt = os.path.join(test_data_dir, 'tls-policy/bsi.txt') + + tls_attacker_dir = os.path.join(ci_tools, 'TLS-Attacker') + tls_attacker_jar = os.path.join(tls_attacker_dir, 'TLS-Attacker-1.2.jar') + tls_attacker_testsuites = os.path.join(tls_attacker_dir, 'resources/testsuite') + tls_fuzzer_workflows = os.path.join(tls_attacker_dir, 'resources/fuzzing/workflows') + + if os.access(tls_attacker_jar, os.R_OK) != True: + print("Unable to find TLS-Attacker jar at %s" % (tls_attacker_jar)) + return 1 + + rsa_key = tempfile.NamedTemporaryFile(prefix='rsa_key_') + rsa_crt = tempfile.NamedTemporaryFile(prefix='rsa_crt_') + + run_subprocess([cli_exe, 'keygen', '--algo=RSA', '--params=2048', '--output=%s' % (rsa_key.name)]) + run_subprocess([cli_exe, 'gen_self_signed', rsa_key.name, 'localhost', '--output=%s' % (rsa_crt.name)]) + + server_log = 'botan_log.txt' + server_err_log = 'botan_err_log.txt' + + tls_port = random.randint(50000, 60000) + + botan_server_cmd = [cli_exe, 'tls_server', rsa_crt.name, rsa_key.name, + '--port=%d' % (tls_port), + '--output='+server_log, + '--error-output='+server_err_log] + + java_tls_attacker = ['java', '-jar', tls_attacker_jar, + '-loglevel', 'DEBUG' if options.verbose else 'ERROR'] + tls_attacker_opts = ['-tls_timeout', '300', '-connect', 'localhost:%d' % (tls_port)] + + if test_type == 'tests': + try: + server_process = spawn_server(botan_server_cmd + + ['--policy=%s' % (lax_policy_txt)]) + time.sleep(1) + run_subprocess(java_tls_attacker + ['testsuite_server'] + tls_attacker_opts + + ['-folder', tls_attacker_testsuites]) + finally: + server_process.terminate() + elif test_type == 'policy': + try: + server_process = spawn_server(botan_server_cmd + + ['--policy=%s' % (bsi_policy_txt)]) + time.sleep(1) + run_subprocess(java_tls_attacker + ['testtls_server'] + tls_attacker_opts + + ['-policy', bsi_policy_txt]) + finally: + server_process.terminate() + elif test_type == 'fuzzer': + + template_mapping = { + 'rsa_key': rsa_key.name, + 'rsa_cert': rsa_crt.name, + 'botan_cli': cli_exe, + 'workflow_dir': tls_fuzzer_workflows, + 'fuzz_policy': lax_policy_txt, + 'tls_port': str(tls_port), + 'PORT': '$PORT' # this is a var for TLS-Attacker don't touch it + } + + template_txt = open(os.path.join(src_dir, 'scripts/fuzzer.xml')).read() + + config = string.Template(template_txt).substitute(template_mapping) + + fuzzer_config = tempfile.NamedTemporaryFile(prefix='fuzzer_cfg_', delete=False) + fuzzer_config.write(config.encode('ascii')) + fuzzer_config.close() + + run_subprocess(java_tls_attacker + ['multi_fuzzer'] + + ['-startup_command_file', fuzzer_config.name]) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/scripts/tls_scanner/policy.txt b/src/scripts/tls_scanner/policy.txt new file mode 100644 index 000000000..a9854ee54 --- /dev/null +++ b/src/scripts/tls_scanner/policy.txt @@ -0,0 +1,19 @@ +allow_tls10=true +allow_tls11=true +allow_tls12=true +allow_dtls10=false +allow_dtls12=false + +# Camellia first just to see if there is anyone out there who will negotiate it with us +ciphers=Camellia-128 Camellia-256 Camellia-128/GCM Camellia-256/GCM ChaCha20Poly1305 AES-256/GCM AES-128/GCM AES-256 AES-128 +signature_hashes=SHA-384 SHA-256 SHA-1 +macs=AEAD SHA-384 SHA-256 SHA-1 +key_exchange_methods=CECPQ1 ECDH DH RSA +signature_methods=ECDSA RSA DSA +ecc_curves=x25519 secp256r1 secp384r1 +minimum_dh_group_size=1024 +minimum_ecdh_group_size=255 +minimum_rsa_bits=2048 + +allow_insecure_renegotiation=false +allow_server_initiated_renegotiation=false diff --git a/src/scripts/tls_scanner/readme.txt b/src/scripts/tls_scanner/readme.txt new file mode 100644 index 000000000..a4754b02d --- /dev/null +++ b/src/scripts/tls_scanner/readme.txt @@ -0,0 +1,5 @@ + +Simple script to scan hosts to check basic TLS client compatability. + +URL list chosen mostly from large tech/software vendors, feel free to +send suggestions. diff --git a/src/scripts/tls_scanner/tls_scanner.py b/src/scripts/tls_scanner/tls_scanner.py new file mode 100755 index 000000000..8fdf046ca --- /dev/null +++ b/src/scripts/tls_scanner/tls_scanner.py @@ -0,0 +1,60 @@ +#!/usr/bin/python2 + +import sys +import time +import subprocess +import re + +def format_report(client_output): + version_re = re.compile('TLS (v1\.[0-2]) using ([A-Z0-9_]+)') + + version_match = version_re.search(client_output) + + #print client_output + + if version_match: + return "Established %s %s" % (version_match.group(1), version_match.group(2)) + else: + return client_output + +def scanner(args = None): + if args is None: + args = sys.argv + + if len(args) != 2: + print "Error: Usage tls_scanner.py host_file" + return 2 + + scanners = {} + + for url in [s.strip() for s in open(args[1]).readlines()]: + scanners[url] = subprocess.Popen(['../../../botan', 'tls_client', '--policy=policy.txt', url], + stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + + for url in scanners.keys(): + scanners[url].stdin.close() + + report = {} + timeout = 10 + + for url in scanners.keys(): + print "waiting for", url + + for i in range(timeout): + scanners[url].poll() + if scanners[url].returncode != None: + break + #print "Waiting %d more seconds for %s" % (timeout-i, url) + time.sleep(1) + + if scanners[url].returncode != None: + output = scanners[url].stdout.read() + scanners[url].stderr.read() + report[url] = format_report(output) + + for url in report.keys(): + print url, ":", report[url] + + return 0 + +if __name__ == '__main__': + sys.exit(scanner()) diff --git a/src/scripts/tls_scanner/urls.txt b/src/scripts/tls_scanner/urls.txt new file mode 100644 index 000000000..a5bcf349e --- /dev/null +++ b/src/scripts/tls_scanner/urls.txt @@ -0,0 +1,61 @@ +adobe.com +adp.com +airbnb.com +akamai.com +amazon.com +apache.org +apple.com +bbc.co.uk +bing.com +ca.com +cisco.com +citrix.com +cloudflare.com +craigslist.org +dell.com +ebay.com +facebook.com +github.com +gmail.com +google.com +hp.com +huawei.com +ibm.com +ietf.org +intuit.com +linkedin.com +medium.com +microsoft.com +mikestoolbox.org +nec.com +netflix.com +openssl.org +oracle.com +sgi.com +chase.com +bankofamerica.com +citibank.com +wellsfargo.com +ebay.com +paypal.com +pwc.com +randombit.net +reddit.com +redhat.com +salesforce.com +sas.com +siemens.com +sony.com +stripe.com +symantec.com +tls.mbed.org +twitter.com +uber.com +vmware.com +whatsapp.com +wikipedia.org +www.iso.org +www.lg.com +yahoo.com +yandex.ru +youtube.com |