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