Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
12 changes: 12 additions & 0 deletions detection-rules/impersonation_vip_bec_loose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ source: |
type.inbound
and any($org_vips,
0 <= strings.ilevenshtein(sender.display_name, .display_name) < 4
or 0 <= strings.ilevenshtein(sender.display_name,
strings.concat(.first_name,
" ",
.last_name
)
) < 4
or 0 <= strings.ilevenshtein(sender.display_name,
strings.concat(.last_name,
", ",
.first_name
)
) < 4
)
and any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "bec" and .confidence in ("medium", "high")
Expand Down
13 changes: 10 additions & 3 deletions detection-rules/impersonation_vip_invoicing_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ type: "rule"
severity: "high"
source: |
type.inbound
and any($org_vips, strings.contains(sender.display_name, .display_name))
and any($org_vips,
strings.contains(sender.display_name, .display_name)
or strings.contains(sender.display_name,
strings.concat(.first_name, " ", .last_name)
)
or strings.contains(sender.display_name,
strings.concat(.last_name, ", ", .first_name)
)
)
and (
(
sender.email.domain.domain in $org_domains
Expand All @@ -26,7 +34,7 @@ source: |
)
)

// and the reply to email address has never been contacted
// and the reply to email address has never been contacted
and any(headers.reply_to, .email.email not in $recipient_emails)

// negate highly trusted sender domains unless they fail DMARC authentication
Expand All @@ -37,7 +45,6 @@ source: |
)
or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

attack_types:
- "BEC/Fraud"
tactics_and_techniques:
Expand Down
6 changes: 5 additions & 1 deletion detection-rules/impersonation_vip_urgent_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ type: "rule"
severity: "high"
source: |
type.inbound
and any($org_vips, .display_name =~ sender.display_name)
and any($org_vips,
.display_name =~ sender.display_name
or strings.concat(.first_name, " ", .last_name) == sender.display_name
or strings.concat(.last_name, ", ", .first_name) == sender.display_name
)
and (
any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "bec" and .confidence in ("medium", "high")
Expand Down
10 changes: 9 additions & 1 deletion detection-rules/impersonation_vip_w2_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ severity: "high"
source: |
type.inbound
and (
any($org_vips, strings.contains(sender.display_name, .display_name))
any($org_vips,
strings.contains(sender.display_name, .display_name)
or strings.contains(sender.display_name,
strings.concat(.first_name, " ", .last_name)
)
or strings.contains(sender.display_name,
strings.concat(.last_name, ", ", .first_name)
)
)
or any(regex.extract(sender.display_name, '^(?<first>\S+)\s+(?<second>\S+)$'),
any($org_vips,
strings.contains(.display_name, ..named_groups["first"])
Expand Down
33 changes: 29 additions & 4 deletions detection-rules/vip_impersonation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,38 @@ source: |
type.inbound
and (
// the display name matches a name on the orgs vip list
any($org_vips, .display_name =~ sender.display_name)
any($org_vips,
.display_name =~ sender.display_name
or strings.concat(.first_name, " ", .last_name) == sender.display_name
or strings.concat(.last_name, ", ", .first_name) == sender.display_name
)
// or the display name starts with the name on the orgs vip list
or (
any($org_vips,
strings.istarts_with(sender.display_name, .display_name)
// and it is longer than just their name (eg. John Doe CEO)
and length(sender.display_name) > length(.display_name)
(
strings.istarts_with(sender.display_name, .display_name)
and length(sender.display_name) > length(.display_name)
)
or (
strings.istarts_with(sender.display_name,
strings.concat(.first_name, " ", .last_name)
)
and length(sender.display_name) > length(strings.concat(.first_name,
" ",
.last_name
)
)
)
or (
strings.istarts_with(sender.display_name,
strings.concat(.last_name, ", ", .first_name)
)
and length(sender.display_name) > length(strings.concat(.last_name,
", ",
.first_name
)
)
)
)
// and we have confidence it's BEC
and any(ml.nlu_classifier(body.current_thread.text).intents,
Expand Down
6 changes: 5 additions & 1 deletion insights/sender/sender_contains_org_vip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ type: "query"
source: |
type.inbound
and any($org_vips,
strings.icontains(sender.display_name, .display_name)
(
strings.icontains(sender.display_name, .display_name)
or strings.icontains(sender.display_name, strings.concat(.first_name, " ", .last_name))
or strings.icontains(sender.display_name, strings.concat(.last_name, ", ", .first_name))
)
and not sender.email.domain.root_domain in $high_trust_sender_root_domains
and not sender.email.domain.root_domain in $org_domains
and headers.auth_summary.dmarc.pass
Comment on lines 11 to 13
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these inside the any($org_vips) check?

Expand Down