Пример #1
0
def pyopenssl_check_hostname(cert, hostname):
    ''' Return True if valid. False is invalid '''
    general_names = SubjectAltName()
    if cert.get_subject().commonName:
        for idx in range(0, cert.get_extension_count()):
            ext = cert.get_extension(idx)
            if ext.get_short_name() == "subjectAltName":
                san = ext.get_data()
                decoded_san = der_decoder.decode(san, asn1Spec=general_names)

                for name in decoded_san:
                    if isinstance(name, SubjectAltName):
                        for entry in range(len(name)):
                            component = name.getComponentByPosition(entry)
                            val = str(component.getComponent())
                            if component.getName(
                            ) == 'dNSName' and val.startswith('*'):
                                # Wilcard
                                if val[2:] == hostname.split('.', 1)[1]:
                                    #                                    print 'OK - wilcard'
                                    return True
                            # Normal hostnames
                            elif component.getName(
                            ) == 'dNSName' and val == hostname:
                                #                                print 'OK - normal'
                                return True
    else:
        return False
Пример #2
0
def get_subj_alt_name(peer_cert):
    # Search through extensions
    dns_name = []
    if not SUBJ_ALT_NAME_SUPPORT:
        return dns_name

    general_names = SubjectAltName()
    for i in range(peer_cert.get_extension_count()):
        ext = peer_cert.get_extension(i)
        ext_name = ext.get_short_name()
        if ext_name != 'subjectAltName':
            continue

        # PyOpenSSL returns extension data in ASN.1 encoded form
        ext_dat = ext.get_data()
        decoded_dat = der_decoder.decode(ext_dat, asn1Spec=general_names)

        for name in decoded_dat:
            if not isinstance(name, SubjectAltName):
                continue
            for entry in range(len(name)):
                component = name.getComponentByPosition(entry)
                if component.getName() != 'dNSName':
                    continue
                dns_name.append(str(component.getComponent()))

    return dns_name
Пример #3
0
 def _get_subj_alt_name(cls, peer_cert):
     '''Extract subjectAltName DNS name settings from certificate extensions
     
     @param peer_cert: peer certificate in SSL connection.  subjectAltName
     settings if any will be extracted from this
     @type peer_cert: OpenSSL.crypto.X509
     '''
     # Search through extensions
     dns_name = []
     general_names = SubjectAltName()
     for i in range(peer_cert.get_extension_count()):
         ext = peer_cert.get_extension(i)
         ext_name = ext.get_short_name()
         if ext_name == cls.SUBJ_ALT_NAME_EXT_NAME:
             # PyOpenSSL returns extension data in ASN.1 encoded form
             ext_dat = ext.get_data()
             decoded_dat = der_decoder.decode(ext_dat, 
                                              asn1Spec=general_names)
             
             for name in decoded_dat:
                 if isinstance(name, SubjectAltName):
                     for entry in range(len(name)):
                         component = name.getComponentByPosition(entry)
                         dns_name.append(str(component.getComponent()))
                         
     return dns_name
Пример #4
0
def get_san(hostname, port, debug=False):
    """Gets Subject Alternative Names from requested host.
    Thanks to Cato- for this piece of code:
    https://gist.github.com/cato-/6551668"""

    subdomains = []
    general_names = SubjectAltName()

    # Tries to connect to server, exits on error unless Traceback is requested
    try:
        cert = ssl.get_server_certificate((args.hostname, args.port))
    except Exception as e:
        err = colored('FATAL: Could not connect to server.', 'white', 'on_red')
        print(err, end='\n')
        if debug:
            raise e
        exit(1)

    # requesting certificate
    x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)

    # get all extensions from certificate and iterate until we find a SAN entry
    for extension_id in range(0, x509.get_extension_count()):
        ext = x509.get_extension(extension_id)

        # decode the shortname to UTF-8 to be able to compare strings
        ext_name = ext.get_short_name().decode('utf-8')
        if ext_name == 'subjectAltName':

            # get_data() returns a heavily coded byte string
            ext_data = ext.get_data()
            decoded_dat = decoder.decode(ext_data, asn1Spec=general_names)

            # decoding SANS with magic sauce, please explain this to me.
            for name in decoded_dat:
                if isinstance(name, SubjectAltName):
                    for entry in range(len(name)):
                        component = name.getComponentByPosition(entry)
                        subdomains.append(str(component.getComponent()))

    # merge list results from crt.sh if found.
    if args.search_crt:
        crt_subdomains = search_crt(hostname)
        if crt_subdomains is not False:
            subdomains = list(subdomains) + list(crt_subdomains)

    # return a unique set of subdomains without wildcards
    filtered_domains = clean_san_list(subdomains, args.matching_domain)
    return set(sorted(filtered_domains))
Пример #5
0
def get_subj_alt_name(peer_cert):
    dns_name = []
    general_names = SubjectAltName()
    for i in range(peer_cert.get_extension_count()):
        ext = peer_cert.get_extension(i)
        ext_name = ext.get_short_name()
        if ext_name == "subjectAltName":
            ext_dat = ext.get_data()
            decoded_dat = der_decoder.decode(ext_dat, asn1Spec=general_names)

            for name in decoded_dat:
                if isinstance(name, SubjectAltName):
                    for entry in range(len(name)):
                        component = name.getComponentByPosition(entry)
                        dns_name.append(str(component.getComponent()))
    return dns_name
Пример #6
0
def subject_alt_name(target, port=443):
    general_names = SubjectAltName()
    try:
        cert = ssl.get_server_certificate((target, port))
    except:
        return
    x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
    for extension_id in range(0, x509.get_extension_count()):
        ext = x509.get_extension(extension_id)
        ext_name = ext.get_short_name().decode('utf-8')
        if ext_name == 'subjectAltName':
            ext_data = ext.get_data()
            decoded_dat = decoder.decode(ext_data, asn1Spec=general_names)
            for name in decoded_dat:
                if isinstance(name, SubjectAltName):
                    for entry in range(len(name)):
                        component = name.getComponentByPosition(entry)
                        if str(component.getComponent()) not in subdomains:
                            subdomains.append(str(component.getComponent()))
                            print("Sub-domain found from subject_alt_name: " +
                                  str(component.getComponent()))
Пример #7
0
    def getpeercert(self, binary_form=False):
        """
        :return: The remote peer certificate in a tuple
        """
        x509 = self.ssl_conn.get_peer_certificate()
        if not x509:
            raise ssl.SSLError('No peer certificate')

        if binary_form:
            return OpenSSL.crypto.dump_certificate(
                OpenSSL.crypto.FILETYPE_ASN1, x509)

        dns_name = []
        general_names = SubjectAltName()

        for i in xrange(x509.get_extension_count()):
            ext = x509.get_extension(i)
            ext_name = ext.get_short_name()

            if ext_name != 'subjectAltName':
                continue

            ext_dat = ext.get_data()
            decoded_dat = der_decoder(ext_dat, asn1Spec=general_names)

            for name in decoded_dat:
                if not isinstance(name, SubjectAltName):
                    continue
                for entry in xrange(len(name)):
                    component = name.getComponentByPosition(entry)
                    if component.getName() != 'dNSName':
                        continue
                    dns_name.append(('DNS', str(component.getComponent())))

        return {
            'subject': ((('commonName', x509.get_subject().CN), ), ),
            'subjectAltName': dns_name,
            'notAfter': x509.get_notAfter()
        }
Пример #8
0
def get_subject_alternates(cert):
    """Get the subject alternates from a x509 object

    :param cert: x509 certificate object
    :returns: list of subject alternates residing on x509 object
    """

    general_names = SubjectAltName()
    subject_alternates = []

    for items in range(cert.get_extension_count()):
        ext = cert.get_extension(items)
        if ext.get_short_name() == 'subjectAltName':
            ext_dat = ext.get_data()
            decoded_dat = der_decoder.decode(ext_dat, asn1Spec=general_names)

            for name in decoded_dat:
                if isinstance(name, SubjectAltName):
                    for entry in range(len(name)):
                        component = name.getComponentByPosition(entry)
                        subject_alternates.append(str(
                            component.getComponent()))
    return subject_alternates
Пример #9
0
def getSubAltName(peer_cert):
    '''
    Performs inspection of the SSL cert

    :param peer_cert:  The cert to inspect
    :return: dns_name - list of names found
    '''
    dns_name = []
    general_names = SubjectAltName()

    for i in range(peer_cert.get_extension_count()):
        extension = peer_cert.get_extension(i)
        extension_name = extension.get_short_name()
        if extension_name == "subjectAltName":
            extension_data = extension.get_data()
            decoded_data = der_decoder.decode(extension_data, asn1Spec=general_names)

            for name in decoded_data:
                if isinstance(name, SubjectAltName):
                    for entry in range(len(name)):
                        component = name.getComponentByPosition(entry)
                        dns_name.append(str(component.getComponent()))
    return dns_name
Пример #10
0
def print_cert(cert, printraw=False):
    #Certain there are better toolsets for this, but parse cert
    #subject and break it into the DN components that are important
    #if this fails, just dump the raw subject data as returned by
    #openssl
    try:
        certobj = crypto.load_certificate(crypto.FILETYPE_ASN1, cert)
        if printraw:
            print crypto.dump_certificate(crypto.FILETYPE_PEM, certobj)

        subject = certobj.get_subject()
        print 'CN={},OU={},O={},L={},S={},C={}'.format(
            subject.commonName, subject.organizationalUnitName,
            subject.organizationName, subject.localityName,
            subject.stateOrProvinceName, subject.countryName)
        #Get contents of subjectAltName extension
        extct = certobj.get_extension_count()
        # Code copied blatently from https://gist.github.com/cato-/6551668/raw/9d0c4d5e1ba16b92c4f4a18e74e460c097676785/verify_cert.py
        # and ndg.httpsclient.ssl_peer_verification.ServerSSLCertVerification
        general_names = SubjectAltName()
        for i in range(extct):
            ext = certobj.get_extension(i)
            if ext.get_short_name() == 'subjectAltName':
                data = der_decoder.decode(ext.get_data(),
                                          asn1Spec=general_names)
                for names in data:
                    for entry in range(len(names)):
                        component = names.getComponentByPosition(entry)
                        print str(component.getComponent())
                bstr = io.BytesIO(ext.get_data())
                blen = len(bstr.read())
                bstr.seek(0)
                val = ''
        print subject.get_components()
    except:
        print "Unable to parse certificate subject"
Пример #11
0
def scan_site(hostnames, match_domain, output, crtsh, timeout, suppress):
    """Scan domains from input or a text file, format is HOST[:PORT].

    e.g: gsan scan domain1.com domain2.com:port

    You can also pass a text file instead, just replace the first domain argument
    for a file. eg: gsan scan filename.txt

    If no ports are defined, then gsan assumes the port 443 is available."""
    subdomains_data = []
    subjaltname = SubjectAltName()

    if isfile(hostnames[0]):
        with open(hostnames[0], "r") as host_file:
            hostnames = [host.rstrip("\n") for host in host_file]
        hostnames = [parse_host_port(host) for host in hostnames]
    else:
        hostnames = [parse_host_port(host) for host in hostnames]

    bad_hosts = []
    for hostname in hostnames:
        click.secho(f"[+] Getting subdomains for {hostname[0]}", bold=True)
        subdomains = []
        port = hostname[1] if hostname[1] else 443
        setdefaulttimeout(timeout)
        try:
            cert = ssl.get_server_certificate((hostname[0], port))
        except Exception:
            click.secho(f"[!] Unable to connect to host {hostname[0]}",
                        bold=True,
                        fg="red")
            bad_hosts.append(hostname[0])
            continue

        # Thanks to Cato- for this piece of code:
        # https://gist.github.com/cato-/6551668
        # get all extensions from certificate and iterate until we find a SAN entry
        x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                               cert)
        for extension_id in range(0, x509.get_extension_count()):
            ext = x509.get_extension(extension_id)
            ext_name = ext.get_short_name().decode("utf-8")
            if ext_name == "subjectAltName":
                ext_data = ext.get_data()
                decoded_dat = decoder.decode(ext_data, asn1Spec=subjaltname)
                for name in decoded_dat:
                    if isinstance(name, SubjectAltName):
                        for entry in range(len(name)):
                            component = name.getComponentByPosition(entry)
                            subdomains.append(str(component.getComponent()))
        subdomain_df = pd.Series(subdomains)

        if crtsh:
            crtsh_results = get_crtsh(hostname[0])
            if crtsh_results.empty:
                pass
            else:
                subdomain_df = pd.concat([subdomain_df, crtsh_results])

        if subdomains:
            subdomain_df = strip_chars(subdomain_df)
        if match_domain:
            subdomain_df = filter_domain(subdomain_df, hostname[0])
        subdomain_df = reindex_df(subdomain_df)
        subdomains_data.append(subdomain_df)

    column_names = [name[0] for name in hostnames]
    for name in bad_hosts:
        column_names.remove(name)
    try:
        concat_df = concat_dfs(subdomains_data, column_names)
    except ValueError:
        click.secho(f"[!] No subdomains where found", bold=True, fg="yellow")
    else:
        if not suppress:
            click.secho("[+] Results:", bold=True)
            print(concat_df.to_string())
            if output:
                dump_filename(output, concat_df)
        elif suppress and not output:
            filename = datetime.now().strftime(
                "subdomains-%Y-%m-%d-%H-%M-%S.csv")
            click.secho("[!] Suppress was active but no output was defined",
                        bold=True,
                        fg="yellow")
            click.secho(f"[!] Output was automatically generated",
                        bold=True,
                        fg="yellow")
            dump_filename(filename, concat_df)
        elif suppress and output:
            dump_filename(output, concat_df)