Add Security Analyze
This commit is contained in:
parent
be8e039d30
commit
43ebb12f4c
86
README.md
86
README.md
@ -1,10 +1,12 @@
|
||||
# SSL Checker
|
||||
#### Simple Python script that collects SSL information from hosts
|
||||
#### Python script that collects SSL information from hosts
|
||||
|
||||
## About
|
||||
|
||||
It's a simple script running in python that collects SSL information then it returns the group of information in JSON. It can also connects trough your specified SOCKS server.
|
||||
|
||||
One of the good thing about this script, is that it will full analyze the SSL certificate for security issue's and will include the report in the output or CSV file.
|
||||
|
||||
## Requirements
|
||||
|
||||
You only need to installl pyOpenSSL:
|
||||
@ -15,17 +17,20 @@ You only need to installl pyOpenSSL:
|
||||
|
||||
```
|
||||
./ssl_checker.py -h
|
||||
usage: ssl_checker.py -H [HOSTS [HOSTS ...]] [-s HOST:PORT] [-j]
|
||||
[-c FILENAME.CSV] [-p] [-h]
|
||||
usage: ssl_checker.py -H [HOSTS [HOSTS ...]] [-s HOST:PORT] [-c FILENAME.CSV]
|
||||
[-j] [-a] [-p] [-h]
|
||||
|
||||
Collects useful information about given host's SSL certificates.
|
||||
|
||||
optional arguments:
|
||||
-H [HOSTS [HOSTS ...]], --host [HOSTS [HOSTS ...]]
|
||||
Hosts as input separated by space
|
||||
-s HOST:PORT, --socks HOST:PORT
|
||||
Enable SOCKS proxy for connection
|
||||
-j, --json Enable JSON in the output
|
||||
-c FILENAME.CSV, --csv FILENAME.CSV
|
||||
Enable CSV file export
|
||||
-j, --json Enable JSON in the output
|
||||
-a, --analyze Enable SSL security analysis on the host
|
||||
-p, --pretty Print pretty and more human readable Json
|
||||
-h, --help Show this help message and exit
|
||||
```
|
||||
@ -38,9 +43,11 @@ Port is optional here. The script will use 443 if not specified.
|
||||
|
||||
`-s, --socks ` Enable connection through SOCKS server
|
||||
|
||||
`-c, --csv ` Enable CSV file export by specifying filename.csv after this argument
|
||||
|
||||
`-j, --json ` Use this if you want to only have the result in JSON
|
||||
|
||||
`-c, --csv ` Enable CSV file export by specifying filename.csv after this argument
|
||||
`-a, --analyze` This argument will include security analyze on the certificate. It will take more time.
|
||||
|
||||
`-p, --pretty ` Use this with `-j` to print indented and human readable JSON
|
||||
|
||||
@ -87,41 +94,80 @@ Analyzing 1 host(s):
|
||||
## Example
|
||||
|
||||
```
|
||||
narbeh@narbeh-xps:~/ssl-checker$ ./ssl_checker.py -H narbeh.org google.com:443 facebook.com
|
||||
Analyzing 3 host(s):
|
||||
-------------------
|
||||
narbeh@narbeh-xps:~/ssl-checker$ ./ssl_checker.py -H narbeh.org google.com:443
|
||||
Analyzing 2 host(s):
|
||||
---------------------
|
||||
|
||||
[+] narbeh.org
|
||||
|
||||
Issued domain: narbeh.org
|
||||
Issued by: Let's Encrypt
|
||||
Issued to: None
|
||||
Issued by: Let's Encrypt (US)
|
||||
Valid from: 2018-04-21
|
||||
Valid to: 2018-07-20 (89 days left)
|
||||
Valid to: 2018-07-20 (88 days left)
|
||||
Validity days: 90
|
||||
Certificate S/N: 338163108483756707389368573553026254634358
|
||||
Certificate version: 2
|
||||
Certificate algorithm: sha256WithRSAEncryption
|
||||
Expired: False
|
||||
----
|
||||
|
||||
[+] google.com
|
||||
|
||||
Issued domain: *.google.com
|
||||
Issued by: Google Inc
|
||||
Issued to: Google Inc
|
||||
Issued by: Google Inc (US)
|
||||
Valid from: 2018-03-28
|
||||
Valid to: 2018-06-20 (59 days left)
|
||||
Valid to: 2018-06-20 (58 days left)
|
||||
Validity days: 83
|
||||
Certificate S/N: 2989116342670522968
|
||||
Certificate version: 2
|
||||
Certificate algorithm: sha256WithRSAEncryption
|
||||
Expired: False
|
||||
----
|
||||
[-] facebook.com Failed: [Errno 111] Connection refused
|
||||
----
|
||||
|
||||
2 successful and 1 failed
|
||||
|
||||
2 successful and 0 failed
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Security Analyze
|
||||
|
||||
By passing `-a/--analyze` to the script, it will scan the certificate for security issues and vulnerabilities. It will also mark a grade for the certificate. **This will take more time to finish.**
|
||||
|
||||
```
|
||||
Analyzing 1 host(s):
|
||||
---------------------
|
||||
|
||||
Warning: -a/--analyze is enabled. It takes more time...
|
||||
|
||||
[+] narbeh.org
|
||||
|
||||
Issued domain: narbeh.org
|
||||
Issued to: None
|
||||
Issued by: Let's Encrypt (US)
|
||||
Valid from: 2018-04-21
|
||||
Valid to: 2018-07-20 (88 days left)
|
||||
Validity days: 90
|
||||
Certificate S/N: 338163108483756707389368573553026254634358
|
||||
Certificate version: 2
|
||||
Certificate algorithm: sha256WithRSAEncryption
|
||||
Certificate grade: A
|
||||
Poodle vulnerability: False
|
||||
Heartbleed vulnerability: False
|
||||
Hearbeat vulnerability: True
|
||||
Freak vulnerability: False
|
||||
Logjam vulnerability: False
|
||||
Drown vulnerability: False
|
||||
Expired: False
|
||||
|
||||
|
||||
1 successful and 0 failed
|
||||
```
|
||||
|
||||
|
||||
|
||||
##JSON And CSV Output
|
||||
|
||||
Example only with the `-j/--json` and `-p/--pretty` arguments which shows the JSON only. Perfect for piping to another tool.
|
||||
|
||||
```
|
||||
@ -130,6 +176,7 @@ narbeh@narbeh-xps:~/ssl-checker$ ./ssl_checker.py -j -p -H narbeh.org:443 test.
|
||||
'cert_exp': False,
|
||||
'cert_sn': 338163108483756707389368573553026254634358L,
|
||||
'cert_ver': 2,
|
||||
'issued_o': None,
|
||||
'issued_to': u'narbeh.org',
|
||||
'issuer_c': u'US',
|
||||
'issuer_cn': u"Let's Encrypt Authority X3",
|
||||
@ -142,6 +189,7 @@ narbeh@narbeh-xps:~/ssl-checker$ ./ssl_checker.py -j -p -H narbeh.org:443 test.
|
||||
'cert_exp': False,
|
||||
'cert_sn': 73932709062103623902948514363737041075L,
|
||||
'cert_ver': 2,
|
||||
'issued_o': None,
|
||||
'issued_to': u'www.test.com',
|
||||
'issuer_c': u'US',
|
||||
'issuer_cn': u'Network Solutions DV Server CA 2',
|
||||
@ -176,3 +224,7 @@ cert_sn,338163108483756707389368573553026254634358
|
||||
|
||||
|
||||
|
||||
### Author
|
||||
|
||||
Narbeh Arakil
|
||||
http://narbeh.org
|
||||
@ -43,6 +43,40 @@ def get_cert(host, port, user_args):
|
||||
return cert
|
||||
|
||||
|
||||
def analyze_ssl(host, context):
|
||||
"""Analyze the security of the SSL certificate."""
|
||||
from json import loads
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
|
||||
api_url = 'https://api.ssllabs.com/api/v3/'
|
||||
counter = 0
|
||||
|
||||
while True:
|
||||
main_request = loads(urlopen(api_url + 'analyze?host={}'.format(host)).read().decode('utf-8'))
|
||||
if main_request['status'] in ['DNS', 'IN_PROGRESS']:
|
||||
print('Analyzing {}. Please wait'.format(host) + '.' * counter)
|
||||
sys.stdout.write("\033[F")
|
||||
counter += 1
|
||||
continue
|
||||
elif main_request['status'] == 'READY':
|
||||
break
|
||||
|
||||
context[host]['grade'] = main_request['endpoints'][0]['grade']
|
||||
endpoint_data = loads(urlopen(api_url + 'getEndpointData?host={}&s={}'.format(host, main_request['endpoints'][0]['ipAddress'])).read().decode('utf-8'))
|
||||
|
||||
context[host]['poodle_vuln'] = endpoint_data['details']['poodle']
|
||||
context[host]['heartbleed_vuln'] = endpoint_data['details']['heartbleed']
|
||||
context[host]['heartbeat_vuln'] = endpoint_data['details']['heartbeat']
|
||||
context[host]['freak_vuln'] = endpoint_data['details']['freak']
|
||||
context[host]['logjam_vuln'] = endpoint_data['details']['logjam']
|
||||
context[host]['drownVulnerable'] = endpoint_data['details']['drownVulnerable']
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_cert_info(host, cert):
|
||||
"""Get all the information about cert and create a JSON file."""
|
||||
context = {}
|
||||
@ -76,7 +110,7 @@ def get_cert_info(host, cert):
|
||||
return context
|
||||
|
||||
|
||||
def print_status(host, context):
|
||||
def print_status(host, context, analyze=False):
|
||||
"""Print all the usefull info about host."""
|
||||
days_left = (datetime.strptime(context[host]['valid_till'], '%Y-%m-%d') - datetime.now()).days
|
||||
|
||||
@ -90,8 +124,18 @@ def print_status(host, context):
|
||||
print('\t\tCertificate S/N: {}'.format(context[host]['cert_sn']))
|
||||
print('\t\tCertificate version: {}'.format(context[host]['cert_ver']))
|
||||
print('\t\tCertificate algorithm: {}'.format(context[host]['cert_alg']))
|
||||
print('\t\tExpired: {}'.format(context[host]['cert_exp']))
|
||||
print('\t----')
|
||||
|
||||
if analyze:
|
||||
print('\t\tCertificate grade: {}'.format(context[host]['grade']))
|
||||
print('\t\tPoodle vulnerability: {}'.format(context[host]['poodle_vuln']))
|
||||
print('\t\tHeartbleed vulnerability: {}'.format(context[host]['heartbleed_vuln']))
|
||||
print('\t\tHearbeat vulnerability: {}'.format(context[host]['heartbeat_vuln']))
|
||||
print('\t\tFreak vulnerability: {}'.format(context[host]['freak_vuln']))
|
||||
print('\t\tLogjam vulnerability: {}'.format(context[host]['logjam_vuln']))
|
||||
print('\t\tDrown vulnerability: {}'.format(context[host]['drownVulnerable']))
|
||||
|
||||
|
||||
print('\t\tExpired: {}\n'.format(context[host]['cert_exp']))
|
||||
|
||||
|
||||
def show_result(user_args):
|
||||
@ -103,6 +147,9 @@ def show_result(user_args):
|
||||
if not user_args.json_true:
|
||||
print('Analyzing {} host(s):\n{}\n'.format(len(hosts), '-' * 21))
|
||||
|
||||
if not user_args.json_true and user_args.analyze:
|
||||
print('{}Warning: -a/--analyze is enabled. It takes more time...{}\n'.format(Clr.YELLOW, Clr.RST))
|
||||
|
||||
for host in hosts:
|
||||
host, port = filter_hostname(host)
|
||||
|
||||
@ -113,14 +160,21 @@ def show_result(user_args):
|
||||
try:
|
||||
cert = get_cert(host, port, user_args)
|
||||
context[host] = get_cert_info(host, cert)
|
||||
|
||||
# Analyze the certificate if enabled
|
||||
if user_args.analyze:
|
||||
context = analyze_ssl(host, context)
|
||||
|
||||
if not user_args.json_true:
|
||||
print_status(host, context)
|
||||
print_status(host, context, user_args.analyze)
|
||||
except Exception as error:
|
||||
if not user_args.json_true:
|
||||
print('\t{}[-]{} {:<20s} Failed: {}'.format(Clr.RED, Clr.RST, host, error))
|
||||
print('\t----')
|
||||
print('\t{}[-]{} {:<20s} Failed: {}\n'.format(Clr.RED, Clr.RST, host, error))
|
||||
failed_cnt += 1
|
||||
except KeyboardInterrupt:
|
||||
print('{}Canceling script...{}\n'.format(Clr.YELLOW, Clr.RST))
|
||||
sys.exit(1)
|
||||
|
||||
failed_cnt += 1
|
||||
|
||||
if not user_args.json_true:
|
||||
print('\n{} successful and {} failed\n'.format(len(hosts) - failed_cnt, failed_cnt))
|
||||
@ -160,18 +214,21 @@ def filter_hostname(host):
|
||||
def get_args():
|
||||
"""Set argparse options."""
|
||||
parser = ArgumentParser(prog='ssl_checker.py', add_help=False,
|
||||
description="""Collects useful information about given hosts SSL certificates.""")
|
||||
description="""Collects useful information about given host's SSL certificates.""")
|
||||
parser.add_argument('-H', '--host', dest='hosts', nargs='*', required=True,
|
||||
help='Hosts as input separated by space')
|
||||
parser.add_argument('-s', '--socks', dest='socks',
|
||||
default=False, metavar='HOST:PORT',
|
||||
help='Enable SOCKS proxy for connection')
|
||||
parser.add_argument('-j', '--json', dest='json_true',
|
||||
action='store_true', default=False,
|
||||
help='Enable JSON in the output')
|
||||
parser.add_argument('-c', '--csv', dest='csv_enabled',
|
||||
default=False, metavar='FILENAME.CSV',
|
||||
help='Enable CSV file export')
|
||||
parser.add_argument('-j', '--json', dest='json_true',
|
||||
action='store_true', default=False,
|
||||
help='Enable JSON in the output')
|
||||
parser.add_argument('-a', '--analyze', dest='analyze',
|
||||
default=False, action='store_true',
|
||||
help='Enable SSL security analysis on the host')
|
||||
parser.add_argument('-p', '--pretty', dest='pretty_output',
|
||||
action='store_true', default=False,
|
||||
help='Print pretty and more human readable Json')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user