diff --git a/alerts/proxy_drop_non_standard_port.py b/alerts/proxy_drop_non_standard_port.py index 0b04b635..8013b8e2 100644 --- a/alerts/proxy_drop_non_standard_port.py +++ b/alerts/proxy_drop_non_standard_port.py @@ -7,44 +7,50 @@ from lib.alerttask import AlertTask -from query_models import SearchQuery, TermMatch, ExistsMatch +from query_models import QueryStringMatch, SearchQuery, TermMatch class AlertProxyDropNonStandardPort(AlertTask): def main(self): - search_query = SearchQuery(minutes=5) + search_query = SearchQuery(minutes=20) search_query.add_must([ TermMatch('category', 'squid'), + TermMatch('tags', 'squid'), TermMatch('details.proxyaction', 'TCP_DENIED/-'), - TermMatch('details.tcpaction', 'CONNECT'), + TermMatch('details.tcpaction', 'CONNECT') ]) search_query.add_must_not([ - PhraseMatch('details.destination', ':443') + QueryStringMatch('details.destination: /.*:443/') ]) self.filtersManual(search_query) - # Search aggregations on field 'ip', keep X samples of events at most + # Search aggregations on field 'hostname', keep X samples of + # events at most self.searchEventsAggregated('details.sourceipaddress', samplesLimit=10) # alert when >= X matching events in an aggregation + # I think it makes sense to alert every time here self.walkAggregations(threshold=1) - # Set alert properties + # Set alert properties def onAggregation(self, aggreg): - # aggreg['count']: number of items in the aggregation, ex: number of failed login attempts - # aggreg['value']: value of the aggregation field, ex: toto@example.com - # aggreg['events']: list of events in the aggregation + # aggreg['count']: number of items in the aggregation, ex: number of failed login attempts + # aggreg['value']: value of the aggregation field, ex: toto@example.com + # aggreg['events']: list of events in the aggregation category = 'squid' tags = ['squid', 'proxy'] severity = 'WARNING' - destinations = [] - + destinations = set() for event in aggreg['allevents']: - destinations.append(event['_source']['details.destination']) + destinations.add(event['_source']['details']['destination']) - summary = ('Suspicious proxy activity from {0} attempting to reach non-std services: {1}'.format(aggreg['value'], join(", ", destinations)) + summary = 'Suspicious Proxy DROP events detected from {0} to the following non-std port(s): {1}'.format( + aggreg['value'], + ",".join(sorted(destinations)) + ) + # Create the alert object based on these properties return self.createAlertDict(summary, category, tags, aggreg['events'], severity) diff --git a/tests/alerts/test_proxy_drop_non_standard_port.py b/tests/alerts/test_proxy_drop_non_standard_port.py index f2b9c122..41e9d0c0 100644 --- a/tests/alerts/test_proxy_drop_non_standard_port.py +++ b/tests/alerts/test_proxy_drop_non_standard_port.py @@ -9,7 +9,7 @@ from negative_alert_test_case import NegativeAlertTestCase from alert_test_suite import AlertTestSuite -class TestAlertSSHPasswordAuthViolation(AlertTestSuite): +class TestAlertProxyDropNonStandardPort(AlertTestSuite): alert_filename = "proxy_drop_non_standard_port" # This event is the default positive event that will cause the @@ -20,10 +20,29 @@ class TestAlertSSHPasswordAuthViolation(AlertTestSuite): "category": "squid", "tags": ["squid"], "details": { - "details.sourceipaddress": "1.2.3.4", - "details.destination": "evil.com:6667", - "details.proxyaction": "TCP_DENIED/-", - "details.tcpaction": "CONNECT", + "sourceipaddress": "1.2.3.4", + "destination": "evil.com:6667", + "proxyaction": "TCP_DENIED/-", + "tcpaction": "CONNECT" + } + } + } + + default_event2 = AlertTestSuite.copy(default_event) + default_event2["_source"]["details"]["destination"] = "evil.com:1337" + + # This event is the default negative event that will cause the + # alert to trigger + default_negative_event = { + "_type": "event", + "_source": { + "category": "squid", + "tags": ["squid"], + "details": { + "sourceipaddress": "1.2.3.4", + "destination": "example.com:443", + "proxyaction": "TCP_DENIED/-", + "tcpaction": "CONNECT" } } } @@ -33,9 +52,13 @@ class TestAlertSSHPasswordAuthViolation(AlertTestSuite): "category": "squid", "tags": ['squid', 'proxy'], "severity": "WARNING", - "summary": 'Suspicious proxy activity from 1.2.3.4 attempting to reach non-std services: evil.com:6667', + "summary": 'Suspicious Proxy DROP events detected from 1.2.3.4 to the following non-std port(s): evil.com:6667' } + default_alert_aggregated = AlertTestSuite.copy(default_alert) + default_alert_aggregated[ + "summary"] = 'Suspicious Proxy DROP events detected from 1.2.3.4 to the following non-std port(s): evil.com:1337,evil.com:6667' + test_cases = [] test_cases.append( @@ -46,6 +69,23 @@ class TestAlertSSHPasswordAuthViolation(AlertTestSuite): ) ) + events1 = AlertTestSuite.create_events(default_event, 1) + events2 = AlertTestSuite.create_events(default_event2, 1) + test_cases.append( + PositiveAlertTestCase( + description="Positive test with default events and default alert expected", + events=events1 + events2, + expected_alert=default_alert_aggregated + ) + ) + + test_cases.append( + NegativeAlertTestCase( + description="Positive test with default events and default alert expected", + events=AlertTestSuite.create_events(default_negative_event, 1), + ) + ) + events = AlertTestSuite.create_events(default_event, 10) for event in events: event['_source']['category'] = 'bad'