Fake thread with suspicious indicators
Fake thread contains suspicious indicators, which can lead to BEC, credential phishing, and other undesirable outcomes.
Sublime rule (View on GitHub)
1name: "Fake thread with suspicious indicators"
2description: "Fake thread contains suspicious indicators, which can lead to BEC, credential phishing, and other undesirable outcomes."
3type: "rule"
4severity: "medium"
5source: |
6 type.inbound
7 // fake thread check
8 and (length(headers.references) == 0 or headers.in_reply_to is null)
9 and (
10 subject.is_reply
11 or subject.is_forward
12 // fake thread, but no indication in the subject line
13 // current_thread pulls the recent thread, but the full body contains the fake "original" email
14 or (
15 not (subject.is_reply or subject.is_forward)
16 and any([body.current_thread.text, body.html.display_text, body.plain.raw],
17 3 of (
18 strings.icontains(., "from:"),
19 strings.icontains(., "to:"),
20 strings.icontains(., "sent:"),
21 strings.icontains(., "date:"),
22 strings.icontains(., "cc:"),
23 strings.icontains(., "subject:")
24 )
25 )
26 and length(body.current_thread.text) + 100 < length(coalesce(body.html.display_text,
27 body.plain.raw
28 )
29 )
30 )
31 )
32
33 // negating bouncebacks
34 and not any(attachments,
35 .content_type in ("message/delivery-status", "message/rfc822")
36 )
37 // negating Google Calendar invites
38 and (
39 (
40 headers.return_path.domain.domain is not null
41 and headers.return_path.domain.domain != 'calendar-server.bounces.google.com'
42 )
43 or headers.return_path.domain.domain is null
44 )
45 // not mimecast secure message from internal source
46 and not (
47 strings.istarts_with(headers.message_id, '<Mimecast.')
48 and strings.iends_with(headers.message_id, '.mimecast.lan>')
49 and headers.hops[0].received.server.raw == "relay.mimecast.com"
50 and strings.icontains(headers.hops[0].received.source.raw, 'mimecast.lan')
51 )
52
53 // and not solicited
54 and not profile.by_sender().solicited
55 and 4 of (
56 // language attempting to engage
57 (
58 any(ml.nlu_classifier(body.current_thread.text).entities,
59 .name == "request"
60 )
61 and any(ml.nlu_classifier(body.current_thread.text).entities,
62 .name == "financial"
63 )
64 ),
65
66 // invoicing language
67 (
68 any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice")
69 or any(ml.nlu_classifier(body.current_thread.text).entities,
70 .text == "invoice"
71 )
72 ),
73
74 // urgency request
75 any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency"),
76
77 // cred_theft detection
78 any(ml.nlu_classifier(body.current_thread.text).intents,
79 .name == "cred_theft" and .confidence in~ ("medium", "high")
80 ),
81
82 // subject has multiple re: tags and suspicious indicators
83 (
84 regex.icontains(subject.subject, '\bre:\s+re:')
85 and (
86 regex.icontains(subject.base,
87 '(?:action.{0,10}required|invest(?:ment|ing)?|enforcement|opportunit|urgent|verif|confirm|suspend|terminat)'
88 )
89 )
90 ),
91
92 // commonly abused sender TLD
93 strings.ilike(sender.email.domain.tld, "*.jp"),
94
95 // headers traverse abused TLD
96 any(headers.domains, strings.ilike(.tld, "*.jp")),
97
98 // known suspicious pattern in the URL path
99 any(body.links, regex.match(.href_url.path, '\/[a-z]{3}\d[a-z]')),
100
101 // link display text is in all caps
102 any(body.links, regex.match(.display_text, '[A-Z ]+')),
103
104 // link display text contains invisible characters (U+200F)
105 any(body.links, strings.contains(.display_text, "\u{200F}")),
106
107 // Low reputation link with display text ending in a document extension
108 any(body.links,
109 .href_url.domain.root_domain not in $tranco_1m
110 and .href_url.domain.valid
111 and .href_url.domain.root_domain not in $org_domains
112 and .href_url.domain.root_domain not in $high_trust_sender_root_domains
113 and (
114 any($file_extensions_macros, strings.ends_with(..display_text, .))
115 or strings.ends_with(.display_text, 'pdf')
116 )
117 ),
118
119 // display name contains an email
120 regex.contains(sender.display_name, '[a-z0-9]+@[a-z]+'),
121
122 // Sender domain is empty
123 sender.email.domain.domain == "",
124
125 // sender domain matches no body domains
126 all(body.links,
127 .href_url.domain.root_domain != sender.email.domain.root_domain
128 ),
129
130 // body contains name of VIP
131 (
132 any($org_vips, strings.icontains(body.html.inner_text, .display_name))
133 or any($org_vips, strings.icontains(body.plain.raw, .display_name))
134 ),
135
136 // new body domain
137 any(body.links, network.whois(.href_url.domain).days_old < 30),
138
139 // new sender domain
140 network.whois(sender.email.domain).days_old < 30,
141
142 // new sender
143 profile.by_sender().days_known < 7,
144
145 // excessive whitespace
146 (
147 regex.icontains(body.html.raw, '((<br\s*/?>\s*){20,}|\n{20,})')
148 or regex.icontains(body.html.raw, '(<p[^>]*>\s*<br\s*/?>\s*</p>\s*){30,}')
149 or regex.icontains(body.html.raw,
150 '(<p class=".*?"><span style=".*?"><o:p> </o:p></span></p>\s*){30,}'
151 )
152 or regex.icontains(body.html.raw, '(<p> </p>\s*){7,}')
153 or regex.icontains(body.html.raw, '(<p> </p><br>\s*){7,}')
154 or regex.icontains(body.html.raw, '(<p[^>]*>\s* <br>\s*</p>\s*){5,}')
155 or regex.icontains(body.html.raw, '(<p[^>]*> </p>\s*){7,}')
156 ),
157
158 // body contains recipient SLD
159 any(recipients.to,
160 strings.icontains(body.current_thread.text, .email.domain.sld)
161 ),
162 (
163 // bec
164 any(ml.nlu_classifier(body.current_thread.text).intents,
165 .name == "bec" and .confidence != "low"
166 )
167 // previous thread contains matching domain but mismatch local part in current thread
168 and any(body.previous_threads,
169 .sender.email.domain.root_domain == recipients.to[0].email.domain.root_domain
170 and .sender.email.email != recipients.to[0].email.email
171 )
172 )
173 )
174
175 // negate highly trusted sender domains unless they fail DMARC authentication
176 and (
177 (
178 sender.email.domain.root_domain in $high_trust_sender_root_domains
179 and not headers.auth_summary.dmarc.pass
180 )
181 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
182 )
183 and not profile.by_sender().any_messages_benign
184tags:
185 - "Attack surface reduction"
186attack_types:
187 - "BEC/Fraud"
188 - "Credential Phishing"
189 - "Spam"
190tactics_and_techniques:
191 - "Evasion"
192 - "Social engineering"
193detection_methods:
194 - "Content analysis"
195 - "Header analysis"
196 - "Natural Language Understanding"
197 - "Sender analysis"
198id: "c2e18a57-1f52-544f-bb6d-a578e286cf89"
Related rules
- HTML content with print styling and credential theft language
- BEC/Fraud: Fake investment outreach from suspicious TLD
- Attachment: PDF with recipient email in link
- Attachment: PDF with self-service platform links with self sender or blank recipients
- Spam: Default Microsoft Exchange Online sender domain (onmicrosoft.com)