Credential phishing: Engaging language and other indicators (untrusted sender)
Message contains various suspicious indicators as well as engaging language resembling credential theft from an untrusted sender.
Sublime rule (View on GitHub)
1name: "Credential phishing: Engaging language and other indicators (untrusted sender)"
2description: |
3 Message contains various suspicious indicators as well as engaging language resembling credential theft from an untrusted sender.
4type: "rule"
5severity: "medium"
6source: |
7 type.inbound
8 and (
9 regex.icontains(subject.subject,
10 "termination.*notice",
11 "38417",
12 ":completed",
13 "[il1]{2}mit.*ma[il1]{2} ?bo?x",
14 "[il][il][il]egai[ -]",
15 "[li][li][li]ega[li] attempt",
16 "[ng]-?[io]n .*block",
17 "[ng]-?[io]n .*cancel",
18 "[ng]-?[io]n .*deactiv",
19 "[ng]-?[io]n .*disabl",
20 "action.*required",
21 "abandon.*package",
22 "about.your.account",
23 "acc(ou)?n?t (is )?on ho[li]d",
24 "acc(ou)?n?t.*terminat",
25 "acc(oun)?t.*[il1]{2}mitation",
26 "access.*limitation",
27 "account (will be )?block",
28 "account.*de-?activat",
29 "account.*locked",
30 "account.*re-verification",
31 "account.*security",
32 "account.*suspension",
33 "account.has.expired",
34 "account.will.be.blocked",
35 "account v[il]o[li]at",
36 "activity.*acc(oun)?t",
37 "almost.full",
38 "app[li]e.[il]d",
39 "authenticate.*account",
40 "been.*suspend",
41 "crediential.*notif",
42 "clos.*of.*account.*processed",
43 "confirm.your.account",
44 "courier.*able",
45 "crediential.*notif",
46 "deactivation.*in.*progress",
47 "delivery.*attempt.*failed",
48 "disconnection.*notice",
49 "document.received",
50 "documented.*shared.*with.*you",
51 "dropbox.*document",
52 "e-?ma[il1]+ .{010}suspen",
53 "e-?ma[il1]{1} user",
54 "e-?ma[il1]{2} acc",
55 "e-?ma[il1]{2} preview",
56 "e-?ma[il1]{2}.*up.?grade",
57 "e.?ma[il1]{2}.*server",
58 "e.?ma[il1]{2}.*suspend",
59 "email.update",
60 "faxed you",
61 "fraud(ulent)?.*charge",
62 "from.helpdesk",
63 "fu[il1]{2}.*ma[il1]+[ -]?box",
64 "has.been.*suspended",
65 "has.been.limited",
66 "have.locked",
67 "he[li]p ?desk upgrade",
68 "heipdesk",
69 "i[il]iega[il]",
70 "ii[il]ega[il]",
71 "incoming e?mail",
72 "incoming.*fax",
73 "lock.*security",
74 "ma[il1]{1}[ -]?box.*quo",
75 "ma[il1]{2}[ -]?box.*fu[il1]",
76 "ma[il1]{2}box.*[il1]{2}mit",
77 "ma[il1]{2}box stor",
78 "mail on.?hold",
79 "mail.*box.*migration",
80 "mail.*de-?activat",
81 "mail.update.required",
82 "mails.*pending",
83 "messages.*pending",
84 "missed.*shipping.*notification",
85 "missed.shipment.notification",
86 "must.update.your.account",
87 "new [sl][io]g?[nig][ -]?in from",
88 "new voice ?-?mail",
89 "notifications.*pending",
90 "office.*3.*6.*5.*suspend",
91 "office365",
92 "on google docs with you",
93 "online doc",
94 "password.*compromised",
95 "(?:payroll|salary|bonus).*Distribution",
96 "periodic maintenance",
97 "potential(ly)? unauthorized",
98 "refund not approved",
99 "report",
100 "revised.*policy",
101 "scam",
102 "scanned.?invoice",
103 "secured?.update",
104 "security breach",
105 "securlty",
106 "signed.*delivery",
107 "status of your .{314}? ?delivery",
108 "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty",
109 "suspicious.*sign.*[io]n",
110 "suspicious.activit",
111 "temporar(il)?y deactivate",
112 "temporar[il1]{2}y disab[li]ed",
113 "temporarily.*lock",
114 "un-?usua[li].activity",
115 "unable.*deliver",
116 "unauthorized.*activit",
117 "unauthorized.device",
118 "undelivered message",
119 "unread.*doc",
120 "unusual.activity",
121 "(?:unrecognized|Unusual|suspicious|unknown) (?:log|sign).?[io]n attempt",
122 "upgrade.*account",
123 "upgrade.notice",
124 "urgent message",
125 "urgent.verification",
126 "v[il1]o[li1]at[il1]on security",
127 "va[il1]{1}date.*ma[il1]{2}[ -]?box",
128 "verification ?-?require",
129 "verification( )?-?need",
130 "verify.your?.account",
131 "web ?-?ma[il1]{2}",
132 "web[ -]?ma[il1]{2}",
133 "will.be.suspended",
134 "your (customer )?account .as",
135 "your.office.365",
136 "your.online.access",
137 "de.activation",
138 // https://github.com/sublime-security/static-files/blob/master/suspicious_subjects.txt
139 "account has been limited",
140 "action required",
141 "almost full",
142 "apd notifi cation",
143 "are you at your desk",
144 "are you available",
145 "attached file to docusign",
146 "banking is temporarily unavailable",
147 "bankofamerica",
148 "closing statement invoice",
149 "completed: docusign",
150 "de-activation of",
151 "delivery attempt",
152 "delivery stopped for shipment",
153 "detected suspicious",
154 "detected suspicious actvity",
155 "docu sign",
156 "document for you",
157 "document has been sent to you via docusign",
158 "document is ready for signature",
159 "docusign",
160 "encrypted message",
161 "failed delivery",
162 "fedex tracking",
163 "file was shared",
164 "freefax",
165 "fwd: due invoice paid",
166 "has shared",
167 "inbox is full",
168 "invitation to comment",
169 "invitation to edit",
170 "invoice due",
171 "left you a message",
172 "message from",
173 "new message",
174 "new voicemail",
175 "on desk",
176 "out of space",
177 "password reset",
178 "payment status",
179 "pay notification",
180 "quick reply",
181 "re: w-2",
182 "required",
183 "required: completed docusign",
184 "remittance",
185 "ringcentral",
186 "scanned image",
187 "secured files",
188 "secured pdf",
189 "security alert",
190 "new sign-in",
191 "new sign in",
192 "sign-in attempt",
193 "sign in attempt",
194 "staff review",
195 "suspicious activity",
196 "unrecognized login attempt",
197 "unusual signin",
198 "upgrade immediately",
199 "urgent",
200 "wants to share",
201 "w2",
202 "you have notifications pending",
203 "your account",
204 "your amazon order",
205 "your document settlement",
206 "your order with amazon",
207 "your password has been compromised",
208 )
209 or (
210 regex.icontains(subject.subject, 'account.has.been')
211 and not regex.icontains(subject.subject, 'account.has.been.*created')
212 )
213 or (
214 regex.icontains(sender.display_name,
215 "Admin",
216 "Administrator",
217 "Alert",
218 "Assistant",
219 "Authenticat(or|ion)",
220 "Billing",
221 "Benefits",
222 "Bonus",
223 "CEO",
224 "CFO",
225 "CIO",
226 "CTO",
227 "Chairman",
228 "Claim",
229 "Confirm",
230 "Cpanel Mail",
231 "Critical",
232 "Customer Service",
233 "Deal",
234 "Discount",
235 "Director",
236 "Exclusive",
237 "Executive",
238 "Fax",
239 "Free",
240 "Gift",
241 '\bHR\b',
242 "Helpdesk",
243 "Human Resources",
244 "Immediate",
245 "Important",
246 "Info",
247 "Information",
248 "Invoice",
249 '\bIT\b',
250 '\bLegal\b',
251 "Lottery",
252 "Management",
253 "Manager",
254 "Member Services",
255 "Notification",
256 "Offer",
257 "Official Communication",
258 "Operations",
259 "Order",
260 "Partner",
261 "Payment",
262 "Payroll",
263 "Postmaster",
264 "President",
265 "Premium",
266 "Prize",
267 "Receipt",
268 "Refund",
269 "Registrar",
270 "Required",
271 "Reward",
272 "Sales",
273 "Secretary",
274 "Security",
275 "Server",
276 "Service",
277 "Storage",
278 "Support",
279 "Sweepstakes",
280 "System",
281 "Tax",
282 "Tech Support",
283 "Update",
284 "Upgrade",
285 "Urgent",
286 "Validate",
287 "Verify",
288 "VIP",
289 "Webmaster",
290 "Winner",
291 )
292 // add negation for common FPs in the sender display_name
293 and not strings.icontains(sender.display_name, "service bulletin")
294 and not strings.icontains(sender.display_name, "automotive service")
295 )
296 )
297 and (
298 4 of (
299 any(recipients.to,
300 .email.domain.valid
301 and (
302 strings.icontains(body.current_thread.text, .email.email)
303 or strings.icontains(body.current_thread.text, .email.local_part)
304 )
305 ),
306 any(ml.nlu_classifier(body.current_thread.text).intents,
307 .name == "cred_theft" and .confidence in ("medium", "high")
308 ),
309 any(ml.nlu_classifier(body.current_thread.text).entities,
310 .name == "request"
311 ),
312 // recipient email address base64 encoded in link
313 any(body.links,
314 any(recipients.to,
315 any(beta.scan_base64(..href_url.url,
316 ignore_padding=true,
317 format="url"
318 ),
319 strings.icontains(., ..email.email)
320 )
321 )
322 ),
323 (
324 // freemail providers should never be sending this type of email
325 sender.email.domain.domain in $free_email_providers
326
327 // if not freemail, it's suspicious if the sender's root domain
328 // doesn't match any links in the body
329 or all(body.links,
330 .href_url.domain.root_domain != sender.email.domain.root_domain
331 and (
332 .href_url.domain.root_domain not in $org_domains
333 // ignore recipient email addresses in the body in relation to this check
334 or (
335 .href_url.domain.root_domain in $org_domains
336 and any(recipients.to,
337 strings.icount(body.current_thread.text, .email.email) == strings.icount(body.current_thread.text,
338 .email.domain.domain
339 )
340 )
341 )
342 )
343 )
344
345 // bulk mailers should also never be sending this type of email
346 or all(filter(body.links,
347 .href_url.domain.domain not in (
348 "aka.ms",
349 "mimecast.com",
350 "mimecastprotect.com",
351 "cisco.com"
352 )
353 ),
354 .href_url.domain.root_domain in $bulk_mailer_url_root_domains
355 )
356 ),
357 // in case it's embedded in an image attachment
358 // note: don't use message_screenshot() because it's not limited to current_thread
359 // and may FP
360 any(attachments,
361 .file_type in $file_types_images
362 and any(file.explode(.),
363 any(ml.nlu_classifier(.scan.ocr.raw).intents,
364 .name == "cred_theft" and .confidence == "high"
365 )
366 )
367 ),
368 strings.contains(body.current_thread.text,
369 "Your mailbox can no longer send or receive messages."
370 ),
371 any(body.links,
372 strings.icontains(.href_url.query_params, 'redirect')
373 or any(.href_url.rewrite.encoders,
374 strings.icontains(., "open_redirect")
375 )
376 ),
377 // multiple entities displaying urgency
378 length(filter(ml.nlu_classifier(body.current_thread.text).entities,
379 .name == "urgency"
380 )
381 ) >= 2
382 // and any body links
383 and any(body.links,
384 // display text contains a request
385 any(ml.nlu_classifier(.display_text).entities, .name == "request")
386 ),
387 any(body.links,
388 // display text contains a request
389 (
390 any(ml.nlu_classifier(.display_text).entities, .name == "request")
391 or regex.match(.display_text, '^[^a-z]+$')
392 )
393 and (
394 .href_url.domain.domain in $url_shorteners
395 or .href_url.domain.domain in $social_landing_hosts
396 or .href_url.domain.root_domain in $url_shorteners
397 or .href_url.domain.root_domain in $social_landing_hosts
398 or .href_url.domain.domain in $free_file_hosts
399 or (
400 .href_url.domain.root_domain in (
401 "mimecast.com",
402 "mimecastprotect.com"
403 )
404 and any(.href_url.query_params_decoded['domain'],
405 strings.parse_url(strings.concat("https://", .)).domain.domain in $url_shorteners
406 or strings.parse_url(strings.concat("https://", .)).domain.root_domain in $url_shorteners
407 or strings.parse_url(strings.concat("https://", .)).domain.domain in $free_file_hosts
408 or strings.parse_url(strings.concat("https://", .)).domain.root_domain in $free_subdomain_hosts
409 or strings.parse_url(strings.concat("https://", .)).domain.domain in $social_landing_hosts
410 or strings.parse_url(strings.concat("https://", .)).domain.root_domain in $social_landing_hosts
411 )
412 )
413 )
414 ),
415 // common greetings via email.local_part
416 any(recipients.to,
417 length(.email.local_part) > 2
418 and
419 // use count to ensure the email address is not part of a disclaimer
420 strings.icount(body.current_thread.text, .email.local_part) >
421 // sum allows us to add more logic as needed
422 strings.icount(body.current_thread.text,
423 strings.concat('was sent to ', .email.email)
424 ) + strings.icount(body.current_thread.text,
425 strings.concat('intended for ', .email.email)
426 )
427 )
428 )
429 or (
430 (
431 // recipient's email address is in the body
432 any(recipients.to,
433 // use count to ensure the email address is not part of a disclaimer
434 strings.icount(body.current_thread.text, .email.email) >
435 // sum allows us to add more logic as needed
436 sum([
437 strings.icount(body.current_thread.text,
438 strings.concat('was sent to ', .email.email)
439 ),
440 strings.icount(body.current_thread.text,
441 strings.concat('intended for ', .email.email)
442 )
443 ]
444 )
445 )
446 // suspicious display text
447 or (
448 length(body.links) == 1
449 and all(body.links,
450 strings.ilike(.display_text, "*click here*", "*password*")
451 )
452 )
453 )
454 // link leads to a suspicious TLD or contains an IP address or contains multiple redirects
455 and any(body.links,
456 (
457 ml.link_analysis(., mode="aggressive").effective_url.domain.tld in $suspicious_tlds
458 or length(distinct(map(ml.link_analysis(., mode="aggressive").redirect_history,
459 .domain.root_domain
460 )
461 )
462 ) >= 4
463 or (
464 any(body.ips,
465 any(body.links, strings.icontains(.href_url.url, ..ip))
466 )
467 )
468 )
469 )
470 )
471 )
472 // exclude Google shared calendar messages
473 // Subject: "<sender name> has shared a calendar with you"
474 and headers.return_path.domain.domain != "calendar-server.bounces.google.com"
475 // negate calendar invites
476 and not (
477 0 < length(attachments) < 3
478 and all(attachments, .content_type in ("text/calendar", "application/ics"))
479 )
480 // negate replies
481 and (
482 (
483 (
484 length(headers.references) > 0
485 or not any(headers.hops,
486 any(.fields, strings.ilike(.name, "In-Reply-To"))
487 )
488 )
489 and not (
490 (
491 strings.istarts_with(subject.subject, "RE:")
492 or strings.istarts_with(subject.subject, "R:")
493 or strings.istarts_with(subject.subject, "ODG:")
494 or strings.istarts_with(subject.subject, "答复:")
495 or strings.istarts_with(subject.subject, "AW:")
496 or strings.istarts_with(subject.subject, "TR:")
497 or strings.istarts_with(subject.subject, "FWD:")
498 or regex.icontains(subject.subject,
499 '^(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:'
500 )
501 )
502 )
503 )
504 or length(headers.references) == 0
505 )
506 // bounce-back and DMARC report negations
507 and not (
508 strings.like(sender.email.local_part,
509 "*postmaster*",
510 "*mailer-daemon*",
511 "*administrator*"
512 )
513 and (
514 any(attachments,
515 .content_type in (
516 "message/rfc822",
517 "message/delivery-status",
518 "text/calendar"
519 )
520 )
521 or (
522 length(attachments) == 1
523 and all(attachments, .content_type in ("application/gzip"))
524 and regex.icontains(subject.subject,
525 '(?:(Report\sDomain).*(Submitter).*(Report-ID))'
526 )
527 )
528 )
529 )
530 and (
531 (
532 profile.by_sender().prevalence != "common"
533 and not profile.by_sender_email().solicited
534 )
535 or (
536 profile.by_sender().any_messages_malicious_or_spam
537 and not profile.by_sender().any_messages_benign
538 )
539 )
540 // negate highly trusted sender domains unless they fail DMARC authentication
541 and (
542 (
543 sender.email.domain.root_domain in $high_trust_sender_root_domains
544 and not headers.auth_summary.dmarc.pass
545 )
546 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
547 )
548attack_types:
549 - "Credential Phishing"
550tactics_and_techniques:
551 - "Free email provider"
552 - "Social engineering"
553detection_methods:
554 - "Content analysis"
555 - "Header analysis"
556 - "Natural Language Understanding"
557 - "Sender analysis"
558 - "URL analysis"
559id: "c2bc8ca2-d207-5c7d-96e4-a0d3d33b2af5"