Skip to content

Commit

Permalink
New: Tailscale Detections and Pack (#852)
Browse files Browse the repository at this point in the history
* New: Tailscale Detections and Pack

* fix: fmt

* fix: tailscale log events seem to have an 'event' attribute that wraps everything other than 'fields' (#853)

---------

Co-authored-by: Ed⁦ <[email protected]>
  • Loading branch information
andrea-youwakim and Ed⁦ authored Jul 19, 2023
1 parent 1e4e940 commit 13e49e6
Show file tree
Hide file tree
Showing 10 changed files with 432 additions and 14 deletions.
2 changes: 1 addition & 1 deletion global_helpers/global_filter_tailscale.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def filter_include_event(event) -> bool: # pylint: disable=unused-argument
#
# # example: event.origin
# # if we don't know the event_origin, we want default behavior to be to alert on this event.
# event_origin = deep_get(event, "origin", default="")
# event_origin = deep_get(event, "event", "origin", default="")
# return event_origin in ["ADMIN_CONSOLE", ""]
#
return True
23 changes: 13 additions & 10 deletions global_helpers/global_helpers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1879,17 +1879,20 @@ class TestTailscaleHelpers(unittest.TestCase):
def setUp(self):
self.event = ImmutableCaseInsensitiveDict(
{
"action": "CREATE",
"actor": {
"displayName": "Homer Simpson",
"id": "uodc9f3CNTRL",
"loginName": "[email protected]",
"type": "USER",
"event": {
"action": "CREATE",
"actor": {
"displayName": "Homer Simpson",
"id": "uodc9f3CNTRL",
"loginName": "[email protected]",
"type": "USER",
},
"eventGroupID": "9f880e02981e341447958344b7b4071f",
"new": {},
"origin": "ADMIN_CONSOLE",
"target": {"id": "k6r3fm3CNTRL", "name": "API key", "type": "API_KEY"},
},
"eventGroupID": "9f880e02981e341447958344b7b4071f",
"new": {},
"origin": "ADMIN_CONSOLE",
"target": {"id": "k6r3fm3CNTRL", "name": "API key", "type": "API_KEY"},
"fields": {"recorded": "2023-07-19 16:10:48.385283827"},
}
)

Expand Down
6 changes: 3 additions & 3 deletions global_helpers/panther_tailscale_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

def tailscale_alert_context(event) -> dict:
a_c = {}
a_c["actor"] = deep_get(event, "actor", default="<NO_ACTOR_FOUND>")
a_c["action"] = deep_get(event, "action", default="<NO_ACTION_FOUND>")
a_c["actor"] = deep_get(event, "event", "actor", default="<NO_ACTOR_FOUND>")
a_c["action"] = deep_get(event, "event", "action", default="<NO_ACTION_FOUND>")
return a_c


def is_tailscale_admin_console_event(event):
origin = deep_get(event, "origin", default="")
origin = deep_get(event, "event", "origin", default="")
return origin == "ADMIN_CONSOLE"
13 changes: 13 additions & 0 deletions packs/tailscale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
AnalysisType: pack
PackID: PantherManaged.Tailscale
Description: Group of all Tailscale detections
PackDefinition:
IDs:
- Tailscale.Magic.DNS.Disabled
- Tailscale.HTTPS.Disabled
- Tailscale.Machine.Approval.Requirements.Disabled
# Globals used in these detections
- panther_base_helpers
- panther_tailscale_helpers
- global_filter_tailscale
DisplayName: "Panther Tailscale Pack"
35 changes: 35 additions & 0 deletions rules/tailscale_rules/tailscale_https_disabled.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from global_filter_tailscale import filter_include_event
from panther_base_helpers import deep_get
from panther_tailscale_helpers import (
is_tailscale_admin_console_event,
tailscale_alert_context,
)


def rule(event):
if not filter_include_event(event):
return False
action = deep_get(event, "event", "action", default="<NO_ACTION_FOUND>")
target_property = deep_get(
event, "event", "target", "property", default="<NO_TARGET_PROPERTY_FOUND>"
)
return all(
[
action == "DISABLE",
target_property == "HTTPS",
is_tailscale_admin_console_event(event),
]
)


def title(event):
user = deep_get(event, "event", "actor", "loginName", default="<NO_USER_FOUND>")
target_id = deep_get(event, "event", "target", "id", default="<NO_TARGET_ID_FOUND>")
return (
f"Tailscale user [{user}] disabled HTTPS for "
f"[{target_id}] in your organization’s tenant."
)


def alert_context(event):
return tailscale_alert_context(event)
99 changes: 99 additions & 0 deletions rules/tailscale_rules/tailscale_https_disabled.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
AnalysisType: rule
Description: A Tailscale User disabled HTTPS settings in your organization's tenant.
DisplayName: "Tailscale HTTPS Disabled"
Enabled: true
Filename: tailscale_https_disabled.py
Runbook: Assess if this was done by the user for a valid business reason. Be vigilant to re-enable this setting as it's in the best security interest for your organization's security posture.
Severity: High
Tests:
- ExpectedResult: true
Log:
{
"event": {
"action": "DISABLE",
"actor": {
"displayName": "Homer Simpson",
"id": "uodc9f3CNTRL",
"loginName": "[email protected]",
"type": "USER"
},
"eventGroupID": "1770eb26fb58fbf67fd8fbfcc2056e66",
"origin": "ADMIN_CONSOLE",
"target": {
"id": "yoururl.com",
"name": "yoururl.com",
"property": "HTTPS",
"type": "TAILNET"
},
},
"fields": {
"recorded": "2023-07-19 16:10:48.385283827"
},
"p_any_actor_ids": [
"uodc9f3CNTRL"
],
"p_any_emails": [
"[email protected]"
],
"p_any_usernames": [
"andrea.youwakim"
],
"p_event_time": "2023-07-19 16:10:48.172000",
"p_log_type": "Tailscale.Audit",
"p_parse_time": "2023-07-19 16:13:56.849092",
"p_row_id": "5e197fb53834e39eeab7feb9198d04",
"p_schema_version": 0,
"p_source_id": "5d65e24a-7ebb-403b-803c-51396e03d201",
"p_source_label": "Tailscale Audit and Network Logs",
"p_udm": {},
"time": "2023-07-19 16:10:48.172000000"
}
Name: HTTPS Disabled
- ExpectedResult: false
Log:
{
"event": {
"action": "CREATE",
"actor": {
"displayName": "Homer Simpson",
"id": "uodc9f3CNTRL",
"loginName": "[email protected]",
"type": "USER"
},
"eventGroupID": "9f880e02981e341447958344b7b4071f",
"new": {},
"origin": "ADMIN_CONSOLE",
"target": {
"id": "k6r3fm3CNTRL",
"name": "API key",
"type": "API_KEY"
},
},
"fields": {
"recorded": "2023-07-19 16:11:41.778839718"
},
"p_any_actor_ids": [
"uodc9f3CNTRL"
],
"p_any_emails": [
"[email protected]"
],
"p_any_usernames": [
"homersimpson"
],
"p_event_time": "2023-07-19 16:11:41.601000",
"p_log_type": "Tailscale.Audit",
"p_parse_time": "2023-07-19 16:14:56.865276",
"p_row_id": "02eaf97ec9caaaabff8882ba19ad1d",
"p_schema_version": 0,
"p_source_id": "5d65e24a-7ebb-403b-803c-51396e03d201",
"p_source_label": "Tailscale Audit and Network Logs",
"p_udm": {},
"time": "2023-07-19 16:11:41.601000000"
}
Name: Other Event
DedupPeriodMinutes: 60
LogTypes:
- Tailscale.Audit
RuleID: "Tailscale.HTTPS.Disabled"
Threshold: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from global_filter_tailscale import filter_include_event
from panther_base_helpers import deep_get
from panther_tailscale_helpers import (
is_tailscale_admin_console_event,
tailscale_alert_context,
)


def rule(event):
if not filter_include_event(event):
return False
action = deep_get(event, "event", "action", default="<NO_ACTION_FOUND>")
target_property = deep_get(
event, "event", "target", "property", default="<NO_TARGET_PROPERTY_FOUND>"
)
return all(
[
action == "DISABLE",
target_property == "MACHINE_APPROVAL_NEEDED",
is_tailscale_admin_console_event(event),
]
)


def title(event):
user = deep_get(event, "event", "actor", "loginName", default="<NO_USER_FOUND>")
return (
f"Tailscale user [{user}] disabled device approval requirements "
f"for new devices accessing your organization’s network."
)


def alert_context(event):
return tailscale_alert_context(event)
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
AnalysisType: rule
Description: A Tailscale User disabled machine approval requirement settings in your organization's tenant. This means devices can access your network without requiring approval.
DisplayName: "Tailscale Machine Approval Requirements Disabled"
Enabled: true
Filename: tailscale_machine_approval_requirements_disabled.py
Runbook: Assess if this was done by the user for a valid business reason. Be vigilant to re-enable this setting as it's in the best security interest for your organization's security posture.
Severity: High
Tests:
- ExpectedResult: true
Log:
{
"event": {
"action": "DISABLE",
"actor": {
"displayName": "Homer Simpson",
"id": "uhfQwM4CNTRL",
"loginName": "[email protected]",
"type": "USER"
},
"eventGroupID": "6dae044c7a8998599e94657b511d28f9",
"origin": "ADMIN_CONSOLE",
"target": {
"id": "panther.com",
"name": "panther.com",
"property": "MACHINE_APPROVAL_NEEDED",
"type": "TAILNET"
},
},
"fields": {
"recorded": "2023-06-27 22:58:15.824694387"
},
"p_any_emails": [
"[email protected]"
],
"p_any_md5_hashes": [
"6dae044c7a8998599e94657b511d28f9"
],
"p_any_usernames": [
"homersimpson"
],
"p_event_time": "2023-06-27 23:02:08.54",
"p_log_type": "Custom.TailscaleAudit",
"p_parse_time": "2023-06-27 23:02:08.54",
"p_row_id": "8ec49771e630f6e8e5fdb28319d95c",
"p_schema_version": 4,
"p_source_id": "3acfbe1d-f7b2-4c3f-a26e-8da418fd29ef",
"p_source_label": "Custom Tailscale Audit",
"p_timeline": "2023-06-27 23:02:08.54",
"p_udm": {},
"time": 1687906694.915
}
Name: Machine Approval Requirements Disabled
- ExpectedResult: false
Log:
{
"event": {
"action": "CREATE",
"actor": {
"displayName": "Homer Simpson",
"id": "uodc9f3CNTRL",
"loginName": "[email protected]",
"type": "USER"
},
"eventGroupID": "9f880e02981e341447958344b7b4071f",
"new": {},
"origin": "ADMIN_CONSOLE",
"target": {
"id": "k6r3fm3CNTRL",
"name": "API key",
"type": "API_KEY"
},
},
"fields": {
"recorded": "2023-07-19 16:11:41.778839718"
},
"p_any_actor_ids": [
"uodc9f3CNTRL"
],
"p_any_emails": [
"[email protected]"
],
"p_any_usernames": [
"homersimpson"
],
"p_event_time": "2023-07-19 16:11:41.601000",
"p_log_type": "Tailscale.Audit",
"p_parse_time": "2023-07-19 16:14:56.865276",
"p_row_id": "02eaf97ec9caaaabff8882ba19ad1d",
"p_schema_version": 0,
"p_source_id": "5d65e24a-7ebb-403b-803c-51396e03d201",
"p_source_label": "Tailscale Audit and Network Logs",
"p_udm": {},
"time": "2023-07-19 16:11:41.601000000"
}
Name: Other Event
DedupPeriodMinutes: 60
LogTypes:
- Tailscale.Audit
RuleID: "Tailscale.Machine.Approval.Requirements.Disabled"
Threshold: 1
35 changes: 35 additions & 0 deletions rules/tailscale_rules/tailscale_magicdns_disabled.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from global_filter_tailscale import filter_include_event
from panther_base_helpers import deep_get
from panther_tailscale_helpers import (
is_tailscale_admin_console_event,
tailscale_alert_context,
)


def rule(event):
if not filter_include_event(event):
return False
action = deep_get(event, "event", "action", default="<NO_ACTION_FOUND>")
target_property = deep_get(
event, "event", "target", "property", default="<NO_TARGET_PROPERTY_FOUND>"
)
return all(
[
action == "DISABLE",
target_property == "MAGIC_DNS",
is_tailscale_admin_console_event(event),
]
)


def title(event):
user = deep_get(event, "event", "actor", "loginName", default="<NO_USER_FOUND>")
target_id = deep_get(event, "event", "target", "id", default="<NO_TARGET_ID_FOUND>")
return (
f"Tailscale user [{user}] disabled Magic DNS for "
f"[{target_id}] in your organization’s tenant."
)


def alert_context(event):
return tailscale_alert_context(event)
Loading

0 comments on commit 13e49e6

Please sign in to comment.