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, body.plain.raw))
27
28 )
29 )
30
31 // negating bouncebacks
32 and not any(attachments,
33 .content_type in ("message/delivery-status", "message/rfc822")
34 )
35 // negating Google Calendar invites
36 and (
37 (
38 headers.return_path.domain.domain is not null
39 and headers.return_path.domain.domain != 'calendar-server.bounces.google.com'
40 )
41 or headers.return_path.domain.domain is null
42 )
43
44 and (
45 length(headers.references) == 0
46 or headers.in_reply_to is null
47 )
48
49 // and not solicited
50 and not profile.by_sender().solicited
51 and 4 of (
52 // language attempting to engage
53 (
54 any(ml.nlu_classifier(body.current_thread.text).entities,
55 .name == "request"
56 )
57 and any(ml.nlu_classifier(body.current_thread.text).entities,
58 .name == "financial"
59 )
60 ),
61
62 // invoicing language
63 (
64 any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice")
65 or any(ml.nlu_classifier(body.current_thread.text).entities,
66 .text == "invoice"
67 )
68 ),
69
70 // urgency request
71 any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency"),
72
73 // cred_theft detection
74 any(ml.nlu_classifier(body.current_thread.text).intents,
75 .name == "cred_theft" and .confidence in~ ("medium", "high")
76 ),
77
78 // commonly abused sender TLD
79 strings.ilike(sender.email.domain.tld, "*.jp"),
80
81 // headers traverse abused TLD
82 any(headers.domains, strings.ilike(.tld, "*.jp")),
83
84 // known suspicious pattern in the URL path
85 any(body.links, regex.match(.href_url.path, '\/[a-z]{3}\d[a-z]')),
86
87 // link display text is in all caps
88 any(body.links, regex.match(.display_text, '[A-Z ]+')),
89
90 // link display text contains invisible characters (U+200F)
91 any(body.links, strings.contains(.display_text, "\u{200F}")),
92
93 // Low reputation link with display text ending in a document extension
94 any(body.links,
95 .href_url.domain.root_domain not in $tranco_1m
96 and .href_url.domain.valid
97 and .href_url.domain.root_domain not in $org_domains
98 and .href_url.domain.root_domain not in $high_trust_sender_root_domains
99 and (
100 any($file_extensions_macros, strings.ends_with(..display_text, .))
101 or strings.ends_with(.display_text, 'pdf')
102 )
103 ),
104
105 // display name contains an email
106 regex.contains(sender.display_name, '[a-z0-9]+@[a-z]+'),
107
108 // Sender domain is empty
109 sender.email.domain.domain == "",
110
111 // sender domain matches no body domains
112 all(body.links,
113 .href_url.domain.root_domain != sender.email.domain.root_domain
114 ),
115
116 // body contains name of VIP
117 (
118 any($org_vips, strings.icontains(body.html.inner_text, .display_name))
119 or any($org_vips, strings.icontains(body.plain.raw, .display_name))
120 ),
121
122 // new body domain
123 any(body.links, network.whois(.href_url.domain).days_old < 30),
124
125 // new sender domain
126 network.whois(sender.email.domain).days_old < 30,
127
128 // new sender
129 profile.by_sender().days_known < 7,
130
131 // excessive whitespace
132 (
133 regex.icontains(body.html.raw, '((<br\s*/?>\s*){20,}|\n{20,})')
134 or regex.icontains(body.html.raw, '(<p[^>]*>\s*<br\s*/?>\s*</p>\s*){30,}')
135 or regex.icontains(body.html.raw,
136 '(<p class=".*?"><span style=".*?"><o:p> </o:p></span></p>\s*){30,}'
137 )
138 or regex.icontains(body.html.raw, '(<p> </p>\s*){7,}')
139 or regex.icontains(body.html.raw, '(<p> </p><br>\s*){7,}')
140 or regex.icontains(body.html.raw, '(<p[^>]*>\s* <br>\s*</p>\s*){5,}')
141 or regex.icontains(body.html.raw, '(<p[^>]*> </p>\s*){7,}')
142 ),
143
144 // body contains recipient SLD
145 any(recipients.to,
146 strings.icontains(body.current_thread.text, .email.domain.sld)
147 )
148 )
149
150 // negate highly trusted sender domains unless they fail DMARC authentication
151 and (
152 (
153 sender.email.domain.root_domain in $high_trust_sender_root_domains
154 and not headers.auth_summary.dmarc.pass
155 )
156 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
157 )
158 and not profile.by_sender().any_messages_benign
159
160tags:
161 - "Attack surface reduction"
162attack_types:
163 - "BEC/Fraud"
164 - "Credential Phishing"
165 - "Spam"
166tactics_and_techniques:
167 - "Evasion"
168 - "Social engineering"
169detection_methods:
170 - "Content analysis"
171 - "Header analysis"
172 - "Natural Language Understanding"
173 - "Sender analysis"
174id: "c2e18a57-1f52-544f-bb6d-a578e286cf89"