Skip to content

Commit 3f37631

Browse files
authored
Merge branch 'develop' into innoloader
2 parents 6541bc7 + 71c6916 commit 3f37631

8 files changed

+345
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Zoom High Video Latency
2+
id: 6ad6b548-adfa-452c-aa77-9ff94877e832
3+
version: 1
4+
date: '2025-06-02'
5+
author: Marissa Bower, Raven Tait
6+
status: experimental
7+
type: Anomaly
8+
description: Detects particularly high latency from Zoom logs. Latency observed from threat actors
9+
performing Remote Employment Fraud (REF) is typically well above what’s normal for the majority of employees.
10+
data_source: []
11+
search: '`zoom_index`
12+
| spath "payload.object.participant.qos{}.type"
13+
| search "payload.object.participant.qos{}.type"=video_input
14+
| rename payload.object.participant.qos{}.details.avg_latency as avg_latency "payload.object.participant.qos{}.details.latency" as latency payload.object.participant.email as email
15+
| rex field=avg_latency "(?<average_latency>\d+) ms"
16+
| rex field=latency "(?<overall_latency>\d+) ms"
17+
| search email="*"
18+
| table email overall_latency latency avg_latency average_latency _raw
19+
| stats latest(overall_latency) as overall_latency by email _raw
20+
| where overall_latency>300 | `zoom_high_video_latency_filter`'
21+
how_to_implement: The analytic leverages Zoom logs to be ingested using
22+
Splunk Connect for Zoom (https://splunkbase.splunk.com/app/4961)
23+
known_false_positives: While latency could simply indicate a slow network connection, when combined
24+
with other indicators, it can help build a more complete picture. Tune the threshold as needed for
25+
your environment baseline.
26+
drilldown_searches:
27+
- name: View the detection results for - "$email$"
28+
search: '%original_detection_search% | search payload.object.participant.email = "$email$"'
29+
earliest_offset: $info_min_time$
30+
latest_offset: $info_max_time$
31+
- name: View risk events for the last 7 days for - "$email$"
32+
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$email$")
33+
starthoursago=168 | stats count min(_time) as firstTime max(_time) as lastTime
34+
values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories)
35+
as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic)
36+
as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)`
37+
| `security_content_ctime(lastTime)`'
38+
earliest_offset: $info_min_time$
39+
latest_offset: $info_max_time$
40+
rba:
41+
message: Suspicious latency from $email$ in Zoom activity.
42+
risk_objects:
43+
- field: email
44+
type: user
45+
score: 39
46+
threat_objects: []
47+
tags:
48+
analytic_story:
49+
- Remote Employment Fraud
50+
asset_type: Identity
51+
mitre_attack_id:
52+
- T1078
53+
product:
54+
- Splunk Enterprise
55+
- Splunk Enterprise Security
56+
- Splunk Cloud
57+
security_domain: identity
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Zoom Rare Audio Devices
2+
id: 9fdbf709-4c46-4819-9fb6-98b2d72059ed
3+
version: 1
4+
date: '2025-06-02'
5+
author: Marissa Bower, Raven Tait
6+
status: experimental
7+
type: Hunting
8+
description: Detects rare audio devices from Zoom logs. Actors performing Remote Employment
9+
Fraud (REF) typically use unusual device information compared to a majority of employees.
10+
Detecting this activity requires careful analysis, regular review, and a thorough
11+
understanding of the audio and video devices commonly used within your environment.
12+
data_source: []
13+
search: '`zoom_index` speaker=* NOT (camera=*iPhone* OR camera="*FaceTime*"
14+
OR speaker="*AirPods*" OR camera="*MacBook*" OR microphone="*MacBook Pro Microphone*")
15+
| rare speaker limit=50 | `zoom_rare_audio_devices_filter`'
16+
how_to_implement: The analytic leverages Zoom logs to be ingested using
17+
Splunk Connect for Zoom (https://splunkbase.splunk.com/app/4961)
18+
known_false_positives: This is a hunting query meant to identify rare audio devices.
19+
tags:
20+
analytic_story:
21+
- Remote Employment Fraud
22+
asset_type: Identity
23+
mitre_attack_id:
24+
- T1123
25+
product:
26+
- Splunk Enterprise
27+
- Splunk Enterprise Security
28+
- Splunk Cloud
29+
security_domain: identity
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Zoom Rare Input Devices
2+
id: d290eeef-d05e-49a8-b598-72296023b87b
3+
version: 1
4+
date: '2025-06-02'
5+
author: Marissa Bower, Raven Tait
6+
status: experimental
7+
type: Hunting
8+
description: Detects rare input devices from Zoom logs. Actors performing Remote Employment
9+
Fraud (REF) typically use unusual device information compared to a majority of employees.
10+
Detecting this activity requires careful analysis, regular review, and a thorough
11+
understanding of the audio and video devices commonly used within your environment.
12+
data_source: []
13+
search: '`zoom_index` microphone=* NOT (camera=*iPhone* OR camera="*FaceTime*"
14+
OR speaker="*AirPods*" OR camera="*MacBook*" OR microphone="*MacBook Pro Microphone*")
15+
| rare microphone limit=50 | `zoom_rare_input_devices_filter`'
16+
how_to_implement: The analytic leverages Zoom logs to be ingested using
17+
Splunk Connect for Zoom (https://splunkbase.splunk.com/app/4961)
18+
known_false_positives: This is a hunting query meant to identify rare microphone devices.
19+
tags:
20+
analytic_story:
21+
- Remote Employment Fraud
22+
asset_type: Identity
23+
mitre_attack_id:
24+
- T1123
25+
product:
26+
- Splunk Enterprise
27+
- Splunk Enterprise Security
28+
- Splunk Cloud
29+
security_domain: identity
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Zoom Rare Video Devices
2+
id: 9b2b819d-c76b-4dc6-bd3d-148edb8de83e
3+
version: 1
4+
date: '2025-06-02'
5+
author: Marissa Bower, Raven Tait
6+
status: experimental
7+
type: Hunting
8+
description: Detects rare video devices from Zoom logs. Actors performing Remote Employment
9+
Fraud (REF) typically use unusual device information compared to a majority of employees.
10+
Detecting this activity requires careful analysis, regular review, and a thorough
11+
understanding of the audio and video devices commonly used within your environment.
12+
data_source: []
13+
search: '`zoom_index` camera=* NOT (camera=*iPhone* OR camera="*FaceTime*"
14+
OR speaker="*AirPods*" OR camera="*MacBook*" OR microphone="*MacBook Pro Microphone*")
15+
| rare camera limit=50 | `zoom_rare_video_devices_filter`'
16+
how_to_implement: The analytic leverages Zoom logs to be ingested using
17+
Splunk Connect for Zoom (https://splunkbase.splunk.com/app/4961)
18+
known_false_positives: This is a hunting query meant to identify rare video devices.
19+
tags:
20+
analytic_story:
21+
- Remote Employment Fraud
22+
asset_type: Identity
23+
mitre_attack_id:
24+
- T1123
25+
product:
26+
- Splunk Enterprise
27+
- Splunk Enterprise Security
28+
- Splunk Cloud
29+
security_domain: identity
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Geographic Improbable Location
2+
id: 64f91df1-49ec-46aa-81bd-2282d3cea765
3+
version: 1
4+
date: '2025-06-03'
5+
author: Marissa Bower, Raven Tait
6+
status: experimental
7+
type: Anomaly
8+
description: Geolocation data can be inaccurate or easily spoofed by Remote Employment Fraud (REF) workers.
9+
REF actors sometimes slip up and reveal their true location, creating what we call 'improbable travel'
10+
scenarios — logins from opposite sides of the world within minutes. This identifies situations where these
11+
travel scenarios occur.
12+
data_source:
13+
- Okta
14+
search: '| tstats summariesonly=true values(Authentication.app) as app from datamodel=Authentication.Authentication
15+
where (`okta` OR (index="firewall" AND sourcetype="pan:globalprotect"))
16+
AND Authentication.action="success" AND Authentication.app IN ("Workday", "Slack", "*GlobalProtect", "Jira*",
17+
"Atlassian Cloud", "Zoom") AND NOT Authentication.user="unknown" by _time index sourcetype host Authentication.user
18+
Authentication.src span=1s
19+
| `drop_dm_object_name("Authentication")`
20+
| fields user,src,app,_time,count,host
21+
| eval user=lower(replace(user, "((^.*\\\)|(@.*$))", ""))
22+
| join type=outer user
23+
[| inputlookup identity_lookup_expanded where user_status=active
24+
| rex field=email "^(?<user>[a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$"
25+
| rename email as user_email bunit as user_bunit priority as user_priority work_country as user_work_country work_city as user_work_city
26+
| fields user user_email user_bunit user_priority user_work_country user_work_city]
27+
| eventstats dc(src) as src_count by user
28+
| eventstats dc(user) as user_count by src
29+
| sort 0 + _time
30+
| iplocation src
31+
| lookup local=true asn_lookup_by_cidr ip as src OUTPUT ip asn description
32+
| eval session_lat=if(isnull(src_lat), lat, src_lat), session_lon=if(isnull(src_long), lon, src_long),
33+
session_city=if(isnull(src_city), City, src_city), session_country=if(isnull(src_country), Country, src_country),
34+
session_region=if(isnull(src_region), Region, src_region)
35+
| eval session_city=if(isnull(session_city) OR match(session_city,"^\s+|^$"), null(), session_city),
36+
session_country=if(isnull(session_country) OR match(session_country,"^\s+|^$"), null(), session_country),
37+
session_region=if(isnull(session_region) OR match(session_region,"^\s+|^$"), null(), session_region)
38+
| where isnotnull(session_lat) and isnotnull(session_lon)
39+
| eval session_city=if(isnull(session_city),"-",session_city), session_country=if(isnull(session_country),"-",session_country),
40+
session_region=if(isnull(session_region),"-",session_region)
41+
| streamstats current=t window=2 earliest(session_region) as prev_region,earliest(session_lat) as prev_lat,
42+
earliest(session_lon) as prev_lon, earliest(session_city) as prev_city, earliest(session_country) as prev_country,
43+
earliest(_time) as prev_time, earliest(src) as prev_src, latest(user_bunit) as user_bunit,
44+
earliest(app) as prev_app values(user_work_country) as user_work_country by user
45+
| where (src!=prev_src) AND !(prev_city=session_city AND prev_country=session_country) AND ((isnotnull(prev_city)
46+
AND isnotnull(session_city)) OR prev_country!=session_country)
47+
| `globedistance(session_lat,session_lon,prev_lat,prev_lon,"m")`
48+
| eval time_diff=if((_time-prev_time)==0, 1, _time - prev_time)
49+
| eval speed = round(distance*3600/time_diff,2)
50+
| eval distance= round(distance,2)
51+
| eval user_work_country=case(user_work_country="usa","United States", user_work_country="cze","Czechia",
52+
user_work_country="pol","Poland", user_work_country="ind","India", user_work_country="fra","France",
53+
user_work_country="can","Canada", user_work_country="mys","Malaysia", user_work_country="kor","South Korea",
54+
user_work_country="aus","Australia", user_work_country="bel","Belgium", user_work_country="dnk","Denmark",
55+
user_work_country="bra","Brazil", user_work_country="deu","Germany", user_work_country="jpn","Japan",
56+
user_work_country="che","Switzerland", user_work_country="swe","Sweden", user_work_country="zaf","South Africa",
57+
user_work_country="irl","Ireland", user_work_country="ita","Italy", user_work_country="nor","Norway",
58+
user_work_country="gbr","United Kingdom", user_work_country="hkg","Hong Kong", user_work_country="chn","China",
59+
user_work_country="esp","Spain", user_work_country="nld", "Netherlands", user_work_country="twn","Taiwan",
60+
user_work_country="est","Estonia", user_work_country="sgp","Singapore", user_work_country="are","United Arab Emirates", 1=1,"N/A")
61+
| lookup local=true asn_lookup_by_cidr ip as prev_src OUTPUT ip as prev_ip asn as prev_asn description as prev_description
62+
| eval suspect=if(!user_work_country==session_country,"Sketchy","Normal")
63+
| search (speed>500 AND distance>750)
64+
| table _time,prev_time,user,host,src,prev_src,app,prev_app,distance,speed,suspect,session_city,session_region,
65+
session_country,prev_city,prev_region,prev_country,user_priority,user_work_*,prev_ip,ip,asn,prev_asn,prev_description,description
66+
| rename _time as event_time
67+
| convert ctime(event_time) timeformat="%Y-%m-%d %H:%M:%S"
68+
| convert ctime(prev_time) timeformat="%Y-%m-%d %H:%M:%S"
69+
| eval problem=if(!session_country==prev_country AND (!session_country==user_work_country),"Yes","Nope")
70+
| search NOT (prev_city="-" OR session_city="-") AND NOT
71+
[inputlookup known_devices_public_ip_filter.csv
72+
| fields ip
73+
| rename ip as src]
74+
| dedup user host prev_src src
75+
| fillnull value="N/A"
76+
| search problem="Yes"| `geographic_improbable_location_filter`'
77+
how_to_implement: The analytic leverages Okta OktaIm2 logs to be ingested using the
78+
Splunk Add-on for Okta Identity Cloud (https://splunkbase.splunk.com/app/6553). This also utilizes
79+
Splunk Enterprise Security Suite for several macros and lookups. The known_devices_public_ip_filter
80+
lookup is a placeholder for known public edge devices in your network.
81+
known_false_positives: Legitimate usage of some VPNs may cause false positives. Tune as needed.
82+
drilldown_searches:
83+
- name: View the detection results for - "$user$"
84+
search: '%original_detection_search% | search Authentication.user = "$user$"'
85+
earliest_offset: $info_min_time$
86+
latest_offset: $info_max_time$
87+
- name: View risk events for the last 7 days for - "$user$"
88+
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$user$")
89+
starthoursago=168 | stats count min(_time) as firstTime max(_time) as lastTime
90+
values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories)
91+
as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic)
92+
as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)`
93+
| `security_content_ctime(lastTime)`'
94+
earliest_offset: $info_min_time$
95+
latest_offset: $info_max_time$
96+
rba:
97+
message: Improbable travel speed between locations observed for $user$.
98+
risk_objects:
99+
- field: user
100+
type: user
101+
score: 50
102+
threat_objects: []
103+
tags:
104+
analytic_story:
105+
- Remote Employment Fraud
106+
asset_type: Identity
107+
mitre_attack_id:
108+
- T1078
109+
product:
110+
- Splunk Enterprise
111+
- Splunk Enterprise Security
112+
- Splunk Cloud
113+
security_domain: identity
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Okta Non-Standard VPN Usage
2+
id: 58eb9f80-896c-42f8-86c6-27ab59026c9c
3+
version: 1
4+
date: '2025-06-03'
5+
author: Marissa Bower, Raven Tait
6+
status: experimental
7+
type: TTP
8+
description: Remote Employment Fraud (REF) actors will often use virtual private networks (VPNs) to conceal their
9+
true physical location. Threat actors mask their originating IP address and instead appear to be situated in
10+
any location where the VPN service has a node.
11+
data_source:
12+
- Okta
13+
search: '`okta` debugContext.debugData.tunnels IN (*Astrill*,*Azire*,*CyberGhost*,*Express*VPN,*HideMe*,
14+
*IPVanish*,*Mullvad*,*Nord*VPN*,*OVPN*,*PIA*VPN*,*Proton*VPN*,*Pure*VPN*,*Slick*VPN*,*Surf*Easy*,
15+
*SurfShark*,*Star*VPN*,*TorGuard*,*TorProxy*,*Tiger*VPN*,*TunnelBear*,*Unblock*VPN*,*Warp*VPN*,*WarpSpeed*,
16+
*VPNReactor*,*VPN*Shield*,*VPN*Super*VPN*,*ZenMate*) ```listing of commonly used known VPN providers. Add or remove whatever is appropriate for your environment```
17+
| eval user=coalesce(''actor.alternateId'',user), user=mvindex(split(user, "@"), 0)
18+
| rename targetUserAlternateId as user client.* as * request.* as * ipChain{}.* as * geographicalContext.* as * debugContext.* as * debugData.* as *
19+
| eval status=case(match(_raw, "FAILURE"), "failure", !match(_raw, "FAILURE"), "success")
20+
| stats count values(status) as status max(published) as UTC min(_time) as firsttime max(_time) as lasttime values(target_data) as target_data values(displayMessage) as displayMessage values(eventType) as eventType values(city) as city values(country) as country values(action) as action values(src_ip) as src_ip values(outcome.*) as * values(user) as user by tunnels,_time,host sourcetype index
21+
| fillnull value="N/A"
22+
| convert ctime(*ttime)
23+
| `okta_non_standard_vpn_usage_filter`'
24+
how_to_implement: The analytic leverages Okta OktaIm2 logs to be ingested using the
25+
Splunk Add-on for Okta Identity Cloud (https://splunkbase.splunk.com/app/6553).
26+
known_false_positives: Limited to no expected false positives once a baseline of common VPN software has been completed.
27+
drilldown_searches:
28+
- name: View the detection results for - "$user$"
29+
search: '%original_detection_search% | search actor.alternateId = "$user$"'
30+
earliest_offset: $info_min_time$
31+
latest_offset: $info_max_time$
32+
- name: View risk events for the last 7 days for - "$user$"
33+
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$user$")
34+
starthoursago=168 | stats count min(_time) as firstTime max(_time) as lastTime
35+
values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories)
36+
as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic)
37+
as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)`
38+
| `security_content_ctime(lastTime)`'
39+
earliest_offset: $info_min_time$
40+
latest_offset: $info_max_time$
41+
rba:
42+
message: Uncommon VPN software used by $user$ to connect to Okta.
43+
risk_objects:
44+
- field: user
45+
type: user
46+
score: 50
47+
threat_objects: []
48+
tags:
49+
analytic_story:
50+
- Remote Employment Fraud
51+
- Suspicious Okta Activity
52+
asset_type: Identity
53+
mitre_attack_id:
54+
- T1078
55+
- T1572
56+
- T1090
57+
product:
58+
- Splunk Enterprise
59+
- Splunk Enterprise Security
60+
- Splunk Cloud
61+
security_domain: identity

macros/zoom_index.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
definition: index=zoom
2+
description: customer specific splunk configurations(eg- index, source, sourcetype).
3+
Replace the macro definition with configurations for your Splunk Environment.
4+
name: zoom_index
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Remote Employment Fraud
2+
id: 81a785e2-1046-44ea-80d7-badf381aa49a
3+
version: 1
4+
status: production
5+
date: '2025-06-02'
6+
author: Raven Tait
7+
description: Fortify your insider threat monitoring with searches that monitor for and help you
8+
investigate possible remote employment fraud.
9+
narrative: Remote employment fraud involves threat actors posing as job seekers or employers to
10+
gain unauthorized access to organizations, often using fake or stolen identities. This can result
11+
in insider threats, data breaches, financial loss, and reputational damage, as attackers exploit
12+
remote onboarding processes to infiltrate systems or harvest sensitive information. Strong
13+
identity verification, background checks, and ongoing monitoring are critical to mitigating
14+
these risks.
15+
references: []
16+
tags:
17+
category:
18+
- Adversary Tactics
19+
product:
20+
- Splunk Enterprise
21+
- Splunk Enterprise Security
22+
- Splunk Cloud
23+
usecase: Insider Threat

0 commit comments

Comments
 (0)