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