How do I actually verify a given url’s SSL certificate?

I am writing a piece of code to verify that a given URL’s SSL certificate is valid, however, the requests library does not seem to be working correctly. Here is the code:

import requests
    try:
        response = str(requests.get(url, verify=True, allow_redirects=True))
        print(response)
        if "SSL: CERTIFICATE_VERIFY_FAILED" in response:
            print("url "" + url + "" has an invalid SSL certificate")
        else:
            valid = True
            for command in commands:
                if command.title == "get info":
                    if command.expirationDate > datetime.date:
                        print("url has an expired SSL certificate.")
                        valid = False
            if valid:
                print("url "" + url + "" has a valid SSL certificate")
    except requests.exceptions.InvalidURL:
        print("Invalid url "" + url + """)
    except requests.exceptions.MissingSchema:
        print("Invalid url "" + url + """)
    except (socket.gaierror, urllib3.exceptions.NewConnectionError, urllib3.exceptions.MaxRetryError, requests.exceptions.ConnectionError):
        print("Could not resolve url "" + url + "" to host")

Putting in the URL “https://expired.badssl.com/ returns Could not resolve url "https://expired.badssl.com/" to host However, I can in fact navigate to this page. Furthermore, pages without a valid certificate are showing as valid. One of my friends ran this exact code on his beef-xss server, and the output was that it had a valid certificate. I’ve looked at many tutorials which say the same thing, however, I must be missing something given how nothing I have tried is working.

Answer

Your problems seems to be that your IF statement is not evaluated because requests already throws the exception when the SSL verification fails.

You will probably need to handle that with a dedicated try-except block, something like:

import requests

def has_valid_ssl_req(url):
    try:
        response = str(requests.get(url, verify=True, allow_redirects=True))
        print(response)
        print(url+" has valid SSL, response: "+response)

    except Exception as e:
        print(url+": has INVALID SSL, error:"+str(e))

has_valid_ssl_req('http://expired.badssl.com')
has_valid_ssl_req('http://google.com')

Based on: How can i get Certificate issuer information in python? I would probably use SSL directly

import socket
import ssl

def has_valid_ssl(url):
    try:
        ctx = ssl.create_default_context()
        with ctx.wrap_socket(socket.socket(), server_hostname=url) as s:
            s.connect((url, 443))

        print(url+" has valid SSL")

    except Exception as e:
        print(url+": has INVALID SSL, error:"+str(e))

has_valid_ssl('expired.badssl.com')
has_valid_ssl('google.com')