From 010ce33a08a6af6af099fcfdbdf752291b1fc499 Mon Sep 17 00:00:00 2001 From: IndiaAce Date: Wed, 20 May 2026 12:52:18 -0400 Subject: [PATCH 1/2] Add first_name/last_name concat matching to org_vips body/subject rules Co-Authored-By: Claude Opus 4.6 --- .../fake_thread_suspicious_indicators.yml | 12 ++++- ...impersonation_google_groups_suspicious.yml | 18 ++++++-- .../service_abuse_trello_board_invite_vip.yml | 12 ++++- detection-rules/vip_impersonation_charity.yml | 12 ++++- .../vip_impersonation_fake_thread.yml | 44 +++++++++++++++---- detection-rules/vip_impersonation_subject.yml | 12 ++++- 6 files changed, 90 insertions(+), 20 deletions(-) diff --git a/detection-rules/fake_thread_suspicious_indicators.yml b/detection-rules/fake_thread_suspicious_indicators.yml index 295753711be..9b2ea42cb9b 100644 --- a/detection-rules/fake_thread_suspicious_indicators.yml +++ b/detection-rules/fake_thread_suspicious_indicators.yml @@ -119,8 +119,16 @@ source: | // body contains name of VIP ( - any($org_vips, strings.icontains(body.html.inner_text, .display_name)) - or any($org_vips, strings.icontains(body.plain.raw, .display_name)) + any($org_vips, + strings.icontains(body.html.inner_text, .display_name) + or strings.icontains(body.html.inner_text, strings.concat(.first_name, " ", .last_name)) + or strings.icontains(body.html.inner_text, strings.concat(.last_name, ", ", .first_name)) + ) + or any($org_vips, + strings.icontains(body.plain.raw, .display_name) + or strings.icontains(body.plain.raw, strings.concat(.first_name, " ", .last_name)) + or strings.icontains(body.plain.raw, strings.concat(.last_name, ", ", .first_name)) + ) ), // new body domain diff --git a/detection-rules/impersonation_google_groups_suspicious.yml b/detection-rules/impersonation_google_groups_suspicious.yml index ba96ff00b00..1cc729b99fb 100644 --- a/detection-rules/impersonation_google_groups_suspicious.yml +++ b/detection-rules/impersonation_google_groups_suspicious.yml @@ -9,10 +9,22 @@ source: | // subject, sender or reply to contains a VIP and ( any(headers.reply_to, - any($org_vips, strings.contains(.display_name, ..display_name)) + any($org_vips, + strings.contains(.display_name, ..display_name) + or strings.contains(strings.concat(.first_name, " ", .last_name), ..display_name) + or strings.contains(strings.concat(.last_name, ", ", .first_name), ..display_name) + ) + ) + or any($org_vips, + strings.contains(subject.subject, .display_name) + or strings.contains(subject.subject, strings.concat(.first_name, " ", .last_name)) + or strings.contains(subject.subject, strings.concat(.last_name, ", ", .first_name)) + ) + or 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($org_vips, strings.contains(subject.subject, .display_name)) - or any($org_vips, strings.contains(sender.display_name, .display_name)) ) and any(headers.hops, any(.fields, diff --git a/detection-rules/service_abuse_trello_board_invite_vip.yml b/detection-rules/service_abuse_trello_board_invite_vip.yml index 42b7b18c7c8..cd6b7513682 100644 --- a/detection-rules/service_abuse_trello_board_invite_vip.yml +++ b/detection-rules/service_abuse_trello_board_invite_vip.yml @@ -27,7 +27,11 @@ source: | // org_sld as the start of the board name with the org_vip as the sender any(html.xpath(body.html, '//h2').nodes, // org vip - any($org_vips, strings.icontains(..display_text, .display_name)) + any($org_vips, + strings.icontains(..display_text, .display_name) + or strings.icontains(..display_text, strings.concat(.first_name, " ", .last_name)) + or strings.icontains(..display_text, strings.concat(.last_name, ", ", .first_name)) + ) // org sld as the board name and any($org_slds, strings.icontains(..display_text, @@ -41,7 +45,11 @@ source: | ).nodes, strings.starts_with(.display_text, 'A note from ') and strings.iends_with(.display_text, 'From') - and any($org_vips, strings.icontains(..display_text, .display_name)) + and any($org_vips, + strings.icontains(..display_text, .display_name) + or strings.icontains(..display_text, strings.concat(.first_name, " ", .last_name)) + or strings.icontains(..display_text, strings.concat(.last_name, ", ", .first_name)) + ) ) ) attack_types: diff --git a/detection-rules/vip_impersonation_charity.yml b/detection-rules/vip_impersonation_charity.yml index 479b3e9a269..0bfc88f1006 100644 --- a/detection-rules/vip_impersonation_charity.yml +++ b/detection-rules/vip_impersonation_charity.yml @@ -17,8 +17,16 @@ source: | .name == "request" ) and ( - any($org_vips, strings.icontains(body.html.inner_text, .display_name)) - or any($org_vips, strings.icontains(body.plain.raw, .display_name)) + any($org_vips, + strings.icontains(body.html.inner_text, .display_name) + or strings.icontains(body.html.inner_text, strings.concat(.first_name, " ", .last_name)) + or strings.icontains(body.html.inner_text, strings.concat(.last_name, ", ", .first_name)) + ) + or any($org_vips, + strings.icontains(body.plain.raw, .display_name) + or strings.icontains(body.plain.raw, strings.concat(.first_name, " ", .last_name)) + or strings.icontains(body.plain.raw, strings.concat(.last_name, ", ", .first_name)) + ) ) and ( ( diff --git a/detection-rules/vip_impersonation_fake_thread.yml b/detection-rules/vip_impersonation_fake_thread.yml index 2e9ff32151b..c473abb4b9f 100644 --- a/detection-rules/vip_impersonation_fake_thread.yml +++ b/detection-rules/vip_impersonation_fake_thread.yml @@ -5,16 +5,42 @@ severity: "medium" source: | type.inbound and any($org_vips, - strings.icontains(body.html.display_text, - strings.concat("From: ", .display_name, " <") + ( + strings.icontains(body.html.display_text, + strings.concat("From: ", .display_name, " <") + ) + or strings.icontains(body.html.display_text, + strings.concat("From: ", strings.concat(.first_name, " ", .last_name), " <") + ) + or strings.icontains(body.html.display_text, + strings.concat("From: ", strings.concat(.last_name, ", ", .first_name), " <") + ) ) - and not strings.icontains(body.html.display_text, - strings.concat("From: ", - .display_name, - " <", - .email, - ">" - ) + and not ( + strings.icontains(body.html.display_text, + strings.concat("From: ", + .display_name, + " <", + .email, + ">" + ) + ) + or strings.icontains(body.html.display_text, + strings.concat("From: ", + strings.concat(.first_name, " ", .last_name), + " <", + .email, + ">" + ) + ) + or strings.icontains(body.html.display_text, + strings.concat("From: ", + strings.concat(.last_name, ", ", .first_name), + " <", + .email, + ">" + ) + ) ) ) and any([body.current_thread.text, body.html.display_text, body.plain.raw], diff --git a/detection-rules/vip_impersonation_subject.yml b/detection-rules/vip_impersonation_subject.yml index 1f233159dd6..e536cb5f41b 100644 --- a/detection-rules/vip_impersonation_subject.yml +++ b/detection-rules/vip_impersonation_subject.yml @@ -13,7 +13,11 @@ severity: "medium" source: | type.inbound and any($org_vips, - strings.contains(subject.subject, .display_name) + ( + strings.contains(subject.subject, .display_name) + or strings.contains(subject.subject, strings.concat(.first_name, " ", .last_name)) + or strings.contains(subject.subject, strings.concat(.last_name, ", ", .first_name)) + ) and strings.contains(.display_name, " ") ) // not being sent to said VIP @@ -23,7 +27,11 @@ source: | and all(recipients.to, any($org_vips, .email == ..email.email - and strings.contains(subject.subject, .display_name) + and ( + strings.contains(subject.subject, .display_name) + or strings.contains(subject.subject, strings.concat(.first_name, " ", .last_name)) + or strings.contains(subject.subject, strings.concat(.last_name, ", ", .first_name)) + ) and strings.contains(.display_name, " ") ) ) From 1658ad9fc984cdf4e2a8a85f6af83206ffd6dde1 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Wed, 20 May 2026 16:53:50 +0000 Subject: [PATCH 2/2] Auto-format MQL and add rule IDs --- .../fake_thread_suspicious_indicators.yml | 16 +++++++++--- ...impersonation_google_groups_suspicious.yml | 26 ++++++++++++++----- .../service_abuse_trello_board_invite_vip.yml | 22 +++++++++++++--- detection-rules/vip_impersonation_charity.yml | 17 ++++++++---- .../vip_impersonation_fake_thread.yml | 26 ++++++++++++++++--- detection-rules/vip_impersonation_subject.yml | 23 ++++++++++++---- 6 files changed, 101 insertions(+), 29 deletions(-) diff --git a/detection-rules/fake_thread_suspicious_indicators.yml b/detection-rules/fake_thread_suspicious_indicators.yml index 9b2ea42cb9b..29ebf13955d 100644 --- a/detection-rules/fake_thread_suspicious_indicators.yml +++ b/detection-rules/fake_thread_suspicious_indicators.yml @@ -121,13 +121,21 @@ source: | ( any($org_vips, strings.icontains(body.html.inner_text, .display_name) - or strings.icontains(body.html.inner_text, strings.concat(.first_name, " ", .last_name)) - or strings.icontains(body.html.inner_text, strings.concat(.last_name, ", ", .first_name)) + or strings.icontains(body.html.inner_text, + strings.concat(.first_name, " ", .last_name) + ) + or strings.icontains(body.html.inner_text, + strings.concat(.last_name, ", ", .first_name) + ) ) or any($org_vips, strings.icontains(body.plain.raw, .display_name) - or strings.icontains(body.plain.raw, strings.concat(.first_name, " ", .last_name)) - or strings.icontains(body.plain.raw, strings.concat(.last_name, ", ", .first_name)) + or strings.icontains(body.plain.raw, + strings.concat(.first_name, " ", .last_name) + ) + or strings.icontains(body.plain.raw, + strings.concat(.last_name, ", ", .first_name) + ) ) ), diff --git a/detection-rules/impersonation_google_groups_suspicious.yml b/detection-rules/impersonation_google_groups_suspicious.yml index 1cc729b99fb..e804d5ac21d 100644 --- a/detection-rules/impersonation_google_groups_suspicious.yml +++ b/detection-rules/impersonation_google_groups_suspicious.yml @@ -11,19 +11,31 @@ source: | any(headers.reply_to, any($org_vips, strings.contains(.display_name, ..display_name) - or strings.contains(strings.concat(.first_name, " ", .last_name), ..display_name) - or strings.contains(strings.concat(.last_name, ", ", .first_name), ..display_name) + or strings.contains(strings.concat(.first_name, " ", .last_name), + ..display_name + ) + or strings.contains(strings.concat(.last_name, ", ", .first_name), + ..display_name + ) ) ) or any($org_vips, strings.contains(subject.subject, .display_name) - or strings.contains(subject.subject, strings.concat(.first_name, " ", .last_name)) - or strings.contains(subject.subject, strings.concat(.last_name, ", ", .first_name)) + or strings.contains(subject.subject, + strings.concat(.first_name, " ", .last_name) + ) + or strings.contains(subject.subject, + strings.concat(.last_name, ", ", .first_name) + ) ) or 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 strings.contains(sender.display_name, + strings.concat(.first_name, " ", .last_name) + ) + or strings.contains(sender.display_name, + strings.concat(.last_name, ", ", .first_name) + ) ) ) and any(headers.hops, @@ -65,7 +77,7 @@ source: | ) ), - // reply-to is freemail + // reply-to is freemail any(headers.reply_to, .email.domain.domain in $free_email_providers), // reply-to is not in $recipient_emails diff --git a/detection-rules/service_abuse_trello_board_invite_vip.yml b/detection-rules/service_abuse_trello_board_invite_vip.yml index cd6b7513682..59bc3b3aa3b 100644 --- a/detection-rules/service_abuse_trello_board_invite_vip.yml +++ b/detection-rules/service_abuse_trello_board_invite_vip.yml @@ -29,8 +29,12 @@ source: | // org vip any($org_vips, strings.icontains(..display_text, .display_name) - or strings.icontains(..display_text, strings.concat(.first_name, " ", .last_name)) - or strings.icontains(..display_text, strings.concat(.last_name, ", ", .first_name)) + or strings.icontains(..display_text, + strings.concat(.first_name, " ", .last_name) + ) + or strings.icontains(..display_text, + strings.concat(.last_name, ", ", .first_name) + ) ) // org sld as the board name and any($org_slds, @@ -47,8 +51,18 @@ source: | and strings.iends_with(.display_text, 'From') and any($org_vips, strings.icontains(..display_text, .display_name) - or strings.icontains(..display_text, strings.concat(.first_name, " ", .last_name)) - or strings.icontains(..display_text, strings.concat(.last_name, ", ", .first_name)) + or strings.icontains(..display_text, + strings.concat(.first_name, + " ", + .last_name + ) + ) + or strings.icontains(..display_text, + strings.concat(.last_name, + ", ", + .first_name + ) + ) ) ) ) diff --git a/detection-rules/vip_impersonation_charity.yml b/detection-rules/vip_impersonation_charity.yml index 0bfc88f1006..43bdfbc89fe 100644 --- a/detection-rules/vip_impersonation_charity.yml +++ b/detection-rules/vip_impersonation_charity.yml @@ -19,13 +19,21 @@ source: | and ( any($org_vips, strings.icontains(body.html.inner_text, .display_name) - or strings.icontains(body.html.inner_text, strings.concat(.first_name, " ", .last_name)) - or strings.icontains(body.html.inner_text, strings.concat(.last_name, ", ", .first_name)) + or strings.icontains(body.html.inner_text, + strings.concat(.first_name, " ", .last_name) + ) + or strings.icontains(body.html.inner_text, + strings.concat(.last_name, ", ", .first_name) + ) ) or any($org_vips, strings.icontains(body.plain.raw, .display_name) - or strings.icontains(body.plain.raw, strings.concat(.first_name, " ", .last_name)) - or strings.icontains(body.plain.raw, strings.concat(.last_name, ", ", .first_name)) + or strings.icontains(body.plain.raw, + strings.concat(.first_name, " ", .last_name) + ) + or strings.icontains(body.plain.raw, + strings.concat(.last_name, ", ", .first_name) + ) ) ) and ( @@ -65,7 +73,6 @@ source: | or profile.by_sender().days_known > 30 ) and not profile.by_sender().any_messages_benign - attack_types: - "BEC/Fraud" tactics_and_techniques: diff --git a/detection-rules/vip_impersonation_fake_thread.yml b/detection-rules/vip_impersonation_fake_thread.yml index c473abb4b9f..651f1e24c41 100644 --- a/detection-rules/vip_impersonation_fake_thread.yml +++ b/detection-rules/vip_impersonation_fake_thread.yml @@ -10,10 +10,22 @@ source: | strings.concat("From: ", .display_name, " <") ) or strings.icontains(body.html.display_text, - strings.concat("From: ", strings.concat(.first_name, " ", .last_name), " <") + strings.concat("From: ", + strings.concat(.first_name, + " ", + .last_name + ), + " <" + ) ) or strings.icontains(body.html.display_text, - strings.concat("From: ", strings.concat(.last_name, ", ", .first_name), " <") + strings.concat("From: ", + strings.concat(.last_name, + ", ", + .first_name + ), + " <" + ) ) ) and not ( @@ -27,7 +39,10 @@ source: | ) or strings.icontains(body.html.display_text, strings.concat("From: ", - strings.concat(.first_name, " ", .last_name), + strings.concat(.first_name, + " ", + .last_name + ), " <", .email, ">" @@ -35,7 +50,10 @@ source: | ) or strings.icontains(body.html.display_text, strings.concat("From: ", - strings.concat(.last_name, ", ", .first_name), + strings.concat(.last_name, + ", ", + .first_name + ), " <", .email, ">" diff --git a/detection-rules/vip_impersonation_subject.yml b/detection-rules/vip_impersonation_subject.yml index e536cb5f41b..11222d92e31 100644 --- a/detection-rules/vip_impersonation_subject.yml +++ b/detection-rules/vip_impersonation_subject.yml @@ -15,8 +15,12 @@ source: | and any($org_vips, ( strings.contains(subject.subject, .display_name) - or strings.contains(subject.subject, strings.concat(.first_name, " ", .last_name)) - or strings.contains(subject.subject, strings.concat(.last_name, ", ", .first_name)) + or strings.contains(subject.subject, + strings.concat(.first_name, " ", .last_name) + ) + or strings.contains(subject.subject, + strings.concat(.last_name, ", ", .first_name) + ) ) and strings.contains(.display_name, " ") ) @@ -29,8 +33,18 @@ source: | .email == ..email.email and ( strings.contains(subject.subject, .display_name) - or strings.contains(subject.subject, strings.concat(.first_name, " ", .last_name)) - or strings.contains(subject.subject, strings.concat(.last_name, ", ", .first_name)) + or strings.contains(subject.subject, + strings.concat(.first_name, + " ", + .last_name + ) + ) + or strings.contains(subject.subject, + strings.concat(.last_name, + ", ", + .first_name + ) + ) ) and strings.contains(.display_name, " ") ) @@ -85,7 +99,6 @@ source: | ) or sender.email.domain.root_domain not in $high_trust_sender_root_domains ) - tags: - "Attack surface reduction" attack_types: