BEC/Fraud: Self-addressed reply with unrelated link in ongoing thread
Flags messages where the sender appears to be replying to themselves within an established thread, but the first non-mailto link in the current message points to a domain unrelated to the sender and to any links seen in the previous thread history (accounting for Mimecast link wrapping). The rule confirms the sender was a genuine participant in prior thread messages and that no organizational recipients or domain matches exist in the earlier history, indicating a likely compromised external account being used to redirect the conversation via a newly introduced, unrelated link.
Sublime rule (View on GitHub)
1name: "BEC/Fraud: Self-addressed reply with unrelated link in ongoing thread"
2description: "Flags messages where the sender appears to be replying to themselves within an established thread, but the first non-mailto link in the current message points to a domain unrelated to the sender and to any links seen in the previous thread history (accounting for Mimecast link wrapping). The rule confirms the sender was a genuine participant in prior thread messages and that no organizational recipients or domain matches exist in the earlier history, indicating a likely compromised external account being used to redirect the conversation via a newly introduced, unrelated link."
3type: "rule"
4severity: "medium"
5source: |
6 type.inbound
7 // self sender behavior
8 and length(recipients.to) == 1
9 and length(recipients.cc) == 0
10 and sender.email.email == recipients.to[0].email.email
11
12 // the first link is not related to the sender
13 and filter(body.current_thread.links, .href_url.scheme != "mailto")[0].href_url.domain.root_domain != sender.email.domain.root_domain
14 // reply-to address (if present) is not related
15 and all(headers.reply_to,
16 filter(body.current_thread.links, .href_url.scheme != "mailto")[0].href_url.domain.root_domain != .email.domain.root_domain
17 )
18 and length(body.previous_threads) > 1
19
20 // the first link's domain does not appears in a previous thread's links
21 and not any(body.previous_threads,
22 any(.links,
23 // current link IS mimecast rewritten
24 (
25 filter(body.current_thread.links,
26 .href_url.scheme != "mailto"
27 )[0].href_url.domain.root_domain in (
28 "mimecastprotect.com",
29 "mimecast.com"
30 )
31 and (
32 // the previous thread is also rewritten
33 strings.parse_domain(.href_url.query_params_decoded['domain'][0]
34 ).root_domain == strings.parse_domain(filter(body.current_thread.links,
35 .href_url.scheme != "mailto"
36 )[0].href_url.query_params_decoded['domain'][0]
37 ).root_domain
38 // or the preiovus thread is not rewritten
39 or .href_url.domain.root_domain == strings.parse_domain(filter(body.current_thread.links,
40 .href_url.scheme != "mailto"
41 )[0].href_url.query_params_decoded['domain'][0]
42 ).root_domain
43 )
44 )
45 // current link is NOT mimecast rewritten
46 or (
47 // but the previous thread is mimecast rewritten
48 strings.parse_domain(.href_url.query_params_decoded['domain'][0]
49 ).root_domain == filter(body.current_thread.links,
50 .href_url.scheme != "mailto"
51 )[0].href_url.domain.root_domain
52 // neither are mimecast rewritten
53 or .href_url.domain.root_domain == filter(body.current_thread.links,
54 .href_url.scheme != "mailto"
55 )[0].href_url.domain.root_domain
56 )
57 )
58 )
59
60 // none of the previous threads
61 and not any(body.previous_threads,
62 // the subjet has been changed
63 .subject.base =~ subject.base
64 // none of the previous corrispondents are in the org_domains
65 or any(flatten([.recipients.to, .recipients.bcc, .recipients.cc]),
66 .email.domain.domain in $org_domains
67 )
68 or .sender.email.domain.domain in $org_domains
69 )
70
71 // there is more than a single particiapte in the previous threads (by email and display_name)
72 and length(filter(flatten([
73 // pull all the sender emails from previous threads
74 map(body.previous_threads, .sender),
75 // get all the recipients from the previous threads
76 flatten(map(body.previous_threads, .recipients.to, )
77 )
78 ]
79 ),
80 // remove entries that have no email or display name
81 .email.email != ""
82 // remove enties that match the sender display name
83 and not strings.icontains(sender.display_name, .display_name)
84 // remove entires that match the sender email
85 and sender.email.email != .email.email
86 // we are left with all the entries that are unrelated to the sender, there should be more than 0
87 )
88 ) > 0
89tags:
90 - "Attack surface reduction"
91attack_types:
92 - "BEC/Fraud"
93 - "Credential Phishing"
94tactics_and_techniques:
95 - "Social engineering"
96 - "Out of band pivot"
97detection_methods:
98 - "URL analysis"
99 - "Header analysis"
100 - "Sender analysis"
101 - "Content analysis"
102id: "7d8cd472-97b1-5088-92fe-5174c19719d7"
Related rules
- ClickFix: Clipboard hijack lure with copy-paste-to-terminal instruction
- Link: Self-sender with sender org in subject and credential theft indicator
- Attachment: PDF with suspicious HeadlessChrome metadata
- Body: AI-generated invoice template artifacts
- Sender: Local part built from recipient domain and mailbox