From ceec9f559e9c454e85a257469d8185e106e0fc17 Mon Sep 17 00:00:00 2001 From: Sublime Rule Testing Bot Date: Fri, 20 Sep 2024 20:38:15 +0000 Subject: [PATCH] Sync from PR#1936 Create Impersonation_vip_fake_thread_not_recip.yml by @zoomequipd https://github.com/sublime-security/sublime-rules/pull/1936 Source SHA 8e2f40ac1edf3eb261fb6d335b48937c37d9fdc0 Triggered by @zoomequipd --- ...mpersonation_vip_fake_thread_not_recip.yml | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 detection-rules/Impersonation_vip_fake_thread_not_recip.yml diff --git a/detection-rules/Impersonation_vip_fake_thread_not_recip.yml b/detection-rules/Impersonation_vip_fake_thread_not_recip.yml new file mode 100644 index 00000000000..f3c54f6c6c7 --- /dev/null +++ b/detection-rules/Impersonation_vip_fake_thread_not_recip.yml @@ -0,0 +1,183 @@ +name: "VIP Impersonation: Fake Thread with VIP Author not in Recipients from a New Sender" +description: "This rule is intended to detect fake threads that are impersonating a VIP. It looks for a previous thread matching $org_vips display name and email address and checks the VIP authoring the previous thread is not a current recipient and this message is from a suspicous sender" +type: "rule" +severity: "medium" +source: | + type.inbound + and any([body.current_thread.text, body.html.display_text, body.plain.raw], + // find threaded messages with a _few_ previous messages, but not too many + 3 <= sum([ + strings.icount(., "from:"), + strings.icount(., "to:"), + strings.icount(., "sent:"), + strings.icount(., "date:"), + strings.icount(., "cc:"), + strings.icount(., "subject:") + ] + ) < 60 + ) + // There is a previous thread which has been authored by a VIP + and any($org_vips, + ( + // without quotes around display_name + strings.icontains(body.html.display_text, + strings.concat("From: ", + .display_name, + " <", + .email, + ">" + ) + ) + // with single quotes around display_name + or strings.icontains(body.html.display_text, + strings.concat("From: \'", + .display_name, + "\' <", + .email, + ">" + ) + ) + // with quotes around display_name + or strings.icontains(body.html.display_text, + strings.concat("From: \"", + .display_name, + "\" <", + .email, + ">" + ) + ) + // with quotes, with mailto + or strings.icontains(body.html.display_text, + strings.concat("From: \"", + .display_name, + "\" [mailto:", + .email, + "]" + ) + ) + // without quotes, with mailto + or strings.icontains(body.html.display_text, + strings.concat("From: ", + .display_name, + " [mailto:", + .email, + "]" + ) + ) + // without quotes only email address + or strings.icontains(body.html.display_text, + strings.concat("From: ", .email) + ) + // with quotes only email address + or strings.icontains(body.html.display_text, + strings.concat("From: \"", .email) + ) + ) + ) + // and none of the recipients that authored a previous thread are in $org_vips + and not any([recipients.to, recipients.cc, recipients.bcc], + any(., // the recipient shows up as a previous sender in the thread + ( + // without quotes around display_name + strings.icontains(body.html.display_text, + strings.concat("From: ", + .display_name, + " <", + .email.email, + ">" + ) + ) + // with single quotes around display_name + or strings.icontains(body.html.display_text, + strings.concat("From: \'", + .display_name, + "\' <", + .email.email, + ">" + ) + ) + // with quotes around display_name + or strings.icontains(body.html.display_text, + strings.concat("From: \"", + .display_name, + "\" <", + .email.email, + ">" + ) + ) + // with quotes, with mailto + or strings.icontains(body.html.display_text, + strings.concat("From: \"", + .display_name, + "\" [mailto:", + .email.email, + "]" + ) + ) + // without quotes, with mailto + or strings.icontains(body.html.display_text, + strings.concat("From: ", + .display_name, + " [mailto:", + .email.email, + "]" + ) + ) + // without quotes only email address + or strings.icontains(body.html.display_text, + strings.concat("From: ", .email.email) + ) + // with quotes only email address + or strings.icontains(body.html.display_text, + strings.concat("From: \"", .email.email) + ) + // without quotes only display_name + or strings.icontains(body.html.display_text, + strings.concat("From: ", .display_name) + ) + // with quotes only display_namea + or strings.icontains(body.html.display_text, + strings.concat("From: \"", .display_name) + ) + ) + // and that recipeint is in the $org_vips + and any($org_vips, ..email.email == .email) + ) + ) + and ( + profile.by_sender().prevalence in ("new", "rare") + or not profile.by_sender().solicited + or profile.by_sender().days_known < 10 + ) + // negate org domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $org_domains + and not headers.auth_summary.dmarc.pass + ) + or sender.email.domain.root_domain not in $org_domains + ) + + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and not headers.auth_summary.dmarc.pass + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) + + and not profile.by_sender().any_false_positives +attack_types: + - "BEC/Fraud" +tactics_and_techniques: + - "Evasion" + - "Impersonation: VIP" + - "Social engineering" + - "Spoofing" +detection_methods: + - "Content analysis" + - "Sender analysis" +id: "36af5488-d10e-5b76-adaf-e0d0a0955aaa" +testing_pr: 1936 +testing_sha: 8e2f40ac1edf3eb261fb6d335b48937c37d9fdc0