示例#1
0
    def test_threat_detection(self, mock_client):
        """Threat Intel - Test threat_detection method"""
        mock_client.return_value = MockDynamoDBClient()
        records = mock_normalized_records()
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        assert_equal(len(threat_intel.threat_detection(records)), 2)
示例#2
0
    def test_query_with_duplicated_value(self, mock_client):
        """Threat Intel - Test query value includes dumplicated value"""
        mock_client.return_value = MockDynamoDBClient()
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        test_values = ['1.1.1.2', 'EVIL.com', 'evil.com', 'abcdef0123456789']
        threat_intel._query(test_values)
示例#3
0
    def test_process_with_threat_intel_enabled(self, mock_client):
        """Rules Engine - Threat Intel is enabled when process method is called"""
        @rule(datatypes=['sourceAddress'], outputs=['s3:sample_bucket'])
        def match_ipaddress(_):  # pylint: disable=unused-variable
            """Testing dummy rule"""
            return True

        mock_client.return_value = MockDynamoDBClient()
        toggled_config = self.config
        toggled_config['global']['threat_intel']['enabled'] = True
        toggled_config['global']['threat_intel'][
            'dynamodb_table'] = 'test_table_name'

        new_rules_engine = RulesEngine(toggled_config)
        kinesis_data_items = [{
            'account': 123456,
            'region': '123456123456',
            'source': '1.1.1.2',
            'detail': {
                'eventName': 'ConsoleLogin',
                'sourceIPAddress': '1.1.1.2',
                'recipientAccountId': '654321'
            }
        }]

        for data in kinesis_data_items:
            kinesis_data = json.dumps(data)
            service, entity = 'kinesis', 'test_kinesis_stream'
            raw_record = make_kinesis_raw_record(entity, kinesis_data)
            payload = load_and_classify_payload(toggled_config, service,
                                                entity, raw_record)

            assert_equal(len(new_rules_engine.run(payload)[0]), 1)
示例#4
0
    def test_process_ioc_with_clienterror(self, mock_client):
        """Threat Intel - Test private method process_ioc"""
        mock_client.return_value = MockDynamoDBClient(exception=True)
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        ioc_collections = [StreamIoc(value='1.1.1.2', ioc_type='ip')]
        threat_intel._process_ioc(ioc_collections)
示例#5
0
    def test_query_with_empty_value(self, mock_client):
        """Threat Intel - Test query value includes empty value"""
        mock_client.return_value = MockDynamoDBClient()
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        test_values = ['1.1.1.2', '', 'evil.com', 'abcdef0123456789']
        result, _ = threat_intel._query(test_values)
        assert_equal(len(result), 3)
示例#6
0
    def test_query(self, mock_client):
        """Threat Intel - Test DynamoDB query method with batch_get_item"""
        mock_client.return_value = MockDynamoDBClient()
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        test_values = ['1.1.1.2', '2.2.2.2', 'evil.com', 'abcdef0123456789']
        result, unprocessed_keys = threat_intel._query(test_values)
        assert_equal(len(result), 2)
        assert_false(unprocessed_keys)
        assert_equal(result[0], {'ioc_value': '1.1.1.2', 'sub_type': 'mal_ip'})
        assert_equal(result[1], {'ioc_value': 'evil.com', 'sub_type': 'c2_domain'})
示例#7
0
    def test_process_ioc_with_clienterror(self, log_mock, mock_client):
        """Threat Intel - Test private method process_ioc with Error"""
        mock_client.return_value = MockDynamoDBClient(exception=True)
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        ioc_collections = [StreamIoc(value='1.1.1.2', ioc_type='ip')]
        threat_intel._process_ioc(ioc_collections)
        log_mock.assert_called_with(
            'An error occurred while quering dynamodb table. Error is: %s',
            {'Error': {
                'Code': 400,
                'Message': 'raising test exception'
            }})
示例#8
0
    def test_process_ioc_with_unprocessed_keys(self, mock_client):
        """Threat Intel - Test private method process_ioc when response has UnprocessedKeys"""
        mock_client.return_value = MockDynamoDBClient(unprocesed_keys=True)
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        ioc_collections = [
            StreamIoc(value='1.1.1.2', ioc_type='ip'),
            StreamIoc(value='foo', ioc_type='domain'),
            StreamIoc(value='bar', ioc_type='domain')
        ]
        threat_intel._process_ioc(ioc_collections)
        assert_true(ioc_collections[0].is_ioc)
        assert_false(ioc_collections[1].is_ioc)
        assert_false(ioc_collections[2].is_ioc)
示例#9
0
    def test_process_ioc(self, mock_client):
        """Threat Intel - Test private method process_ioc"""
        mock_client.return_value = MockDynamoDBClient()
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        ioc_collections = [
            StreamIoc(value='1.1.1.2', ioc_type='ip'),
            StreamIoc(value='2.2.2.2', ioc_type='ip'),
            StreamIoc(value='evil.com', ioc_type='domain')
        ]
        threat_intel._process_ioc(ioc_collections)
        assert_true(ioc_collections[0].is_ioc)
        assert_false(ioc_collections[1].is_ioc)
        assert_true(ioc_collections[2].is_ioc)
示例#10
0
    def test_threat_intel_match(self, mock_client):
        """Rules Engine - Threat Intel is enabled when threat_intel_match is called"""
        @rule(datatypes=['sourceAddress', 'destinationDomain', 'fileHash'],
              outputs=['s3:sample_bucket'])
        def match_rule(_): # pylint: disable=unused-variable
            """Testing dummy rule"""
            return True

        mock_client.return_value = MockDynamoDBClient()
        toggled_config = self.config
        toggled_config['global']['threat_intel']['enabled'] = True
        toggled_config['global']['threat_intel']['dynamodb_table'] = 'test_table_name'

        new_rules_engine = RulesEngine(toggled_config)
        records = mock_normalized_records()
        alerts = new_rules_engine.threat_intel_match(records)
        assert_equal(len(alerts), 2)
示例#11
0
 def test_threat_detection_with_empty_ioc_value(self, mock_client):
     """Threat Intel - Test threat_detection with record contains empty/duplicated value"""
     records = [
         {
             'account': 12345,
             'region': '123456123456',
             'detail': {
                 'eventName': 'ConsoleLogin',
                 'userIdentity': {
                     'userName': '******',
                     'accountId': '12345'
                 },
                 'sourceIPAddress': None,
                 'recipientAccountId': '12345'
             },
             'source': '1.1.1.2',
             'streamalert:normalization': {
                 'sourceAddress': [['detail', 'sourceIPAddress'],
                                   ['source']],
                 'usernNme': [['detail', 'userIdentity', 'userName']]
             }
         },
         {
             'domain': 'evil.com',
             'pc_name': 'test-pc',
             'date': 'Dec 1st, 2016',
             'data': 'ABCDEF',
             'streamalert:normalization': {
                 'destinationDomain': [['domain']]
             }
         },
         {
             'domain': 'EVIL.com',
             'pc_name': 'test-pc',
             'date': 'Dec 1st, 2016',
             'data': 'ABCDEF',
             'streamalert:normalization': {
                 'destinationDomain': [['domain']]
             }
         },
     ]
     mock_client.return_value = MockDynamoDBClient()
     threat_intel = StreamThreatIntel.load_from_config(self.config)
     records = mock_normalized_records(records)
     assert_equal(len(threat_intel.threat_detection(records)), 3)
示例#12
0
    def test_query_with_exception(self, mock_client):
        """Threat Intel - Test DynamoDB query method with exception"""
        mock_client.return_value = MockDynamoDBClient(exception=True)
        threat_intel = StreamThreatIntel.load_from_config(self.config)

        threat_intel._query(['1.1.1.2'])
示例#13
0
    def test_process_allow_multi_around_normalization(self, mock_client):
        """Rules Engine - Threat Intel is enabled run multi-round_normalization"""
        @rule(datatypes=['fileHash'], outputs=['s3:sample_bucket'])
        def match_file_hash(rec):  # pylint: disable=unused-variable
            """Testing dummy rule to match file hash"""
            return 'streamalert:ioc' in rec and 'md5' in rec['streamalert:ioc']

        @rule(datatypes=['fileHash'], outputs=['s3:sample_bucket'])
        def match_file_hash_again(_):  # pylint: disable=unused-variable
            """Testing dummy rule to match file hash again"""
            return False

        @rule(datatypes=['fileHash', 'sourceDomain'],
              outputs=['s3:sample_bucket'])
        def match_source_domain(rec):  # pylint: disable=unused-variable
            """Testing dummy rule to match source domain and file hash"""
            return 'streamalert:ioc' in rec

        mock_client.return_value = MockDynamoDBClient()
        toggled_config = self.config
        toggled_config['global']['threat_intel']['enabled'] = True
        toggled_config['global']['threat_intel'][
            'dynamodb_table'] = 'test_table_name'

        new_rules_engine = RulesEngine(toggled_config)
        kinesis_data = {
            "Field1": {
                "SubField1": {
                    "key1": 17,
                    "key2_md5": "md5-of-file",
                    "key3_source_domain": "evil.com"
                },
                "SubField2": 1
            },
            "Field2": {
                "Authentication": {}
            },
            "Field3": {},
            "Field4": {}
        }

        kinesis_data = json.dumps(kinesis_data)
        service, entity = 'kinesis', 'test_stream_threat_intel'
        raw_record = make_kinesis_raw_record(entity, kinesis_data)
        payload = load_and_classify_payload(toggled_config, service, entity,
                                            raw_record)
        alerts, normalized_records = new_rules_engine.run(payload)

        # Two testing rules are for threat intelligence matching. So no alert will be
        # generated before threat intel takes effect.
        assert_equal(len(alerts), 0)

        # One record will be normalized once by two different rules with different
        # normalization keys.
        assert_equal(len(normalized_records), 1)
        assert_equal(
            normalized_records[0].
            pre_parsed_record['streamalert:normalization'].keys(),
            ['fileHash', 'sourceDomain'])

        # Pass normalized records to threat intel engine.
        alerts_from_threat_intel = new_rules_engine.threat_intel_match(
            normalized_records)
        assert_equal(len(alerts_from_threat_intel), 2)
        assert_equal(alerts_from_threat_intel[0].rule_name, 'match_file_hash')
        assert_equal(alerts_from_threat_intel[1].rule_name,
                     'match_source_domain')