#!/usr/bin/python3 #-*- coding: utf-8 -*- # IMPORTATION import cgi import html import json import ssl import hashlib import dns.query import dns.message import socket import requests from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import Encoding from cryptography.hazmat.primitives.serialization import PublicFormat # MODULES def dnssec_validation(DOMAIN): qm = dns.message.make_query(DOMAIN, dns.rdatatype.A,want_dnssec=True) response = dns.query.udp(qm,"1.1.1.1") dnssec = dns.flags.to_text(response.flags) if "AD" in dnssec: return(True) else: return(False) def tlsa_validation(DOMAIN): def compute_hash(func, string): """compute hash of string using given hash function""" h = func() h.update(string) return h.hexdigest() qm = dns.message.make_query('_443._tcp.' + DOMAIN, dns.rdatatype.TLSA) response = dns.query.udp(qm,"1.1.1.1") if len(response.answer) is 0: return(False) else: tlsaanswer = str(response.answer[-1]) tlsalist = tlsaanswer.split() if len(tlsalist) < 7: return(False) selector = str(tlsalist[5]) mtype = str(tlsalist[6]) hexdata1 = str(tlsalist[7]) try: conn = ssl.create_connection((DOMAIN , 443)) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) sock = context.wrap_socket(conn, server_hostname=DOMAIN) dercert = sock.getpeercert(True) pemcert = ssl.DER_cert_to_PEM_cert(dercert) cert = pemcert.encode('ascii') except: return(False) if selector == "0": certdata = dercert elif selector == "1": cert = x509.load_pem_x509_certificate(cert, default_backend()) certdata = cert.public_key().public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo) else: raise ValueError("selector type %d not recognized" % selector) if mtype == "0": hexdata2 = hexdump(certdata) elif mtype == "1": hexdata2 = compute_hash(hashlib.sha256, certdata) elif mtype == "2": hexdata2 = compute_hash(hashlib.sha512, certdata) else: raise ValueError("matchtype %d not recognized" % matchtype) if hexdata1 == hexdata2: return True else: return False def headers_validation(DOMAIN): url = "https://" + DOMAIN + "/" try: r = requests.get(url) headers = r.headers except: return("NO HTTPS") if "public-key-pins" in str(headers).lower(): RESULT="HPKP_TRUE" else: RESULT="HPKP _FALSE" if "strict-transport-security" in str(headers).lower(): RESULT = RESULT + " HSTS_TRUE" else: RESULT = RESULT + " HSTS_FALSE" return(RESULT) # MAIN print("Content-Type: application/json") print("") fs = cgi.FieldStorage() JSON_RESULT= '{"DNSSEC": false,"DANE": false,"HSTS": false,"HPKP": false}' JSON_DATA = json.loads(JSON_RESULT) if "domain" not in fs: print("{ERROR}") cgi.sys.exit(0) domain = html.escape(fs["domain"].value) if dnssec_validation(domain) is True: JSON_DATA["DNSSEC"] = True if tlsa_validation(domain) is True: JSON_DATA["DANE"] = True headers = headers_validation(domain) if "HSTS_TRUE" in headers: JSON_DATA["HSTS"] = True if "HPKP_TRUE" in headers: JSON_DATA["HPKP"] = True JSON_RESULT = json.dumps(JSON_DATA) print(JSON_RESULT)