Brand impersonation: Sharepoint fake file share
This rule detects messages impersonating a Sharepoint file sharing email where no links point to known Microsoft domains.
Sublime rule (View on GitHub)
1name: "Brand impersonation: Sharepoint fake file share"
2description: |
3 This rule detects messages impersonating a Sharepoint file sharing email where no links point to known Microsoft domains.
4type: "rule"
5severity: "medium"
6source: |
7 type.inbound
8
9 // Sharepoint body content looks like this
10 and (
11 (
12 (
13 any([body.current_thread.text, body.plain.raw],
14 strings.ilike(.,
15 "*shared a file with you*",
16 "*shared with you*",
17 "*invited you to access a file*",
18 "*received a document*",
19 "*shared a document*",
20 "*shared this document*"
21 )
22 )
23 or any(file.explode(beta.message_screenshot()),
24 strings.ilike(.scan.ocr.raw,
25 "*shared a file with you*",
26 "*shared with you*",
27 "*invited you to access a file*",
28 "*received a document*",
29 "*shared a document*",
30 "*shared this document*"
31 )
32 )
33 )
34 and (
35 strings.ilike(subject.subject,
36 "*shared*",
37 "*updated*",
38 "*sign*",
39 "*review*"
40 )
41 or strings.ilike(subject.subject,
42 "*Excel*",
43 "*SharePoint*",
44 "*PowerPoint*",
45 "*OneNote*"
46 )
47 or any(body.links, strings.icontains(.display_text, "OPEN DOCUMENT"))
48 or subject.subject is null
49 or subject.subject == ""
50 // the org as determined by NLU is in the subject
51 or any(ml.nlu_classifier(body.current_thread.text).entities,
52 .name == "org" and strings.icontains(subject.subject, .text)
53 )
54
55 )
56 )
57 or any([
58 "Contigo", // Spanish
59 "Avec vous", // French
60 "Mit Ihnen", // German
61 "Con te", // Italian
62 "Com você", // Portuguese
63 "Met u", // Dutch
64 "С вами", // Russian
65 "与你", // Chinese (Simplified)
66 "與您", // Chinese (Traditional)
67 "あなたと", // Japanese
68 "당신과", // Korean
69 "معك", // Arabic
70 "آپ کے ساتھ", // Urdu
71 "আপনার সাথে", // Bengali
72 "आपके साथ", // Hindi
73 "Sizinle", // Turkish // Azerbaijani
74 "Med dig", // Swedish
75 "Z tobą", // Polish
76 "З вами", // Ukrainian
77 "Önnel", // Hungarian
78 "Μαζί σας", // Greek
79 "איתך", // Hebrew
80 "กับคุณ", // Thai
81 "Với bạn", // Vietnamese
82 "Dengan Anda", // Indonesian // Malay
83 "Nawe", // Swahili
84 "Cu dumneavoastră", // Romanian
85 "S vámi", // Czech
86 "Med deg", // Norwegian
87 "S vami", // Slovak
88 "Med dig", // Danish
89 "Amb vostè", // Catalan
90 "Teiega", // Estonian
91 "S vama", // Serbian
92 ],
93 strings.icontains(subject.subject, .)
94 )
95 )
96
97 // contains logic that impersonates Microsoft
98 and (
99 any(ml.logo_detect(beta.message_screenshot()).brands,
100 strings.starts_with(.name, "Microsoft")
101 )
102 or any(attachments,
103 .file_type in $file_types_images
104 and any(ml.logo_detect(.).brands,
105 strings.starts_with(.name, "Microsoft")
106 )
107 )
108 or (
109 regex.icontains(body.html.raw,
110 '<table[^>]*>\s*<tbody[^>]*>\s*<tr[^>]*>\s*(<td[^>]*bgcolor="#[0-9A-Fa-f]{6}"[^>]*>\s* \s*</td>\s*){2}\s*</tr>\s*<tr[^>]*>\s*(<td[^>]*bgcolor="#[0-9A-Fa-f]{6}"[^>]*>\s* \s*</td>\s*){2}'
111 )
112 or 3 of (
113 regex.icontains(body.html.raw, '.password-expiration'),
114 regex.icontains(body.html.raw, 'color: #2672ec;'),
115 regex.icontains(body.html.raw, 'Microsoft')
116 )
117 or 4 of (
118 regex.icontains(body.html.raw, 'rgb\(246,\s?93,\s?53\)'),
119 regex.icontains(body.html.raw, 'rgb\(129,\s?187,\s?5\)'),
120 regex.icontains(body.html.raw, 'rgb\(4,\s?165,\s?240\)'),
121 regex.icontains(body.html.raw, 'rgb\(255,\s?186,\s?7\)'),
122 )
123 or 4 of (
124 regex.icontains(body.html.raw,
125 '(background-color:|background:|bgcolor=)(.)red'
126 ),
127 regex.icontains(body.html.raw, 'rgb\(19,\s?186,\s?132\)'),
128 regex.icontains(body.html.raw, 'rgb\(4,\s?166,\s?240\)'),
129 regex.icontains(body.html.raw, 'rgb\(255,\s?186,\s?8\)'),
130 )
131 or 4 of (
132 regex.icontains(body.html.raw, 'rgb\(245,\s?189,\s?67\)'),
133 regex.icontains(body.html.raw, 'rgb\(137,\s?184,\s?57\)'),
134 regex.icontains(body.html.raw, 'rgb\(217,\s?83,\s?51\)'),
135 regex.icontains(body.html.raw, 'rgb\(71,\s?160,\s?218\)')
136 )
137 or 4 of (
138 regex.icontains(body.html.raw, 'rgb\(73,\s?161,\s?232\)'),
139 regex.icontains(body.html.raw, 'rgb\(224,\s?92,\s?53\)'),
140 regex.icontains(body.html.raw, 'rgb\(139,\s?183,\s?55\)'),
141 regex.icontains(body.html.raw, 'rgb\(244,\s?188,\s?65\)')
142 )
143 or 4 of (
144 regex.icontains(body.html.raw, 'rgb\(213,\s?56,\s?62\)'),
145 regex.icontains(body.html.raw, 'rgb\(0,\s?114,\s?30\)'),
146 regex.icontains(body.html.raw, 'rgb\(0,\s?110,\s?173\)'),
147 regex.icontains(body.html.raw, 'rgb\(227,\s?209,\s?43\)'),
148 )
149 or 4 of (
150 regex.icontains(body.html.raw, 'rgb\(246,\s?93,\s?53\)'),
151 regex.icontains(body.html.raw, 'rgb\(129,\s?187,\s?5\)'),
152 regex.icontains(body.html.raw, 'rgb\(4,\s?165,\s?240\)'),
153 regex.icontains(body.html.raw, 'rgb\(255,\s?186,\s?7\)')
154 )
155 or 4 of (
156 regex.icontains(body.html.raw, 'rgb\(242,\s?80,\s?34\)'),
157 regex.icontains(body.html.raw, 'rgb\(127,\s?186,\s?0\)'),
158 regex.icontains(body.html.raw, 'rgb\(0,\s?164,\s?239\)'),
159 regex.icontains(body.html.raw, 'rgb\(255,\s?185,\s?0\)'),
160 )
161 or 4 of (
162 regex.icontains(body.html.raw, 'rgb\(243,\s?83,\s?37\)'),
163 regex.icontains(body.html.raw, 'rgb\(129,\s?188,\s?6\)'),
164 regex.icontains(body.html.raw, 'rgb\(5,\s?166,\s?240\)'),
165 regex.icontains(body.html.raw, 'rgb\(255,\s?186,\s?8\)')
166 )
167 or 4 of (
168 regex.icontains(body.html.raw, 'rgb\(243,\s?80,\s?34\)'),
169 regex.icontains(body.html.raw, 'rgb\(128,\s?187,\s?3\)'),
170 regex.icontains(body.html.raw, 'rgb\(3,\s?165,\s?240\)'),
171 regex.icontains(body.html.raw, 'rgb\(255,\s?185,\s?3\)')
172 )
173 or 4 of (
174 regex.icontains(body.html.raw,
175 '(background-color:|background:|bgcolor=)(.)?(#)?(FF1940|eb5024|F25022|FF1941|red)'
176 ),
177 regex.icontains(body.html.raw,
178 '(background-color:|background:|bgcolor=)(.)?(#)?(36ba57|3eb55d|7db606|7FBA00|36ba58|green)'
179 ),
180 regex.icontains(body.html.raw,
181 '(background-color:|background:|bgcolor=)(.)?#(04a1d6|04B5F0|05a1e8|00A4EF|01a4ef|04a5f0)'
182 ),
183 regex.icontains(body.html.raw,
184 '(background-color:|background:|bgcolor=)(.)?#(FFCA07|f7b408|FFB900|FFCA08|ffb901|ffba07)'
185 ),
186 )
187 or 4 of (
188 regex.icontains(body.html.raw,
189 '(background-color:|background:|bgcolor=)(.)?#(f65314|f65d35|49a1e8|E74F23|F35325)'
190 ),
191 regex.icontains(body.html.raw,
192 '(background-color:|background:|bgcolor=)(.)?#(7cbf42|81bb05|e05c35|7AB206|81BC06)'
193 ),
194 regex.icontains(body.html.raw,
195 '(background-color:|background:|bgcolor=)(.)?#(00a4ef|0078d7|8bb737|04a5f0|059EE4|05A6F0)'
196 ),
197 regex.icontains(body.html.raw,
198 '(background-color:|background:|bgcolor=)(.)?#(ffb900|ffba07|f4bc41|F2B108|FFBA08)'
199 ),
200 )
201 // fuzzy approach
202 or 4 of (
203 regex.icontains(body.html.raw,
204 'rgb\((2[1-4][0-9]|250),\s?(7[0-9]|8[0-9]|9[0-3]),\s?(3[0-9]|4[0-9]|5[0-3])\)'
205 ),
206 regex.icontains(body.html.raw,
207 'rgb\((12[0-9]|13[0-9]),\s?(18[0-9]|190),\s?([0-9]|10)\)'
208 ),
209 regex.icontains(body.html.raw,
210 'rgb\(([0-9]|1[0-5]),\s?(16[0-5]|166),\s?(23[0-9]|240)\)'
211 ),
212 regex.icontains(body.html.raw,
213 'rgb\((25[0-5]),\s?(18[5-9]|19[0-9]),\s?([0-9]|10)\)'
214 )
215 )
216 or 4 of (
217 regex.icontains(body.html.raw, 'rgb\((25[0-5]),\s?(2[0-5]),\s?(6[0-4])\)'),
218 regex.icontains(body.html.raw, 'rgb\((6[0-2]),\s?(18[0-1]),\s?(9[0-3])\)'),
219 regex.icontains(body.html.raw, 'rgb\(([0-4]),\s?(18[0-1]),\s?(24[0])\)'),
220 regex.icontains(body.html.raw, 'rgb\((25[0-5]),\s?(20[0-2]),\s?([0-7])\)')
221 )
222 or regex.icontains(body.html.raw,
223 '<a[^>]+style="[^"]*background-color:\s*#[0-9A-F]{2}[5-9A-F]{2}[0-9A-F]{2}[^"]*"[^>]*>[^<]*(?:open)[^<]*</a>' // blue button containing the word "open"
224 )
225 or (
226 any(recipients.to,
227 strings.icontains(body.current_thread.text,
228 strings.concat(.email.domain.sld,
229 " shared a file with you"
230 )
231 )
232 )
233 )
234 )
235 )
236
237 // Negate messages when the message-id indciates the message is from MS actual. DKIM/SPF domains can be custom and therefore are unpredictable.
238 and not (
239 strings.starts_with(headers.message_id, '<Share-')
240 and strings.ends_with(headers.message_id, '@odspnotify>')
241 )
242
243 // fake Sharepoint shares are easy to identify if there are any links
244 // that don't point to microsoft[.]com or *.sharepoint[.]com
245 and not all(body.links,
246 .href_url.domain.root_domain in (
247 "1drv.ms",
248 "aka.ms",
249 "microsoft.com",
250 "sharepoint.com"
251 )
252 )
253 and sender.email.domain.root_domain not in $org_domains
254 and sender.email.domain.root_domain not in (
255 "bing.com",
256 "microsoft.com",
257 "microsoftonline.com",
258 "microsoftsupport.com",
259 "microsoft365.com",
260 "office.com",
261 "onedrive.com",
262 "sharepointonline.com",
263 "yammer.com",
264 // ignore microsoft privacy statement links
265 "aka.ms"
266 )
267
268 // negate highly trusted sender domains unless they fail DMARC authentication
269 and (
270 (
271 sender.email.domain.root_domain in $high_trust_sender_root_domains
272 and not headers.auth_summary.dmarc.pass
273 )
274 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
275 )
276 and (
277 profile.by_sender().solicited == false
278 or profile.by_sender_email().prevalence == "new"
279 or (
280 profile.by_sender().any_messages_malicious_or_spam
281 and not profile.by_sender().any_false_positives
282 )
283 )
284 and not profile.by_sender().any_false_positives
285attack_types:
286 - "Credential Phishing"
287 - "Malware/Ransomware"
288detection_methods:
289 - "Content analysis"
290 - "Header analysis"
291 - "URL analysis"
292 - "Computer Vision"
293tactics_and_techniques:
294 - "Impersonation: Brand"
295 - "Social engineering"
296id: "ff8b296b-aa0d-5df0-b4d2-0e599b688f6a"