예제 #1
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None



        issuer_common_name = deep_get(data,
                                      'data.tls.result.handshake_log.server_certificates.certificate.parsed.issuer.common_name')
        if issuer_common_name:
            issuer_common_name = issuer_common_name[0]
        else:
            return False, None
        subject_common_name = deep_get(data,
                                       'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.common_name')
        if subject_common_name:
            subject_common_name = subject_common_name[0]
        else:
            return False, None

        upper = False
        lower = False
        prefix_length = 0
        dot = False
        banned = False
        incorrect = False
        for i in range(len(subject_common_name)):
            if subject_common_name[i] == '.':
                if dot:
                    incorrect = True
                dot = True
                prefix_length = i
            elif subject_common_name[i].isupper() and not dot:
                upper = True
            elif subject_common_name[i].islower() and not dot:
                lower = True
            elif subject_common_name[i] == '-':
                banned = True
        correct_pattern = upper and lower and dot and prefix_length == 10 and not banned and not incorrect

        validity = deep_get(data,
                            'data.tls.result.handshake_log.server_certificates.certificate.parsed.validity.length')
        key_length = deep_get(data,
                              'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject_key_info.rsa_public_key.length')

        if correct_pattern \
                and issuer_common_name == subject_common_name \
                and int(validity) == 31536000 \
                and int(key_length) == 2048:

            allowed_hashes = {
                "108d4ee4b9f3cd5c0efba8af2dab5009",
            }

            if CSHash(cert) in allowed_hashes:
                return True, "cluster-3"

        return False, None
예제 #2
0
async def scan(producer):
    while True:  # Continuously run new full IPv4 range scans
        logging.info('New scan started')
        proc = subprocess.Popen(
            "zmap -q --log-file=zmap.log -r 10000 --blacklist-file=config/blacklist.conf --sender-threads=1 --cores=0 -p 443 -n 100% -o - | ztee hosts.txt | ./bin/zgrab2 tls -o - --gomaxprocs=1 --senders=1000",
            shell=True,
            stdout=subprocess.PIPE)

        while True:  # Continuously poll new certificates from scan
            raw = proc.stdout.readline()
            if raw == b'' and proc.poll() is not None:
                break
            if raw:  # Handle new output line from zgrab
                date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                try:
                    data = json.loads(raw)
                    sha1 = deep_get(
                        data,
                        'data.tls.result.handshake_log.server_certificates.certificate.parsed.fingerprint_sha1',
                        None)
                    if sha1:  # Send certificate and metadata to Kafka
                        body = {"date": date, "data": data, "sha1": sha1}
                        producer.produce("scan", body)
                except Exception as e:
                    logging.error(e)
                    continue

        logging.info('Scan ended')
        time.sleep(600)
예제 #3
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None
        validity = deep_get(data,
                            'data.tls.result.handshake_log.server_certificates.certificate.parsed.validity.length')
        issuer_dn = deep_get(data, 'data.tls.result.handshake_log.server_certificates.certificate.parsed.issuer_dn')

        if issuer_dn == "C=XX, L=Default City, O=Default Company Ltd" and int(validity) == 172800000:
            allowed_hashes = {
                "d29c030a2687b4e3364811e73700c523",
            }

            if CSHash(cert) in allowed_hashes:
                return True, "cluster-1"

        return False, None
예제 #4
0
    async def __analyze(self):
        try:
            while True:
                msg = self.consumer.poll(timeout=1.0)
                if msg is None:
                    continue
                if msg.error():
                    raise confluent_kafka.KafkaException(msg.error())
                else:
                    topic = msg.topic()
                    message = json.loads(msg.value())
                    data = message['data']
                    date = message['date']
                    sha1 = message['sha1']
                    cert = deep_get(data,
                                    'data.tls.result.handshake_log.server_certificates.certificate.raw',
                                    "")

                    for module in self.modules:
                        match, comment = module.analyze(topic, data, cert)
                        if match:
                            body = {
                                "date": date,
                                "sha1": sha1,
                                "tag": module.tag,
                                "comment": comment,
                            }
                            logging.info("Found match :")
                            logging.info(str(body))
                            self.producer.produce("tags", body)
        except Exception as e:
            logging.error(e)
        finally:
            self.consumer.close()
예제 #5
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None


        CN = deep_get(data, 'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.common_name')
        C = deep_get(data,
                      'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.country')

        if CN is None and C and C[0] == "US":
            allowed_hashes = {
                "23468ff8bd0e196cdc4fcff56cf8eb7e",
            }
            if CSHash(cert) in allowed_hashes:
                return True, "Powershell Empire C2" # or APfell actually

        return False, None
예제 #6
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None


        CN = deep_get(data, 'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.common_name')
        OU = deep_get(data,
                      'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.organizational_unit')
        EMAIL = deep_get(data,
                      'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.email_address')

        if (CN and OU and EMAIL and EMAIL[0] == OU[0] + "@" + CN[0]):
            allowed_hashes = {
                "b432fd10cb96cd7c0d6d07d8ad2afd73",
            }
            if CSHash(cert) in allowed_hashes:
                return True, "Metasploit C2"

        return False, None
예제 #7
0
    def analyze(self, topic, data, cert):
        if topic == "scan":
            subject_common_name = deep_get(data,'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.common_name', "")
            if subject_common_name:
                subject_common_name = subject_common_name[0]
            else:
                return False, None
        elif topic == "ct":
            subject_common_name = deep_get(data,
                                           'leaf_cert.subject.CN',
                                           "")
        else:
            subject_common_name = ""

        suffixes = ['.ddns.net', '.spdns.org', '.duckdns.org', '.myddns.com']
        for suffix in suffixes:
            length = len(subject_common_name)
            if len(suffix) < length and subject_common_name[length - len(suffix):] == suffix:
                return True, "cluster-1"

        return False, None
예제 #8
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None


        C = deep_get(data, 'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.country')
        L = deep_get(data, 'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.locality')
        ST = deep_get(data, 'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.province')
        O = deep_get(data,
                     'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.organization')
        OU = deep_get(data,
                      'data.tls.result.handshake_log.server_certificates.certificate.parsed.subject.organizational_unit')

        if (C and C[0]=='') or (L and L[0] == '') or (ST and ST[0] == '') or (O and O[0] == '') or (OU and OU[0] == ''):
            allowed_hashes = {
                "4f8c042aa2987ce4d06797a84b2f832d",
            }
            if CSHash(cert) in allowed_hashes:
                serial = deep_get(data,
                                  'data.tls.result.handshake_log.server_certificates.certificate.parsed.serial_number')
                if int(serial) == 146473198:
                    return True, "CobaltStrike Default Certificate"
                else:
                    return True, "CobaltStrike C2"

        return False, None
예제 #9
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None

        issuer_dn = deep_get(data,'data.tls.result.handshake_log.server_certificates.certificate.parsed.issuer_dn')

        if issuer_dn == "C=XX, ST=1, L=1, O=1, OU=1, CN=*":
            allowed_hashes = {
                "b00e2855520f59644754e8bfa6dc1821",
            }
            if CSHash(cert) in allowed_hashes:
                return True, "cluster-1"
        return False, None
예제 #10
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None

        issuer_dn = deep_get(data,'data.tls.result.handshake_log.server_certificates.certificate.parsed.issuer_dn')

        if issuer_dn == "CN=localhost, C=AU, ST=Some-State, O=Internet Widgits Pty Ltd":
            allowed_hashes = {
                "3fbc3c90292240b7a5e5ff9a7130d59c",
            }

            if CSHash(cert) in allowed_hashes:
                return True, "cluster-4"
        return False, None
예제 #11
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None

        issuer_dn = deep_get(data,'data.tls.result.handshake_log.server_certificates.certificate.parsed.issuer_dn')

        if issuer_dn == "C=GB, ST=London, L=London, O=Global Security, OU=IT Department, CN=example.com":
            allowed_hashes = {
                "b00e2855520f59644754e8bfa6dc1821",
                "612c9021db95bd4323cbcd3d00fedca7",
            }

            if CSHash(cert) in allowed_hashes:
                return True, "cluster-1"

        return False, None
예제 #12
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None

        validity = deep_get(data,
                            'data.tls.result.handshake_log.server_certificates.certificate.parsed.validity.length', "0")


        if  int(validity) == 315446400:
            allowed_hashes = {
                "1ce2b13bea04aaccc85e2725f8d1e7f4",
            }
            if CSHash(cert) in allowed_hashes:
                return True, "Covenant c2"

        return False, None
예제 #13
0
    def analyze(self, topic, data, cert):
        if topic != "scan":
            return False, None

        issuer_dn = deep_get(data,'data.tls.result.handshake_log.server_certificates.certificate.parsed.issuer_dn')

        if issuer_dn == "O=FASTVPS, CN=parking":
            allowed_hashes = {
                "0a8940ab07f7dbfabc238c80edb05426",
            }


            if CSHash(cert) in allowed_hashes:
                return True, "cluster-1"

        return False, None
예제 #14
0
def main(bootstrap_servers, host, port, user, password):
    consumerConfiguration = {
        'bootstrap.servers': bootstrap_servers,
        'group.id': "elasticsearch",
        'session.timeout.ms': 30000,
        'auto.offset.reset': 'earliest'
    }
    consumer = confluent_kafka.Consumer(consumerConfiguration)
    consumer.subscribe(["scan", "ct", "tags"])

    # Elasticsearch configuration
    es = Elasticsearch([{
        'host': host,
        'port': port
    }],
                       http_auth=(user, password),
                       timeout=60)

    actions = []
    try:
        while True:
            msg = consumer.poll(timeout=1.0)
            if msg is None:  # no message received yet
                continue
            if msg.error():
                raise confluent_kafka.KafkaException(msg.error())
            else:
                topic = msg.topic()
                if topic == "scan":
                    message = json.loads(msg.value())
                    data = message['data']
                    date = message['date']
                    sha1 = message['sha1']

                    raw = deep_get(
                        data,
                        'data.tls.result.handshake_log.server_certificates.certificate.raw',
                        "")

                    tls_version = deep_get(
                        data,
                        'data.tls.result.handshake_log.server_hello.version.value',
                        "")

                    tls_cipher_suite = deep_get(
                        data,
                        'data.tls.result.handshake_log.server_hello.cipher_suite.hex',
                        "")

                    actions.append({
                        "_index": "certificates",
                        "_id": sha1,
                        "date": date,
                        "sha1": sha1,
                        "raw": raw,
                        "scan": True,
                    })

                    ip = deep_get(data, 'ip', "")
                    md5 = deep_get(
                        data,
                        'data.tls.result.handshake_log.server_certificates.certificate.parsed.fingerprint_md5',
                        "")
                    sha256 = deep_get(
                        data,
                        'data.tls.result.handshake_log.server_certificates.certificate.parsed.fingerprint_sha256',
                        "")

                    actions.append({
                        "_index": "hosts_{date}".format(date=date),
                        "ip": ip,
                        "date": date,
                        "md5": md5,
                        "sha1": sha1,
                        "sha256": sha256,
                        "tls_version": tls_version,
                        "tls_cipher_suite": tls_cipher_suite,
                    })

                elif topic == "ct":
                    message = json.loads(msg.value())
                    data = message['data']
                    date = message['date']
                    sha1 = message['sha1']

                    try:
                        issuer_common_name = data["chain"][0]["subject"]["CN"]
                    except KeyError or IndexError:
                        issuer_common_name = ""

                    subject_common_name = deep_get(data,
                                                   'leaf_cert.subject.CN', "")
                    raw = deep_get(data, 'leaf_cert.as_der', "")

                    actions.append({
                        "_index": "certificates",
                        "_id": sha1,
                        "date": date,
                        "sha1": sha1,
                        "raw": raw,
                        "ct": True,
                    })

                elif msg.topic() == "tags":
                    message = json.loads(msg.value())
                    date = message['date']
                    sha1 = message['sha1']
                    tag = message['tag']
                    comment = message['comment']
                    actions.append({
                        "_index": "tags",
                        "date": date,
                        "sha1": sha1,
                        "tag": tag,
                        "comment": comment,
                    })
                if len(actions) > 1000:
                    bulk(es, iter(actions))
                    actions = []

    except KeyboardInterrupt:
        sys.stderr.write('Aborted by user\n')

    finally:
        consumer.close()