mirror of
https://github.com/mozilla/cipherscan.git
synced 2024-12-26 04:33:42 +01:00
First shot at cipherscan results analyzer
This commit is contained in:
parent
ca0ef2fc5c
commit
34b2eb7819
121
analyze.py
Normal file
121
analyze.py
Normal file
@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]
|
||||
|
||||
import fileinput
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
from collections import defaultdict
|
||||
|
||||
def is_fubar(results):
|
||||
fubar_ciphers = set(all_ciphers) - set(old_ciphers)
|
||||
for conn in results['ciphersuite']:
|
||||
if conn['cipher'] in fubar_ciphers:
|
||||
return True
|
||||
if 'SSLv2' in conn['protocols']:
|
||||
return True
|
||||
if conn['pubkey'] < 2048:
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_old(results):
|
||||
for conn in results['ciphersuite']:
|
||||
if conn['cipher'] not in old_ciphers:
|
||||
return False
|
||||
if 'SSLv3' not in conn['protocols']:
|
||||
return False
|
||||
if 'sha1WithRSAEncryption' not in conn['sigalg']:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_intermediate(results):
|
||||
for conn in results['ciphersuite']:
|
||||
if conn['cipher'] not in intermediate_ciphers:
|
||||
return False
|
||||
if len(set(conn['protocols']) - set(['TLSv1', 'TLSv1.1', 'TLSv1.2'])) > 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_modern(results):
|
||||
for conn in results['ciphersuite']:
|
||||
if conn['cipher'] not in modern_ciphers:
|
||||
errors["modern"]["ciphers"].append(conn['cipher'])
|
||||
return False
|
||||
if len(set(conn['protocols']) - set(['TLSv1.1', 'TLSv1.2'])) > 0:
|
||||
# deprecated protocols are supported
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_ordered(results, ciphersuite):
|
||||
return True
|
||||
|
||||
def evaluate(results):
|
||||
status = "obscure unknown ssl"
|
||||
|
||||
if len(results['ciphersuite']) == 0:
|
||||
status = "no ssl"
|
||||
|
||||
if is_modern(results):
|
||||
if is_ordered(results, modern_ciphers):
|
||||
status = "modern tls"
|
||||
else:
|
||||
status = "modern tls with bad ordering"
|
||||
|
||||
if is_intermediate(results):
|
||||
if is_ordered(results, intermediate_ciphers):
|
||||
status = "intermediate tls"
|
||||
else:
|
||||
status = "intermediate tls with bad ordering"
|
||||
|
||||
if is_old(results):
|
||||
if is_ordered(results, old_ciphers):
|
||||
status = "old ssl"
|
||||
else:
|
||||
status = "old ssl with bad ordering"
|
||||
|
||||
if is_fubar(results):
|
||||
status = "fubar ssl"
|
||||
|
||||
return status
|
||||
|
||||
def process_results(data):
|
||||
results = dict()
|
||||
try:
|
||||
results = json.loads(data)
|
||||
except ValueError, e:
|
||||
print("invalid json data")
|
||||
try:
|
||||
if results:
|
||||
print(results['target'] + " has " + evaluate(results))
|
||||
except TypeError, e:
|
||||
pass
|
||||
|
||||
def main():
|
||||
global all_ciphers, old_ciphers, intermediate_ciphers, modern_ciphers, errors
|
||||
all_ciphers = subprocess.check_output(['./openssl', 'ciphers', all_ciphersuite]).rstrip().split(':')
|
||||
old_ciphers = subprocess.check_output(['./openssl', 'ciphers', old_ciphersuite]).rstrip().split(':')
|
||||
intermediate_ciphers = subprocess.check_output(['./openssl', 'ciphers', intermediate_ciphersuite]).rstrip().split(':')
|
||||
modern_ciphers = subprocess.check_output(['./openssl', 'ciphers', modern_ciphersuite]).rstrip().split(':')
|
||||
if len(sys.argv) > 1:
|
||||
# evaluate target specified as argument
|
||||
data = subprocess.check_output(['./cipherscan', '-j', sys.argv[1]])
|
||||
process_results(data)
|
||||
else:
|
||||
# take input from stdin
|
||||
for data in fileinput.input():
|
||||
if data:
|
||||
process_results(data)
|
||||
print errors
|
||||
# from https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||
all_ciphersuite = "ALL:COMPLEMENTOFALL:+aRSA"
|
||||
old_ciphersuite = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
|
||||
intermediate_ciphersuite = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
|
||||
modern_ciphersuite = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"
|
||||
errors = defaultdict(str)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user