-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcertificate_chain_extractor.py
144 lines (90 loc) · 3.3 KB
/
certificate_chain_extractor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 26 13:40:21 2020
@author: dsikerid
"""
import cert_human
from OpenSSL import SSL
import socket
from urllib.parse import urlparse
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options
import os
def get_certificate_chain(host):
"""
Extracts the certificate chain from the provided host.
params:
host (str): hostname
output:
-list of certificates in the chain (excluding root)
-in case of exception (eg. timeout) returns -1
"""
try:
with cert_human.ssl_socket(host) as sock:
# cert = sock.get_peer_certificate()
cert_chain = sock.get_peer_cert_chain()
return cert_chain
except:
try:
dst = (host, 443)
ctx = SSL.Context(SSL.SSLv23_METHOD)
sock = socket.create_connection(dst)
s = SSL.Connection(ctx, sock)
s.set_connect_state()
s.set_tlsext_host_name(dst[0].encode())
s.sendall('HEAD / HTTP/1.0\n\n')
s.recv(16)
cert_chain = s.get_peer_cert_chain()
return cert_chain
except:
return -1
def explore_web_address(WebAddress):
"""
Uses selenium-wire:https://pypi.org/project/selenium-wire/#openssl
Extracts the underlying requests made by the browser for a specific url.
params:
WebAddress (str): url
outputs:
requested_urls: urls of the requested content
unique_hostnames: unique hostnames of the requested_urls
"""
options = Options()
options.headless = True
options.add_argument("--window-size=1920,1200")
# Create a new instance of the Chrome driver
path_to_chromedriver=os.getcwd()+'\\chromedriver.exe'
driver = webdriver.Chrome(options=options, executable_path=path_to_chromedriver)
# driver = webdriver.Chrome(options=options, executable_path=r"C:/Users/dsikerid/Desktop/chromedriver.exe")
# Go to the page
driver.get(WebAddress)
requested_urls=[]
requested_hostnames=[]
# Access requests via the `requests` attribute
for request in driver.requests:
if request.response:
requested_urls.append(request.url)
url=urlparse(request.url)
if url.scheme=='https':
requested_hostnames.append(url.hostname)
unique=set(requested_hostnames)
unique_hostnames=list(unique)
return requested_urls, unique_hostnames
def get_interm_cert_chains(WebAddress):
"""
Extracts certificate chains from all contents requests made when loading a page.
params:
WebAddress (str): url
outputs:
number of requested_urls: number of total connections initiated by the browser
chains: list of certificate chains per unique content request address
"""
main_host=urlparse(WebAddress)
requested_urls, unique_hostnames=explore_web_address(WebAddress)
if main_host.hostname not in unique_hostnames: unique_hostnames.insert(0,main_host.hostname)
chains = []
for host in unique_hostnames:
cert_chain=get_certificate_chain(host)
if cert_chain != -1:
temp = (host, cert_chain)
chains.append(temp)
return len(requested_urls), chains