Example #1
0
 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)
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
 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())
Example #5
0
    def _get_ocsp_response(self):
        if self.ocsp_url is not None:
            try:
                issuerCert, _ = decoder.decode(
                    self.issuer_cert, asn1Spec=rfc2459.Certificate())
                userCert, _ = decoder.decode(
                    self.user_cert, asn1Spec=rfc2459.Certificate())

            except:
                return

            ocspReq = self.make_ocsp_request(issuerCert, userCert)

            try:
                httpReq = urllib2.Request(
                    self.ocsp_url,
                    encoder.encode(ocspReq),
                    {'Content-Type': 'application/ocsp-request'}
                    )
                httpRsp = urllib2.urlopen(httpReq).read()
            except:
                return

# Process OCSP response

            ocspRsp, _ = decoder.decode(
                httpRsp, asn1Spec=rfc2560.OCSPResponse())
            responseStatus = ocspRsp.getComponentByName('responseStatus')
            responseBytes = ocspRsp.getComponentByName('responseBytes')
            if responseStatus == 0:
                try:
                    response = responseBytes.getComponentByName('response')
                except:
                    self.tbsResponseData = -1
                    return

                basicOCSPResponse, _ = decoder.decode(
                    response, asn1Spec=rfc2560.BasicOCSPResponse()
                    )

                self.tbsResponseData = basicOCSPResponse.getComponentByName(
                    'tbsResponseData')

            else:
                mes = "get status %d %s" % (
                    responseStatus, self._name)
                MITMNotification.notify(title="OCSP", message=mes)
Example #6
0
    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())
Example #7
0
 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())
Example #8
0
    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")
Example #9
0
    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")
Example #10
0
    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())
Example #11
0
 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)
Example #12
0
 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)
Example #13
0
    # This is to delete the pinning database each day to avoid that an evil
    # site perform MITM attacks over our connections That's why because in our
    # code we save the pinning each time that we visite a site. But if this
    # site is evil we are saving bad pinning so we have to delete the database
    # to ensure that evil site has been deleted. You can change the seconds
    # in the configuration file

    #scheduler.add_job(drop, 'interval', seconds=config.DB_TIME_REMOVE)
    #scheduler.start()

    # configure logger

    with open(os.path.expanduser(config.LOG_FILE)) as log:
        config_log = json.load(log)
    logging.config.dictConfig(config_log)

    # Configure type of notifications

    if sys.platform == "darwin":
        from notification.notification_osx import NotificationOSX
        MITMNotification.register(NotificationOSX())

    print '[+] Downloading SSL blacklist'
    proc = Process(target=init_ssl_blacklist, args=())
    proc.start()
    print '[+] Sniffing'

    s = Sniff()
    s.sniff()
Example #14
0
    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")
Example #15
0
    # This is to delete the pinning database each day to avoid that an evil
    # site perform MITM attacks over our connections That's why because in our
    # code we save the pinning each time that we visite a site. But if this
    # site is evil we are saving bad pinning so we have to delete the database
    # to ensure that evil site has been deleted. You can change the seconds
    # in the configuration file

    #scheduler.add_job(drop, 'interval', seconds=config.DB_TIME_REMOVE)
    #scheduler.start()

    # configure logger

    with open(os.path.expanduser(config.LOG_FILE)) as log:
        config_log = json.load(log)
    logging.config.dictConfig(config_log)

    # Configure type of notifications

    if sys.platform == "darwin":
        from notification.notification_osx import NotificationOSX
        MITMNotification.register(NotificationOSX())

    print '[+] Downloading SSL blacklist'
    proc = Process(target=init_ssl_blacklist, args=())
    proc.start()
    print '[+] Sniffing'

    s = Sniff()
    s.sniff()