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