Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter out Intelsat satellite network plane wifi from Impossible Travel #1358

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions rules/standard_rules/impossible_travel_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

# pylint: disable=global-variable-undefined

SATELLITE_NETWORK_ASNS = ["AS22351"]


def gen_key(event):
"""
Expand All @@ -26,16 +28,18 @@ def gen_key(event):

def rule(event):
# too-many-return-statements due to error checking
# pylint: disable=global-statement,too-many-return-statements,too-complex
# pylint: disable=global-statement,too-many-return-statements,too-complex,too-many-statements
global EVENT_CITY_TRACKING
global CACHE_KEY
global IS_VPN
global IS_PRIVATE_RELAY
global IS_SATELLITE_NETWORK

EVENT_CITY_TRACKING = {}
CACHE_KEY = ""
IS_VPN = False
IS_PRIVATE_RELAY = False
IS_SATELLITE_NETWORK = False

# Only evaluate successful logins
if event.udm("event_type") != event_type.SUCCESSFUL_LOGIN:
Expand Down Expand Up @@ -87,11 +91,15 @@ def rule(event):
deep_get(ipinfo_privacy, "service", default="") != "",
]
)
if IS_VPN or IS_PRIVATE_RELAY:
# Some satellite networks used during plane travel don't always
# register properly as VPN's, so we have a separate check here.
IS_SATELLITE_NETWORK = is_satellite_network(src_ip_enrichments)
arielkr256 marked this conversation as resolved.
Show resolved Hide resolved
if IS_VPN or IS_PRIVATE_RELAY or IS_SATELLITE_NETWORK:
arielkr256 marked this conversation as resolved.
Show resolved Hide resolved
new_login_stats.update(
{
"is_vpn": f"{IS_VPN}",
"is_apple_priv_relay": f"{IS_PRIVATE_RELAY}",
"is_satellite_network": f"{IS_SATELLITE_NETWORK}",
"service_name": f"{deep_get(ipinfo_privacy, 'service', default='<NO_SERVICE>')}",
"NOTE": "APPLE PRIVATE RELAY AND VPN LOGINS ARE NOT CACHED FOR COMPARISON",
}
Expand All @@ -107,7 +115,7 @@ def rule(event):
# If we haven't seen this user login in the past 1 day,
# store this login for future use and don't alert
if not last_login:
if not (IS_PRIVATE_RELAY or IS_VPN):
if not (IS_PRIVATE_RELAY or IS_VPN or IS_SATELLITE_NETWORK):
arielkr256 marked this conversation as resolved.
Show resolved Hide resolved
put_string_set(
key=CACHE_KEY,
val=[dumps(new_login_stats)],
Expand Down Expand Up @@ -152,6 +160,15 @@ def rule(event):
return speed > 900 # Boeing 747 cruising speed


def is_satellite_network(src_ip_enrichments):
# Satellite networks have a GeoIP to a physical location, but transit around the globe
# In-flight plane wifi like Intelsat provides leads to false positives
ipinfo_asn = deep_get(src_ip_enrichments, "ipinfo_asn")
if deep_get(ipinfo_asn, "asn", default="") in SATELLITE_NETWORK_ASNS:
return True
return False


def title(event):
#
log_source = deep_get(event, "p_source_label", default="<NO_SOURCE_LABEL>")
Expand Down Expand Up @@ -179,7 +196,7 @@ def alert_context(event):


def severity(_):
if IS_VPN or IS_PRIVATE_RELAY:
if any((IS_VPN, IS_PRIVATE_RELAY, IS_SATELLITE_NETWORK)):
return "INFO"
# time = distance/speed
distance = deep_get(EVENT_CITY_TRACKING, "distance", default=None)
Expand Down
104 changes: 104 additions & 0 deletions rules/standard_rules/impossible_travel_login.yml
Original file line number Diff line number Diff line change
Expand Up @@ -825,3 +825,107 @@ Tests:
"uuid": "79999999-ffff-eeee-bbbb-222222222222",
"version": "0",
}
- Name: Okta sign-in with history and impossible travel, no VPN, Intelsat ASN
ExpectedResult: true
Mocks:
- objectName: put_string_set
returnValue: ""
- objectName: get_string_set
returnValue: >-
[
{
"p_event_time": "2023-05-26 18:14:51",
"city": "Los Angeles",
"country": "US",
"lat": "4.05223",
"lng": "-118.24368",
"postal_code": "90009",
"region": "California",
"region_code": "CA",
"timezone": "America/Los_Angeles"
}
]
Log:
{
"actor":
{
"alternateId": "[email protected]",
"displayName": "Homer Simpson",
"id": "00uwuwuwuwuwuwuwuwuw",
"type": "User",
},
"authenticationContext":
{ "authenticationStep": 0, "externalSessionId": "idx1234" },
"client":
{
"device": "Computer",
"ipAddress": "164.86.38.26",
"userAgent":
{
"browser": "CHROME",
"os": "Mac OS X",
"rawUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
},
"zone": "null",
},
"debugContext": { "debugData": {} },
"device": {},
"displayMessage": "User login to Okta",
"eventType": "user.session.start",
"legacyEventType": "core.user_auth.login_success",
"outcome": { "result": "SUCCESS" },
"p_event_time": "2023-05-26 20:18:51",
"p_enrichment":
{
"ipinfo_asn":
{
"client.ipAddress":
{
"asn": "AS22351",
"domain": "intelsat.com",
"name": "INTELSAT GLOBAL SERVICE CORPORATION",
"p_match": "164.86.38.26",
"route": "164.86.38.0/23",
"type": "isp",
},
},
"ipinfo_location":
{
"client.ipAddress":
{
"city": "Tysons Corner",
"country": "US",
"lat": "38.953",
"lng": "-77.2295",
"p_match": "164.86.38.26",
"postal_code": "22102",
"region": "Virginia",
"region_code": "VA",
"timezone": "America/America/New_York",
},
},
"ipinfo_privacy":
{
"client.ipAddress":
{
"hosting": false,
"proxy": false,
"relay": false,
"service": "",
"tor": false,
"vpn": false,
},
},
},
"p_log_type": "Okta.SystemLog",
"p_source_label": "Okta Logs",
"p_parse_time": "2023-05-26 20:22:51.888",
"published": "2023-05-26 20:18:51.888",
"request": { "ipChain": [] },
"securityContext": {},
"severity": "INFO",
"target": [],
"transaction": {},
"uuid": "79999999-ffff-eeee-bbbb-222222222222",
"version": "0",
}
Loading