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