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

Cy 496 o365 user audit signin logs #342

Merged
merged 9 commits into from
Jul 20, 2023
5,258 changes: 5,258 additions & 0 deletions cyences_app_for_splunk/default/data/models/Cyences_Authentication.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@
</input>
<table>
<search>
<query>| tstats `cs_summariesonly_authentication` values(Authentication.src) as src_ip from datamodel=Authentication where Authentication.dest_category="vpn_auth" AND $tkn_filter_authentication$ AND `cs_vpn_indexes` by _time Authentication.action Authentication.user span=1s | rename Authentication.* as *
<query>| tstats `cs_summariesonly_authentication` values(Authentication.src) as src_ip from datamodel=Cyences_Authentication where Authentication.dest_category="vpn_auth" AND $tkn_filter_authentication$ AND `cs_vpn_indexes` by _time Authentication.action Authentication.user span=1s | rename Authentication.* as *
| iplocation src_ip
| eval Country = if(isnull(Country) OR Country="", "Unknown", Country)
| eval City = if(isnull(City) OR City="", "Unknown", City) | fields _time user action src_ip City Country
Expand Down Expand Up @@ -320,7 +320,7 @@
</input>
<table>
<search>
<query>| tstats `cs_summariesonly_authentication` count from datamodel=Authentication where `cs_authentication_indexes` $tkn_filter_authentication$ Authentication.app!=OktaIM2:log Authentication.action IN ("success","failure") Authentication.app="*" `cs_authentication_app_filter` by Authentication.app Authentication.action Authentication.user, Authentication.src</query>
<query>| tstats `cs_summariesonly_authentication` count from datamodel=Cyences_Authentication where `cs_o365_login_filter_source` `cs_authentication_indexes` $tkn_filter_authentication$ Authentication.app!=OktaIM2:log Authentication.action IN ("success","failure") Authentication.app="*" `cs_authentication_app_filter` by Authentication.app Authentication.action Authentication.user, Authentication.src</query>
<earliest>$tkn_timeRange_authentication.earliest$</earliest>
<latest>$tkn_timeRange_authentication.latest$</latest>
</search>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<fieldForLabel>app</fieldForLabel>
<fieldForValue>app</fieldForValue>
<search>
<query>| tstats `cs_summariesonly_authentication` count from datamodel=Authentication where `cs_authentication_indexes` `cs_authentication_app_filter` by Authentication.app | rename "Authentication.app" as app</query>
<query>| tstats `cs_summariesonly_authentication` count from datamodel=Cyences_Authentication where `cs_o365_login_filter_source` `cs_authentication_indexes` `cs_authentication_app_filter` by Authentication.app | rename "Authentication.app" as app</query>
<earliest>$timeRange.earliest$</earliest>
<latest>$timeRange.latest$</latest>
</search>
Expand Down Expand Up @@ -48,7 +48,7 @@
<title>All Authentications</title>
<chart>
<search>
<query>| tstats `cs_summariesonly_authentication` prestats=t count as count, dc(Authentication.user) as dc_users from datamodel=Authentication where `cs_authentication_indexes` Authentication.action IN ("success","failure") Authentication.app=$tkn_app|s$ `cs_authentication_app_filter` by _time Authentication.action
<query>| tstats `cs_summariesonly_authentication` prestats=t count as count, dc(Authentication.user) as dc_users from datamodel=Cyences_Authentication where `cs_o365_login_filter_source` `cs_authentication_indexes` Authentication.action IN ("success","failure") Authentication.app=$tkn_app|s$ `cs_authentication_app_filter` by _time Authentication.action
| timechart span=1h count, dc(Authentication.user) by Authentication.action
| eval "Unique Users"='dc(Authentication.user): failure'+'dc(Authentication.user): success'
| fields - "dc(Authentication.user): failure", "dc(Authentication.user): success"
Expand All @@ -75,7 +75,7 @@
<title>Authentication Failure Reasons Over Time</title>
<chart>
<search>
<query>| tstats `cs_summariesonly_authentication` prestats=t count from datamodel=Authentication where `cs_authentication_indexes` nodename=Authentication.Failed_Authentication Authentication.action=failure Authentication.app=$tkn_app|s$ `cs_authentication_app_filter` by _time Authentication.signature
<query>| tstats `cs_summariesonly_authentication` prestats=t count from datamodel=Cyences_Authentication where `cs_o365_login_filter_source` `cs_authentication_indexes` nodename=Authentication.Failed_Authentication Authentication.action=failure Authentication.app=$tkn_app|s$ `cs_authentication_app_filter` by _time Authentication.signature
| timechart span=1h count by Authentication.signature limit=0</query>
<earliest>$timeRange.earliest$</earliest>
<latest>$timeRange.latest$</latest>
Expand All @@ -96,7 +96,7 @@
<title>Application Authentication Success Rate</title>
<table>
<search>
<query>| tstats `cs_summariesonly_authentication` prestats=t count from datamodel=Authentication where `cs_authentication_indexes` Authentication.app!=OktaIM2:log Authentication.action IN ("success","failure") Authentication.app=$tkn_app|s$ `cs_authentication_app_filter` by Authentication.app Authentication.action | `drop_dm_object_name(Authentication)`
<query>| tstats `cs_summariesonly_authentication` prestats=t count from datamodel=Cyences_Authentication where `cs_o365_login_filter_source` `cs_authentication_indexes` Authentication.app!=OktaIM2:log Authentication.action IN ("success","failure") Authentication.app=$tkn_app|s$ `cs_authentication_app_filter` by Authentication.app Authentication.action | `drop_dm_object_name(Authentication)`
| chart count by app action
| addtotals
| eval "Success%" = round(success / Total * 100,2)
Expand Down Expand Up @@ -143,7 +143,7 @@
</input>
<table>
<search>
<query>| tstats `cs_summariesonly_authentication` count as count, latest(_time) as last_login from datamodel=Authentication where `cs_authentication_indexes` Authentication.action IN ("success","failure") Authentication.app=$tkn_app|s$ Authentication.user=$tkn_user|s$ `cs_authentication_app_filter` by Authentication.user, Authentication.app, Authentication.action
<query>| tstats `cs_summariesonly_authentication` count as count, latest(_time) as last_login from datamodel=Cyences_Authentication where `cs_o365_login_filter_source` `cs_authentication_indexes` Authentication.action IN ("success","failure") Authentication.app=$tkn_app|s$ Authentication.user=$tkn_user|s$ `cs_authentication_app_filter` by Authentication.user, Authentication.app, Authentication.action
| `drop_dm_object_name(Authentication)`
| eval over_field=user."|".app
| chart sum(count) as count, max(last_login) as last_login over over_field by action
Expand Down
43 changes: 37 additions & 6 deletions cyences_app_for_splunk/default/data/ui/views/cs_o365_reports.xml
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,25 @@
</input>
<table>
<search>
<query>`cs_o365` sourcetype="o365:management:activity" Workload=AzureActiveDirectory Operation=UserLoggedIn NOT LogonError=* $tkn_host$| iplocation ClientIP | search $tkn_drop__country$ user=$tkn__user|s$ | stats count, values(user_type) as user_type, values(authentication_method) as authentication_method, latest(_time) as Last_Success_Login, values(ClientIP) as ClientIPs, values(Country) as Country, values(Region) as Region, values(City) as City by host, user | fields - host | `cs_human_readable_time_format(Last_Success_Login)` | `cs_o365_success_login_outside_country_filter`</query>
<query>`cs_o365` sourcetype="o365:management:activity" Workload=AzureActiveDirectory Operation=UserLoggedIn NOT LogonError=* $tkn_host$
| fields _time host sourcetype user ClientIP Id user_type authentication_method
| append
[| search `cs_o365` sourcetype=o365:graph:api source="AuditLogs.SignIns" status.errorCode=0 $tkn_host$
| fields _time host sourcetype userPrincipalName ipAddress id LogonError appDisplayName clientAppUsed conditionalAccessStatus isInteractive deviceDetail.* org_country org_region org_city
| rename userPrincipalName as user, ipAddress as ClientIP, id as Id ]
| eval user = lower(user)
| stats values(*) as *, max(_time) as Last_Success_Login by Id, host, user, ClientIP
| search sourcetype="o365:management:activity"
| fields - Id, sourcetype, lat, lon, deviceDetail.deviceId
| stats count, values(*) as *, max(Last_Success_Login) as Last_Success_Login by host, user, ClientIP
| iplocation ClientIP
| eval Country = if(isnotnull(org_country), org_country, Country)
| eval Region = if(isnotnull(org_country), org_region, Region)
| eval City = if(isnotnull(org_country), org_city, City)
| search $tkn_drop__country$ user=$tkn__user|s$
| table user, ClientIP, count, Country, Region, City, Last_Success_Login, user_type, authentication_method, appDisplayName clientAppUsed conditionalAccessStatus isInteractive deviceDetail.*
| `cs_human_readable_time_format(Last_Success_Login)`
| `cs_o365_success_login_outside_country_filter`</query>
<earliest>$timeRange.earliest$</earliest>
<latest>$timeRange.latest$</latest>
<sampleRatio>1</sampleRatio>
Expand Down Expand Up @@ -273,12 +291,25 @@
</input>
<table>
<search>
<query>`cs_o365` sourcetype="o365:management:activity" Workload=AzureActiveDirectory Operation=UserLoginFailed $tkn_host$ $tkn_logon_error$
<query>`cs_o365` sourcetype="o365:management:activity" Workload=AzureActiveDirectory Operation=UserLoginFailed $tkn_host$ $tkn_logon_error$
| fields _time host sourcetype user ClientIP Id LogonError user_type authentication_method app ApplicationId ExtendedProperties{}.Name ExtendedProperties{}.Value
| eval ExtendedProperties=mvzip('ExtendedProperties{}.Name','ExtendedProperties{}.Value'," : ")
| append
[| search `cs_o365` sourcetype=o365:graph:api source="AuditLogs.SignIns" status.errorCode!=0 $tkn_host$ $tkn_logon_error$
| fields _time host sourcetype userPrincipalName ipAddress id LogonError appDisplayName clientAppUsed conditionalAccessStatus isInteractive deviceDetail.* org_country org_region org_city
| rename userPrincipalName as user, ipAddress as ClientIP, id as Id ]
| eval user = lower(user)
| stats values(*) as *, max(_time) as _time by Id, host, user, ClientIP, LogonError
| search sourcetype="o365:management:activity"
| fields - Id, sourcetype, lat, lon, deviceDetail.deviceId
| stats count, values(*) as *, max(_time) as Last_Failed_Login by host, user, ClientIP, LogonError
| iplocation ClientIP
| eval Country = if(isnotnull(org_country), org_country, Country)
| eval Region = if(isnotnull(org_country), org_region, Region)
| eval City = if(isnotnull(org_country), org_city, City)
| search $tkn_drop_country$ user=$tkn_user|s$
| eval ExtendedProperties=mvzip('ExtendedProperties{}.Name','ExtendedProperties{}.Value'," : ")
| stats count, values(user_type) as user_type, values(authentication_method) as authentication_method, latest(_time) as Last_Failed_Login, values(ExtendedProperties) as ExtendedProperties, values(Country) as Country, values(Region) as Region, values(City) as City by host, user, LogonError, ClientIP
| fields - host | `cs_human_readable_time_format(Last_Failed_Login)`
| table user, ClientIP, LogonError, count, Country, Region, City, Last_Failed_Login, user_type, authentication_method, appDisplayName clientAppUsed conditionalAccessStatus isInteractive deviceDetail.* , ExtendedProperties
| `cs_human_readable_time_format(Last_Failed_Login)`
| `cs_o365_failed_login_outside_country_filter`</query>
<earliest>$timeRange.earliest$</earliest>
<latest>$timeRange.latest$</latest>
Expand All @@ -299,7 +330,7 @@
<title>Office 365/Azure - Login from Unknown UserId</title>
<table>
<search>
<query>`cs_o365` sourcetype="o365:management:activity" Workload=AzureActiveDirectory Operation=UserLoggedIn UserId=Unknown $tkn_host$| iplocation ClientIP | `cs_human_readable_time_format(_time, time)` | stats count, list(time) as time, first(Country) as Country, first(Region) as Region, first(City) as City, first(user) as user by host, ClientIP | fields - time | `cs_o365_login_by_unknown_userid_filter`</query>
<query>`cs_o365` sourcetype="o365:management:activity" Workload=AzureActiveDirectory Operation=UserLoggedIn (UserId=Unknown OR UserId="Not Available") $tkn_host$| iplocation ClientIP | `cs_human_readable_time_format(_time, time)` | stats count, list(time) as time, first(Country) as Country, first(Region) as Region, first(City) as City, first(user) as user by host, ClientIP | fields - time | `cs_o365_login_by_unknown_userid_filter`</query>
<earliest>$timeRange.earliest$</earliest>
<latest>$timeRange.latest$</latest>
</search>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<search>
<query>`cs_palo` sourcetype!="pan:log" sourcetype!="pan:globalprotect"
| stats count as Event_Count, values(dvc_name) as dvc_name, values(sourcetype) as sourcetype by host
| append [| tstats `cs_summariesonly_authentication` count as VPN from datamodel=Authentication where Authentication.dest_category="vpn_auth" AND `cs_palo` by host]
| append [| tstats `cs_summariesonly_authentication` count as VPN from datamodel=Cyences_Authentication where Authentication.dest_category="vpn_auth" AND `cs_palo` by host]
| stats values(dvc_name) as dvc_name, values(sourcetype) as sourcetype, sum(*) as * by host
| eval VPN=if(VPN&gt;0,"Global Protect Present", "Global Protect Absent") | fields - Event_Count | sort - VPN</query>
<earliest>$timeRange.earliest$</earliest>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</init>
<search id="bs0">
<query>
| tstats `cs_summariesonly_authentication` values(Authentication.src) as src_ip from datamodel=Authentication where Authentication.dest_category="vpn_auth" AND `cs_vpn_indexes` by _time Authentication.action Authentication.user Authentication.dest span=1s
| tstats `cs_summariesonly_authentication` values(Authentication.src) as src_ip from datamodel=Cyences_Authentication where Authentication.dest_category="vpn_auth" AND `cs_vpn_indexes` by _time Authentication.action Authentication.user Authentication.dest span=1s
| rename Authentication.* as *
</query>
<earliest>$time.earliest$</earliest>
Expand Down
5 changes: 5 additions & 0 deletions cyences_app_for_splunk/default/datamodels.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ acceleration.schedule_priority = highest
acceleration = false
acceleration.earliest_time = -6mon
acceleration.schedule_priority = highest

[Cyences_Authentication]
acceleration = false
acceleration.earliest_time = -1mon
acceleration.schedule_priority = highest
3 changes: 3 additions & 0 deletions cyences_app_for_splunk/default/eventtypes.conf
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ search = (sourcetype="cisco:estreamer:data" rec_type_desc="New VPN Device Logoff
[cs_o365_authentication]
search = sourcetype="o365:management:activity" Workload=AzureActiveDirectory Operation=UserLog*

[cs_o365_audit_sigin_authentication]
search = sourcetype=o365:graph:api source="AuditLogs.SignIns"


##############
### GSuite ###
Expand Down
35 changes: 34 additions & 1 deletion cyences_app_for_splunk/default/macros.conf
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,12 @@ iseval = 0
[cs_current_week_login_count(1)]
args = sourcetypefilter
definition = eval main_event="1" \
| append [ | tstats count from datamodel=Authentication where Authentication.action="success" AND Authentication.user!="unknown" AND `cs_public_ips(Authentication.src)` AND sourcetype="$sourcetypefilter$" AND earliest="@w" latest="@d" by Authentication.app, Authentication.user, Authentication.src \
| append [ | tstats count, values(Authentication.org_country) as org_country from datamodel=Cyences_Authentication where Authentication.action="success" AND Authentication.user!="unknown" AND `cs_public_ips(Authentication.src)` AND sourcetype="$sourcetypefilter$" AND earliest="@w" latest="@d" by Authentication.app, Authentication.user, Authentication.src \
| `drop_dm_object_name(Authentication)` \
| iplocation src \
| eval Country = if(isnotnull(org_country), org_country, Country) \
| inputlookup cs_authentication_usual_location.csv append=true \
| eval user = lower(user) \
| stats sum(count) as count by user, app, Country \
| eventstats sum(count) as total by user, app \
| eval percentage_login_from_country = round(count*100/total, 2) \
Expand All @@ -546,6 +548,37 @@ definition = eval main_event="1" \
| fields - main_event
iseval = 0

[cs_current_week_login_count_o365]
definition = eval main_event="1" \
| append [ | tstats count, values(Authentication.org_country) as org_country from datamodel=Cyences_Authentication where Authentication.action="success" AND Authentication.user!="unknown" AND `cs_public_ips(Authentication.src)` AND `cs_o365_login_source` AND earliest="@w" latest="@d" by Authentication.app, Authentication.user, Authentication.src \
| `drop_dm_object_name(Authentication)` \
| iplocation src \
| eval Country = if(isnotnull(org_country), org_country, Country) \
| inputlookup cs_authentication_usual_location.csv append=true \
| eval user = lower(user) \
| stats sum(count) as count by user, app, Country \
| eventstats sum(count) as total by user, app \
| eval percentage_login_from_country = round(count*100/total, 2) \
| table user app Country percentage_login_from_country ] \
| eventstats values(eval(Country." (". percentage_login_from_country. "%)")) as usual_login_location by user, app \
| stats values(*) as * by user,app, Country \
| search main_event="1" \
| fields - main_event
iseval = 0

[cs_o365_login_source]
definition = [|search `cs_o365` (sourcetype="o365:management:activity" OR (sourcetype=o365:graph:api source="AuditLogs.SignIns")) earliest=-2h latest=now \
| stats values(sourcetype) as sourcetype, dc(sourcetype) as count \
| eval search=if(count==2 or (count==1 and sourcetype=="o365:graph:api"), "(sourcetype=o365:graph:api source=AuditLogs.SignIns)", "sourcetype=o365:management:activity") \
| table search | return $search]
iseval = 0

[cs_o365_login_filter_source]
definition = [|search `cs_o365` (sourcetype="o365:management:activity" OR (sourcetype=o365:graph:api source="AuditLogs.SignIns")) earliest=-2h latest=now \
| stats values(sourcetype) as sourcetype, dc(sourcetype) as count \
| eval search=if(count==2 or (count==1 and sourcetype=="o365:graph:api"), "sourcetype!=o365:management:activity", "(sourcetype!=o365:graph:api source!=AuditLogs.SignIns)") \
| table search | return $search]
iseval = 0

# ================================== #
# Update below macros based on your environment #
Expand Down
15 changes: 15 additions & 0 deletions cyences_app_for_splunk/default/props.conf
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ EXTRACT-msgfield = msg=(?<msg>.*)rt=\d+
[o365:management:activity]
EVAL-action = case(isnotnull(action),action,(Operation == "UserLoginFailed"),"failure",(Operation == "UserLoggedIn"),"success")

[source::AuditLogs.SignIns]
FIELDALIAS-country = location.countryOrRegion AS org_country_code
FIELDALIAS-region = location.state AS org_region
FIELDALIAS-city = location.city AS org_city
FIELDALIAS-lat = location.geoCoordinates.latitude AS org_lat
FIELDALIAS-lon = location.geoCoordinates.longitude AS org_lon
FIELDALIAS-user = userPrincipalName AS user
FIELDALIAS-src = ipAddress AS src

EVAL-action = case(isnotnull(action),action, 'status.errorCode' != 0,"failure", 'status.errorCode' == 0,"success")
EVAL-app = "AzureActiveDirectory"

LOOKUP-cs_obj_changes = cs_o365_error_codes ErrorCode AS status.errorCode OUTPUT LogonError
LOOKUP-cs_country = cs_country_code code AS location.countryOrRegion OUTPUT org_country


######################
### Global Protect ###
Expand Down
Loading
Loading