Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Add v0.1 of Auth0 username/password bruteforce alert (#1681)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Claudius committed Sep 11, 2020
1 parent ddd2114 commit 140ff2b
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 0 deletions.
4 changes: 4 additions & 0 deletions alerts/auth0_bruteforce_user.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[options]
threshold_count = 1
search_depth_min = 60
severity = 'WARNING'
46 changes: 46 additions & 0 deletions alerts/auth0_bruteforce_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# Copyright (c) 2014 Mozilla Corporation


from lib.alerttask import AlertTask
from mozdef_util.query_models import SearchQuery, TermMatch


class AlertAuth0BruteforceUser(AlertTask):
def main(self):
self.parse_config('auth0_bruteforce_user.conf', ['threshold_count',
'search_depth_min',
'severity'])
search_query = SearchQuery(minutes=int(self.config.search_depth_min))
search_query.add_must_not(TermMatch('details.username', ''))
search_query.add_must([
TermMatch('tags', 'auth0'),
TermMatch('details.eventname', 'Failed Login (wrong password)'),
])

self.filtersManual(search_query)
self.searchEventsAggregated('details.username', samplesLimit=10)
self.walkAggregations(threshold=int(self.config.threshold_count))

def onAggregation(self, aggreg):
category = 'bruteforce'
tags = ['auth0']
severity = self.config.severity
ip_list = set()

for event in aggreg['allevents']:
ip_list.add(event['_source']['details']['sourceipaddress'])

summary = 'Auth0 Username/Password Bruteforce Attack in Progress against user ({0}) from the following source ip(s): {1}'.format(
aggreg['value'], ", ".join(sorted(ip_list)[:10]))

if len(ip_list) >= 10:
summary += '...'

return self.createAlertDict(
summary, category, tags, aggreg['events'], severity
)
103 changes: 103 additions & 0 deletions tests/alerts/test_auth0_bruteforce_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# Copyright (c) 2017 Mozilla Corporation

from .positive_alert_test_case import PositiveAlertTestCase
from .negative_alert_test_case import NegativeAlertTestCase

from .alert_test_suite import AlertTestSuite


class TestAuth0BruteforceUser(AlertTestSuite):
alert_filename = "auth0_bruteforce_user"
alert_classname = "AlertAuth0BruteforceUser"

# This event is the default positive event that will cause the
# alert to trigger
default_event = {
"_source": {
"details": {
"connection": "Mozilla-LDAP",
"description": "Wrong email or password.",
"eventname": "Failed Login (wrong password)",
"sourceipaddress": "1.1.1.1",
"success": False,
"useragent": "Firefox 80.0.0 / Windows 10.0.0",
"userid": "ad|foo",
"username": "foo@mozilla.com",
},
"category": "authentication",
"severity": "ERROR",
"summary": "Failed Login (wrong password) Wrong email or password. by foo@mozilla.com",
"tags": [
"auth0"
],
"type": "event",
}
}

# This alert is the expected result from running this task
default_alert = {
"category": "bruteforce",
"tags": ["auth0"],
"severity": "WARNING",
"summary": "Auth0 Username/Password Bruteforce Attack in Progress against user (foo@mozilla.com) from the following source ip(s): 1.1.1.1",
}

# This alert is the expected result from this task against multiple matching events
default_alert_aggregated = AlertTestSuite.copy(default_alert)
default_alert_aggregated[
"summary"
] = "Auth0 Username/Password Bruteforce Attack in Progress against user (foo@mozilla.com) from the following source ip(s): 1.1.1.1"

test_cases = []

test_cases.append(
PositiveAlertTestCase(
description="Positive test with default events and default alert expected",
events=AlertTestSuite.create_events(default_event, 10),
expected_alert=default_alert,
)
)

test_cases.append(
PositiveAlertTestCase(
description="Positive test with default events and default alert expected - dedup",
events=AlertTestSuite.create_events(default_event, 2),
expected_alert=default_alert,
)
)

events = AlertTestSuite.create_events(default_event, 10)
for event in events:
event["_source"]["details"]["eventname"] = "Success Login"
test_cases.append(
NegativeAlertTestCase(
description="Negative test with default negative event", events=events
)
)

events = AlertTestSuite.create_events(default_event, 10)
for event in events:
event["_source"]["tags"] = ["bad"]
test_cases.append(
NegativeAlertTestCase(
description="Negative test case with events with incorrect tags",
events=events,
)
)

events = AlertTestSuite.create_events(default_event, 10)
for event in events:
event["_source"][
"utctimestamp"
] = AlertTestSuite.subtract_from_timestamp_lambda({"minutes": 241})
event["_source"][
"receivedtimestamp"
] = AlertTestSuite.subtract_from_timestamp_lambda({"minutes": 241})
test_cases.append(
NegativeAlertTestCase(
description="Negative test case with old timestamp", events=events
)
)

0 comments on commit 140ff2b

Please sign in to comment.