Disable SSL Certificate Validation in Python

I am writing a script that connects to a bunch of URLs via HTTPS, downloads their SSL certificate and retrieves the CN. Everything works, except when I come across a site with an invalid SSL certificate. I absolutely don't care if the certificate is valid or not. I just want CN, but Python stubbornly refuses to retrieve certificate information if the certificate is not verified. Is there any way around this deeply silly behavior? Oh, I use only the built-in socket and ssl libraries. I don’t want to use third-party libraries like M2Crypto or pyOpenSSL because I try to port the script as little as possible.

Here is the relevant code:

file = open("list.txt", "r") for x in file: server = socket.getaddrinfo(x.rstrip(), "443")[0][4][0] sslsocket = socket.socket() sslsocket.connect((server, 443)) sslsocket = ssl.wrap_socket(sslsocket, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt") certificate = sslsocket.getpeercert()` 
+6
source share
2 answers

ssl.get_server_certificate can do this:

 import ssl ssl.get_server_certificate(("www.sefaz.ce.gov.br",443)) 

I think the doc string function is more clear than the dyth python site:

 """Retrieve the certificate from the server at the specified address, and return it as a PEM-encoded string. If 'ca_certs' is specified, validate the server cert against it. If 'ssl_version' is specified, use it in the connection attempt.""" 

Thus, you can extract the common name from the binary DER certificate to search for the common identifier of the object:

 def get_commonname(host,port=443): oid='\x06\x03U\x04\x03' # Object Identifier 2.5.4.3 (COMMON NAME) pem=ssl.get_server_certificate((host,port)) der=ssl.PEM_cert_to_DER_cert(pem) i=der.find(oid) # find first common name (certificate authority) if i!=-1: i=der.find(oid,i+1) # skip and find second common name if i!=-1: begin=i+len(oid)+2 end=begin+ord(der[begin-1]) return der[begin:end] return None 
+6
source

Ok I cleaned up the olivecoder code to solve the problem, which assumes that there will always be three CNs (root, intermediate, server) in the certificate chain, and I will hide it. This is the last code that I will use.

 cert = ssl.get_server_certificate(("www.google.com", 443)) #Retrieve SSL server certificate cert = ssl.PEM_cert_to_DER_cert(cert) #Convert certificate to DER format begin = cert.rfind('\x06\x03\x55\x04\x03') + 7 #Find the last occurence of this byte string indicating the CN, add 7 bytes to startpoint to account for length of byte string and padding end = begin + ord(cert[begin - 1]) #Set endpoint to startpoint + the length of the CN print cert[begin:end] #Retrieve the CN from the DER encoded certificate 
+2
source

Source: https://habr.com/ru/post/923164/


All Articles