wext-httpspluschecker_api/index.py

139 lines
3.7 KiB
Python

#!/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)