commit
d71bb1531f
@ -25,11 +25,13 @@ class Clr:
|
|||||||
YELLOW = '\033[33m'
|
YELLOW = '\033[33m'
|
||||||
|
|
||||||
|
|
||||||
def get_cert(host, port, user_args):
|
class SSLChecker:
|
||||||
|
|
||||||
|
def get_cert(self, host, port, user_args):
|
||||||
"""Connection to the host."""
|
"""Connection to the host."""
|
||||||
if user_args.socks:
|
if user_args.socks:
|
||||||
import socks
|
import socks
|
||||||
socks_host, socks_port = filter_hostname(user_args.socks)
|
socks_host, socks_port = self.filter_hostname(user_args.socks)
|
||||||
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, socks_host, int(socks_port), True)
|
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, socks_host, int(socks_port), True)
|
||||||
socket.socket = socks.socksocket
|
socket.socket = socks.socksocket
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ def get_cert(host, port, user_args):
|
|||||||
return cert
|
return cert
|
||||||
|
|
||||||
|
|
||||||
def border_msg(message):
|
def border_msg(self, message):
|
||||||
"""Print the message in the box."""
|
"""Print the message in the box."""
|
||||||
row = len(message)
|
row = len(message)
|
||||||
h = ''.join(['+'] + ['-' * row] + ['+'])
|
h = ''.join(['+'] + ['-' * row] + ['+'])
|
||||||
@ -54,7 +56,7 @@ def border_msg(message):
|
|||||||
print(result)
|
print(result)
|
||||||
|
|
||||||
|
|
||||||
def analyze_ssl(host, context):
|
def analyze_ssl(self, host, context):
|
||||||
"""Analyze the security of the SSL certificate."""
|
"""Analyze the security of the SSL certificate."""
|
||||||
try:
|
try:
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
@ -88,7 +90,7 @@ def analyze_ssl(host, context):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
def get_cert_sans(x509cert):
|
def get_cert_sans(self, x509cert):
|
||||||
"""
|
"""
|
||||||
Get Subject Alt Names from Certificate. Shameless taken from stack overflow:
|
Get Subject Alt Names from Certificate. Shameless taken from stack overflow:
|
||||||
https://stackoverflow.com/users/4547691/anatolii-chmykhalo
|
https://stackoverflow.com/users/4547691/anatolii-chmykhalo
|
||||||
@ -104,7 +106,7 @@ def get_cert_sans(x509cert):
|
|||||||
return san
|
return san
|
||||||
|
|
||||||
|
|
||||||
def get_cert_info(host, cert):
|
def get_cert_info(self, host, cert):
|
||||||
"""Get all the information about cert and create a JSON file."""
|
"""Get all the information about cert and create a JSON file."""
|
||||||
context = {}
|
context = {}
|
||||||
|
|
||||||
@ -121,7 +123,7 @@ def get_cert_info(host, cert):
|
|||||||
context['cert_sha1'] = cert.digest('sha1').decode()
|
context['cert_sha1'] = cert.digest('sha1').decode()
|
||||||
context['cert_alg'] = cert.get_signature_algorithm().decode()
|
context['cert_alg'] = cert.get_signature_algorithm().decode()
|
||||||
context['cert_ver'] = cert.get_version()
|
context['cert_ver'] = cert.get_version()
|
||||||
context['cert_sans'] = get_cert_sans(cert)
|
context['cert_sans'] = self.get_cert_sans(cert)
|
||||||
context['cert_exp'] = cert.has_expired()
|
context['cert_exp'] = cert.has_expired()
|
||||||
|
|
||||||
# Valid from
|
# Valid from
|
||||||
@ -144,7 +146,7 @@ def get_cert_info(host, cert):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
def print_status(host, context, analyze=False):
|
def print_status(self, host, context, analyze=False):
|
||||||
"""Print all the usefull info about host."""
|
"""Print all the usefull info about host."""
|
||||||
days_left = (datetime.strptime(context[host]['valid_till'], '%Y-%m-%d') - datetime.now()).days
|
days_left = (datetime.strptime(context[host]['valid_till'], '%Y-%m-%d') - datetime.now()).days
|
||||||
|
|
||||||
@ -178,7 +180,7 @@ def print_status(host, context, analyze=False):
|
|||||||
print('\n')
|
print('\n')
|
||||||
|
|
||||||
|
|
||||||
def show_result(user_args):
|
def show_result(self, user_args):
|
||||||
"""Get the context."""
|
"""Get the context."""
|
||||||
context = {}
|
context = {}
|
||||||
failed_cnt = 0
|
failed_cnt = 0
|
||||||
@ -186,29 +188,29 @@ def show_result(user_args):
|
|||||||
hosts = user_args.hosts
|
hosts = user_args.hosts
|
||||||
|
|
||||||
if not user_args.json_true:
|
if not user_args.json_true:
|
||||||
border_msg(' Analyzing {} host(s) '.format(len(hosts)))
|
self.border_msg(' Analyzing {} host(s) '.format(len(hosts)))
|
||||||
|
|
||||||
if not user_args.json_true and user_args.analyze:
|
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))
|
print('{}Warning: -a/--analyze is enabled. It takes more time...{}\n'.format(Clr.YELLOW, Clr.RST))
|
||||||
|
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
host, port = filter_hostname(host)
|
host, port = self.filter_hostname(host)
|
||||||
|
|
||||||
# Check duplication
|
# Check duplication
|
||||||
if host in context.keys():
|
if host in context.keys():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cert = get_cert(host, port, user_args)
|
cert = self.get_cert(host, port, user_args)
|
||||||
context[host] = get_cert_info(host, cert)
|
context[host] = self.get_cert_info(host, cert)
|
||||||
context[host]['tcp_port'] = int(port)
|
context[host]['tcp_port'] = int(port)
|
||||||
|
|
||||||
# Analyze the certificate if enabled
|
# Analyze the certificate if enabled
|
||||||
if user_args.analyze:
|
if user_args.analyze:
|
||||||
context = analyze_ssl(host, context)
|
context = self.analyze_ssl(host, context)
|
||||||
|
|
||||||
if not user_args.json_true:
|
if not user_args.json_true:
|
||||||
print_status(host, context, user_args.analyze)
|
self.print_status(host, context, user_args.analyze)
|
||||||
except SSL.SysCallError:
|
except SSL.SysCallError:
|
||||||
if not user_args.json_true:
|
if not user_args.json_true:
|
||||||
print('\t{}[-]{} {:<20s} Failed: Misconfigured SSL/TLS\n'.format(Clr.RED, Clr.RST, host))
|
print('\t{}[-]{} {:<20s} Failed: Misconfigured SSL/TLS\n'.format(Clr.RED, Clr.RST, host))
|
||||||
@ -222,12 +224,12 @@ def show_result(user_args):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not user_args.json_true:
|
if not user_args.json_true:
|
||||||
border_msg(' Successful: {} | Failed: {} | Duration: {} '.format(
|
self.border_msg(' Successful: {} | Failed: {} | Duration: {} '.format(
|
||||||
len(hosts) - failed_cnt, failed_cnt, datetime.now() - start_time))
|
len(hosts) - failed_cnt, failed_cnt, datetime.now() - start_time))
|
||||||
|
|
||||||
# CSV export if -c/--csv is specified
|
# CSV export if -c/--csv is specified
|
||||||
if user_args.csv_enabled:
|
if user_args.csv_enabled:
|
||||||
export_csv(context, user_args.csv_enabled)
|
self.export_csv(context, user_args.csv_enabled)
|
||||||
|
|
||||||
# Enable JSON output if -j/--json argument specified
|
# Enable JSON output if -j/--json argument specified
|
||||||
if user_args.json_true:
|
if user_args.json_true:
|
||||||
@ -239,7 +241,7 @@ def show_result(user_args):
|
|||||||
fp.write(json.dumps(context[host]))
|
fp.write(json.dumps(context[host]))
|
||||||
|
|
||||||
|
|
||||||
def export_csv(context, filename):
|
def export_csv(self, context, filename):
|
||||||
"""Export all context results to CSV file."""
|
"""Export all context results to CSV file."""
|
||||||
# prepend dict keys to write column headers
|
# prepend dict keys to write column headers
|
||||||
with open(filename, 'w') as csv_file:
|
with open(filename, 'w') as csv_file:
|
||||||
@ -249,7 +251,7 @@ def export_csv(context, filename):
|
|||||||
csv_writer.writerow(context[host])
|
csv_writer.writerow(context[host])
|
||||||
|
|
||||||
|
|
||||||
def filter_hostname(host):
|
def filter_hostname(self, host):
|
||||||
"""Remove unused characters and split by address and port."""
|
"""Remove unused characters and split by address and port."""
|
||||||
host = host.replace('http://', '').replace('https://', '').replace('/', '')
|
host = host.replace('http://', '').replace('https://', '').replace('/', '')
|
||||||
port = 443
|
port = 443
|
||||||
@ -259,7 +261,7 @@ def filter_hostname(host):
|
|||||||
return host, port
|
return host, port
|
||||||
|
|
||||||
|
|
||||||
def get_args():
|
def get_args(self):
|
||||||
"""Set argparse options."""
|
"""Set argparse options."""
|
||||||
parser = ArgumentParser(prog='ssl_checker.py', add_help=False,
|
parser = ArgumentParser(prog='ssl_checker.py', add_help=False,
|
||||||
description="""Collects useful information about given host's SSL certificates.""")
|
description="""Collects useful information about given host's SSL certificates.""")
|
||||||
@ -303,6 +305,6 @@ def get_args():
|
|||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
show_result(get_args())
|
SSLCheckerObject = SSLChecker()
|
||||||
|
SSLCheckerObject.show_result(SSLCheckerObject.get_args())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user