diff --git a/CHANGELOG.md b/CHANGELOG.md index e590e765..36cec4c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,9 @@ ## Other changes - [Indexer] Fixed fields types error on instance indexer_alert_config in schema.yml - [#1499](https://github.com/jertel/elastalert2/pull/1499) - @olehpalanskyi -- [IRIS] Changed alert_source field from static 'ElastAlert2' value to field iris_alert_source value with default of 'ElastAlert2' - @bvirgilioamnh +- [IRIS] Changed alert_source field from static 'ElastAlert2' value to field iris_alert_source value with default of 'ElastAlert2' - [#1531](https://github.com/jertel/elastalert2/pull/1531) - @bvirgilioamnh +- [IRIS] Fixed NoneType error raised in issue [#1457](https://github.com/jertel/elastalert2/issues/1457) - [#1533](https://github.com/jertel/elastalert2/pull/1533) - @bvirgilioamnh + # 2.19.0 diff --git a/elastalert/alerters/iris.py b/elastalert/alerters/iris.py index a804a285..be96a2c5 100644 --- a/elastalert/alerters/iris.py +++ b/elastalert/alerters/iris.py @@ -65,9 +65,11 @@ def make_alert_context_records(self, matches): def make_iocs_records(self, matches): iocs = [] for record in self.iocs: - record['ioc_value'] = lookup_es_key(matches[0], record['ioc_value']) - if record['ioc_value'] is not None: - iocs.append(record) + # Duplicating match record data so we can update the ioc_value without overwriting record + record_data = record.copy() + record_data['ioc_value'] = lookup_es_key(matches[0], record['ioc_value']) + if record_data['ioc_value'] is not None: + iocs.append(record_data) return iocs def make_alert(self, matches): diff --git a/tests/alerters/iris_test.py b/tests/alerters/iris_test.py index f7832537..14647008 100644 --- a/tests/alerters/iris_test.py +++ b/tests/alerters/iris_test.py @@ -106,6 +106,73 @@ def test_iris_make_iocs_records(caplog): assert expected_data == actual_data +def test_iris_handle_multiple_alerts_with_iocs(caplog): + caplog.set_level(logging.INFO) + rule = { + 'name': 'Test Context', + 'type': 'any', + 'iris_type': 'alert', + 'iris_host': '127.0.0.1', + 'iris_api_token': 'token 12345', + 'iris_customer_id': 1, + 'iris_iocs': [ + { + 'ioc_description': 'source address', + 'ioc_tags': 'ip, ipv4', + 'ioc_tlp_id': 1, + 'ioc_type_id': 76, + 'ioc_value': 'src_ip' + }, + { + 'ioc_description': 'target username', + 'ioc_tags': 'login, username', + 'ioc_tlp_id': 3, + 'ioc_type_id': 3, + 'ioc_value': 'username' + }, + { + 'ioc_description': 'empty ioc', + 'ioc_tags': 'ioc', + 'ioc_tlp_id': 3, + 'ioc_type_id': 3, + 'ioc_value': 'non_existent_data' + } + ], + 'alert': [] + } + + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = IrisAlerter(rule) + + match = { + '@timestamp': '2023-10-21 20:00:00.000', 'username': 'evil_user', 'src_ip': '172.20.1.1', 'dst_ip': '10.0.0.1', + 'event_type': 'login', 'event_status': 'success' + } + + expected_data = [ + { + 'ioc_description': 'source address', + 'ioc_tags': 'ip, ipv4', + 'ioc_tlp_id': 1, + 'ioc_type_id': 76, + 'ioc_value': '172.20.1.1' + }, + { + 'ioc_description': 'target username', + 'ioc_tags': 'login, username', + 'ioc_tlp_id': 3, + 'ioc_type_id': 3, + 'ioc_value': 'evil_user' + } + ] + + # Submitting a bogus alert to test follow up alerts + alert.make_iocs_records([match]) + actual_data = alert.make_iocs_records([match]) + assert expected_data == actual_data + + def test_iris_make_alert_minimal(caplog): caplog.set_level(logging.INFO) rule = {