def on_ocsp_response(self, ocsp): sct = ocsp.check_certificate_transparency() if sct is not None: self.check_sct(sct) else: debug_logger.debug("\t[-] Certificate %s has not SCT" % self._ca_name)
def on_certificate(self, cert): name = cert.subject_common_name() issuer_name = cert.issuer_common_name() query = db.get(name) if query is None: debug_logger.debug( "\t[-] You have not pinned this certificate %s" % name) return try: spki = cert.hash_spki(deep=1, algorithm="sha256") spki = base64.b64encode(spki) except: logger.error("Getting spki of the intermediate CA %s" % name) return try: issuers = query["issuers"] for i in issuers[issuer_name]: if spki == i: debug_logger.debug("\t[+] pin correct %s " % name) return logger.info("\t[-] Pin does not match %s" % name) debug_logger.debug("\t[-] Pin does not match %s" % name) MITMNotification.notify( title="Pinning", message=cert.subject_common_name()) except: MITMNotification.notify( title="Pinning", message="Issuer different") debug_logger.debug("\t[-] issuer with different name %s" % name)
def on_certificate(self, cert): name = cert.ca_name() fingerprint = cert.hash() query = db.get(fingerprint) if query is None: debug_logger.debug( "\t[+] Certificate %s is safe against blacklist" % name) else: debug_logger.debug( "\t[-] Certificate %s matched with a malware site" % name) logger.info("\t[-] Certificate %s matched with a malware site" % name) MITMNotification.notify(title=self.name, message=cert.subject_common_name())
def on_certificate(self, cert): name = cert.subject_common_name() issuer_name = cert.issuer_common_name() query = db.get(name) if query is None: debug_logger.debug( "\t[-] You have not pinned this certificate %s" % name) return try: spki = cert.hash_spki(deep=1, algorithm="sha256") spki = base64.b64encode(spki) except: logger.error("Getting spki of the intermediate CA %s" % name) return try: issuers = query["issuers"] for i in issuers[issuer_name]: if spki == i: debug_logger.debug("\t[+] pin correct %s " % name) return logger.info("\t[-] Pin does not match %s" % name) debug_logger.debug("\t[-] Pin does not match %s" % name) MITMNotification.notify(title="Pinning", message=cert.subject_common_name()) except: MITMNotification.notify(title="Pinning", message="Issuer different") debug_logger.debug("\t[-] issuer with different name %s" % name)
def on_certificate(self, cert): address = cert.hash() + '.notary.icsi.berkeley.edu' name = cert.ca_name() try: result = resolver.query( address, rdtype=dns.rdatatype.TXT)[0].__str__().split() except: MITMNotification.notify(title="ICSI-NO Certificate", message=cert.subject_common_name()) debug_logger.debug("\t[-] Certificate %s isn't in icsi notary" % name) return validated = int(result[4].split('=')[1][0]) first_seen = int(result[1].split('=')[1]) last_seen = int(result[2].split('=')[1]) times_seen = int(result[3].split('=')[1]) if validated is not 1: debug_logger.debug("\t[-] Certificate {0}".format(name) + " is not safe through icsi notary") logger.info("\t[-] Certificate {0}".format(name) + "is not safe through icsi notary") MITMNotification.notify(title="ICSI-NO valid", message=cert.subject_common_name()) else: s = last_seen - first_seen + 1 if s - times_seen >= config.ICSI_MAXIMUM_INTERVAL: debug_logger.debug( "\t[-] Certificate {0}".format(name) + " is not enough secure acording with icsi notary") MITMNotification.notify(title='ICSI-NO famous', message=cert.subject_common_name()) else: debug_logger.debug( "\t[+] Certificate %s is secure through icsi notary" % name)
def on_certificate(self, cert): name = cert.ca_name() fingerprint = cert.hash() query = db.get(fingerprint) if query is None: debug_logger.debug( "\t[+] Certificate %s is safe against blacklist" % name ) else: debug_logger.debug( "\t[-] Certificate %s matched with a malware site" % name ) logger.info( "\t[-] Certificate %s matched with a malware site" % name ) MITMNotification.notify( title=self.name, message=cert.subject_common_name())
def check_sct(self, sct): sct = decoder.decode(sct)[0] sct = str(decoder.decode(str(sct))[0]) now = datetime.utcnow() seconds_from = (now - datetime(1970, 1, 1)).total_seconds() sct_list_des = DeserializeSCTList(sct) list_sct = sct_list_des.deserialize_sct_list() for i in list_sct: sct = DeserializeSCT(i).deserialize_sct() if seconds_from > sct.timestamp: debug_logger.debug( "\t[+] SCT valid found: Version" + " = {0}, LogID = {1}, utc = {2}".format(sct.version, sct.logID, time.ctime(sct.timestamp)) ) else: debug_logger.debug("\t[-] SCT not valid. Timestamp" + " in the future") MITMNotification.notify(title="CT", message="SCT in the future")
def check_sct(self, sct): sct = decoder.decode(sct)[0] sct = str(decoder.decode(str(sct))[0]) now = datetime.utcnow() seconds_from = (now - datetime(1970, 1, 1)).total_seconds() sct_list_des = DeserializeSCTList(sct) list_sct = sct_list_des.deserialize_sct_list() for i in list_sct: sct = DeserializeSCT(i).deserialize_sct() if seconds_from > sct.timestamp: debug_logger.debug( "\t[+] SCT valid found: Version" + " = {0}, LogID = {1}, utc = {2}".format( sct.version, sct.logID, time.ctime(sct.timestamp))) else: debug_logger.debug("\t[-] SCT not valid. Timestamp" + " in the future") MITMNotification.notify(title="CT", message="SCT in the future")
def dispatch_certificate(self): # Do everything related with certificate if self.certs is not None: # verify certificate try: chain = X509Chain(self.certs) except Exception: return if chain.length_chain() == 1: try: debug_logger.debug( '[-] Chain incomplete from %s' % chain.ca_name() ) logger.info( "The chain is incomplete %s" % chain.subject_common_name() ) except Exception: debug_logger.debug('[-] Chain incomplete') logger.info('[-] Chain incomplete') else: # TODO ask ocsp status when is only necessary ocsp = Ocsp(chain) debug_logger.debug('[+] Verifying certificate') for cls in handlers.store: handlers.store[cls](chain, ocsp) else: pass
def on_certificate(self, cert): hash_t = cert.hash_spki(algorithm="sha256") name = cert.subject_common_name() algorithm = cert.get_cert_nss().subject_public_key_info.algorithm algorithm = algorithm.id_str _id = algorithm + ' - ' + name exist = db.get(_id) if exist is None: # That means that the certificate is not in the db, it's the # first time it was seen db.set_hash(hash_t, _id) debug_logger.debug("\t[+] Certificate %s first seen" % name) else: # Exist so we have to ensure that it is correct correct = db.compare(_id, hash_t) if correct is False: before = db.get(_id) debug_logger.debug("\t[-] Certificate %s has changed" % name) logger.info( "\t[-] Certificate {0} has changed from".format(name) + " \n{0}--->{1}\n ".format(before["_id"], before["hash"]) + "to \n{0}--->{1}".format(algorithm, hash_t)) MITMNotification.notify(title=self.name, message=name) else: debug_logger.debug("\t[+] Certificate %s has not changed" % name)
def on_certificate(self, cert): address = cert.hash()+'.notary.icsi.berkeley.edu' name = cert.ca_name() try: result = resolver.query( address, rdtype=dns.rdatatype.TXT )[0].__str__().split() except: MITMNotification.notify( title="ICSI-NO Certificate", message=cert.subject_common_name()) debug_logger.debug( "\t[-] Certificate %s isn't in icsi notary" % name ) return validated = int(result[4].split('=')[1][0]) first_seen = int(result[1].split('=')[1]) last_seen = int(result[2].split('=')[1]) times_seen = int(result[3].split('=')[1]) if validated is not 1: debug_logger.debug( "\t[-] Certificate {0}".format(name) + " is not safe through icsi notary") logger.info( "\t[-] Certificate {0}".format(name) + "is not safe through icsi notary") MITMNotification.notify( title="ICSI-NO valid", message=cert.subject_common_name()) else: s = last_seen - first_seen + 1 if s - times_seen >= config.ICSI_MAXIMUM_INTERVAL: debug_logger.debug( "\t[-] Certificate {0}".format(name) + " is not enough secure acording with icsi notary") MITMNotification.notify( title='ICSI-NO famous', message=cert.subject_common_name()) else: debug_logger.debug( "\t[+] Certificate %s is secure through icsi notary" % name)
def on_certificate(self, cert): approved_usage = not intended_usage try: length = cert.length_chain() if length > 4: debug_logger.debug( "\t[-] Certificate chain large > 4." + "It's a weird situtation") MITMNotification.notify( title="chain large", message=cert.subject_common_name(), group="NSS" ) return cert_nss = cert.get_cert_nss() name = cert.ca_name() certdb = nssconfig.certdb approved_usage = cert_nss.verify_now( certdb, True, intended_usage, None) except NSPRError: cert.add_to_nssdb(cert_nss.issuer.common_name, deep=1) if length == 4: inter = cert.get_cert_nss(deep=1) cert.add_to_nssdb(inter.issuer.common_name, deep=2) try: approved_usage = cert_nss.verify_now( certdb, True, intended_usage, None) except NSPRError: pass cert.remove_from_nssdb(cert_nss.issuer.common_name) if length == 4: cert.remove_from_nssdb(inter.issuer.common_name) if approved_usage & intended_usage: debug_logger.debug( "\t[+] Certificate %s is safe using NSS library" % name) else: debug_logger.debug( "\t[-] Certificate %s is not safe using NSS library" % name) logger.info( "\t[-] Certificate %s is not safe using NSS library" % name) MITMNotification.notify( title="Chain of trust", message=cert.subject_common_name())
def on_certificate(self, cert): approved_usage = not intended_usage try: length = cert.length_chain() if length > 4: debug_logger.debug("\t[-] Certificate chain large > 4." + "It's a weird situtation") MITMNotification.notify(title="chain large", message=cert.subject_common_name(), group="NSS") return cert_nss = cert.get_cert_nss() name = cert.ca_name() certdb = nssconfig.certdb approved_usage = cert_nss.verify_now(certdb, True, intended_usage, None) except NSPRError: cert.add_to_nssdb(cert_nss.issuer.common_name, deep=1) if length == 4: inter = cert.get_cert_nss(deep=1) cert.add_to_nssdb(inter.issuer.common_name, deep=2) try: approved_usage = cert_nss.verify_now(certdb, True, intended_usage, None) except NSPRError: pass cert.remove_from_nssdb(cert_nss.issuer.common_name) if length == 4: cert.remove_from_nssdb(inter.issuer.common_name) if approved_usage & intended_usage: debug_logger.debug( "\t[+] Certificate %s is safe using NSS library" % name) else: debug_logger.debug( "\t[-] Certificate %s is not safe using NSS library" % name) logger.info("\t[-] Certificate %s is not safe using NSS library" % name) MITMNotification.notify(title="Chain of trust", message=cert.subject_common_name())
def dispatch_certificate(self): # Do everything related with certificate if self.certs is not None: # verify certificate try: chain = X509Chain(self.certs) except Exception: return if chain.length_chain() == 1: try: debug_logger.debug("[-] Chain incomplete from %s" % chain.ca_name()) logger.info("The chain is incomplete %s" % chain.subject_common_name()) except Exception: debug_logger.debug("[-] Chain incomplete") logger.info("[-] Chain incomplete") else: # TODO ask ocsp status when is only necessary ocsp = Ocsp(chain) debug_logger.debug("[+] Verifying certificate") for cls in handlers.store: handlers.store[cls](chain, ocsp) else: pass
def _check_thisUpdate(self, check_thisUpdate, name): if check_thisUpdate is True: debug_logger.debug( "\t[+] Certificate %s is not revoked" % name) elif check_thisUpdate is False: debug_logger.debug('\t[-] Awkward Situation %s' % name)
def on_certificate(self, cert): def verify(url): try: answer = dns.resolver.query('_443._tcp.' + url, 'TLSA') except: # print "Unexpected error:", sys.exc_info()[0] return -1 ( cert_usage, selector, match_type, associated_data ) = [str(ans) for ans in answer][0].split(' ') funct = [cert.der_data, cert.subject_public_key_info] hash_funct = [None, hashlib.sha256, hashlib.sha512] temp = hash_funct[int(match_type)] # depend on the match_type we need use different algorithms if cert_usage == '3' or cert_usage == '1': # depend on the selector file we use the whole certificate or # only the subjectPublicKeyInfo data = funct[int(selector)]() if temp is not None: m = temp(data) data = m.hexdigest() if data == associated_data: return True else: return False if cert_usage == '0' or cert_usage == '2': # We must check for each certificate in the chain that the # associated data is presented for cer in xrange(0, cert.length_chain()): data = funct[int(selector)](deep=cer) if temp is not None: m = temp(data) data = m.hexdigest() if data == associated_data: if cert_usage == '0': return True else: cert.add_to_nssdb( cert.subject_common_name(deep=cer), deep=cer) value = self.verify_chain(cert) cert.remove_from_nssdb( cert.subject_common_name(deep=cer) ) return value return False try: url = cert.subject_common_name() except IndexError: debug_logger.debug("\t[-] ERROR extracting subject_common_name") return result = False result = verify(url) if result is True: debug_logger.debug( "\t[+] Certificate %s has a valid TLSA record" % cert.ca_name() ) return if url[0:3] == "www": url = url.replace("www.", '') result = verify(url) if url[0] == '*': url = url.replace('*', 'www') result = verify(url) if result is True: debug_logger.debug( "\t[+] Certificate %s has a valid TLSA record" % cert.ca_name() ) return url = url.replace('www', '*') if url[0] == '*.': url = url.replace('*.', '') result = verify(url) if result is True: debug_logger.debug( "\t[+] Certificate %s has a valid TLSA record" % cert.ca_name() ) return if result == -1: debug_logger.debug( "\t[-] Certificate {0} does not implement DANE".format( cert.ca_name())) return debug_logger.debug( "\t[-] Certificate {0} has not a valid TLSA".format( cert.ca_name()))
def on_ocsp_response(self, ocsp): ( status, certId, thisUpdate, nextUpdate, issuerHashz ) = ocsp.get_response() serial = self._cert.serial_number() issuer = self._cert.der_data(1) try: issuer_der = decoder.decode( issuer, asn1Spec=rfc2459.Certificate())[0] except: debug_logger.debug("\t[-] ERROR parsing") return issuerTbsCert = issuer_der.getComponentByName('tbsCertificate') issuerSubjectPublicKey = issuerTbsCert.getComponentByName( 'subjectPublicKeyInfo').getComponentByName('subjectPublicKey') issuerKeyHash = hashlib.sha1( self.valueOnlyBitStringEncoder(issuerSubjectPublicKey) ).digest() name = self._cert.ca_name() if status is None: debug_logger.debug("\t[-] Certificate has not OCSP URI") return if status == 3: # It is own status code debug_logger.debug("\t[-] Not bytes in OCSP response") MITMNotification.notify( title="OCSP", message="No bytes in response") return if certId == serial and issuerHashz == issuerKeyHash: if status == 'revoked': debug_logger.debug("\t[-] Certificate %s revoked" % name) logger.info("\t[-] Certificate %s revoked" % name) MITMNotification.notify( title='OCSP', message=name) return utcnow = datetime.utcnow() try: date_thisUpdate = datetime( year=int(thisUpdate[0:4]), month=int(thisUpdate[4:6]), day=int(thisUpdate[6:8]), hour=int(thisUpdate[8:10]), minute=int(thisUpdate[10:12]), second=int(thisUpdate[12:14])) except: debug_logger.debug( "\t[-] This certificate although is NOT revoked does not" + "provide information in thisUpdate") return check_thisUpdate = utcnow > date_thisUpdate try: date_NextUpdate = datetime( year=int(nextUpdate[0:4]), month=int(nextUpdate[4:6]), day=int(nextUpdate[6:8]), hour=int(nextUpdate[8:10]), minute=int(nextUpdate[10:12]), second=int(nextUpdate[12:14])) check_NextUpdate = date_NextUpdate > utcnow if check_NextUpdate is True: self._check_thisUpdate(check_thisUpdate, name) else: debug_logger.debug( "\t[-] There will not be more revocation status" + "information about %s" % name) except: self._check_thisUpdate(check_thisUpdate, name) pass else: debug_logger.debug( "\t[-] Likely you have received a bad response from OCSP" + " responder of %s" % name) logger.info( "\t[-] Likely you have received a bad response from OCSP" + " responder of %s" % name) MITMNotification.notify( title='OCSP', message="OCSP bad response")