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.icontains(sender.display_name,
219                      "Admin",
220                      "Administrator",
221                      "Alert",
222                      "Assistant",
223                      "Authenticat(or|ion)",
224                      "Billing",
225                      "Benefits",
226                      "Bonus",
227                      "CEO",
228                      "CFO",
229                      "CIO",
230                      "CTO",
231                      "Chairman",
232                      "Claim",
233                      "Confirm",
234                      "Cpanel Mail",
235                      "Critical",
236                      "Customer Service",
237                      "Deal",
238                      "Discount",
239                      "Director",
240                      "Exclusive",
241                      "Executive",
242                      "Fax",
243                      "Free",
244                      "Gift",
245                      '\bHR\b',
246                      "Helpdesk",
247                      "Human Resources",
248                      "Immediate",
249                      "Important",
250                      "Info",
251                      "Information",
252                      "Invoice",
253                      '\bIT\b',
254                      '\bLegal\b',
255                      "Lottery",
256                      "Management",
257                      "Manager",
258                      "Member Services",
259                      "Notification",
260                      "Offer",
261                      "Official Communication",
262                      "Operations",
263                      "Order",
264                      "Partner",
265                      "Payment",
266                      "Payroll",
267                      "Postmaster",
268                      "President",
269                      "Premium",
270                      "Prize",
271                      "Receipt",
272                      "Refund",
273                      "Registrar",
274                      "Required",
275                      "Reward",
276                      "Sales",
277                      "Secretary",
278                      "Security",
279                      "Server",
280                      "Service",
281                      "Storage",
282                      "Support",
283                      "Sweepstakes",
284                      "System",
285                      "Tax",
286                      "Tech Support",
287                      "Update",
288                      "Upgrade",
289                      "Urgent",
290                      "Validate",
291                      "Verify",
292                      "VIP",
293                      "Webmaster",
294                      "Winner",
295                      "DocReq\\b"
296      )
297      // add negation for common FPs in the sender display_name
298      and not strings.icontains(sender.display_name, "service bulletin")
299      and not strings.icontains(sender.display_name, "automotive service")
300    )
301  )
302  and (
303    4 of (
304      any(recipients.to,
305          .email.domain.valid
306          and (
307            strings.icontains(body.current_thread.text, .email.email)
308            or strings.icontains(body.current_thread.text, .email.local_part)
309          )
310      ),
311      any(ml.nlu_classifier(body.current_thread.text).intents,
312          .name == "cred_theft" and .confidence in ("medium", "high")
313      ),
314      any(ml.nlu_classifier(body.current_thread.text).entities,
315          .name == "request"
316      ),
317      (
318        any(body.current_thread.links,
319            strings.iends_with(.display_text, ".pdf")
320            and strings.istarts_with(.display_text, "view")
321        )
322      ),
323      // recipient email address base64 encoded in link
324      any(body.links,
325          any(strings.scan_base64(.href_url.url,
326                                  ignore_padding=true,
327                                  format="url"
328              ),
329              any(recipients.to, strings.icontains(.., .email.email))
330          )
331      ),
332      (
333        // freemail providers should never be sending this type of email
334        sender.email.domain.domain in $free_email_providers
335  
336        // if not freemail, it's suspicious if the sender's root domain
337        // doesn't match any links in the body
338        or all(body.links,
339               .href_url.domain.root_domain != sender.email.domain.root_domain
340               and (
341                 .href_url.domain.root_domain not in $org_domains
342                 // ignore recipient email addresses in the body in relation to this check
343                 or (
344                   .href_url.domain.root_domain in $org_domains
345                   and any(recipients.to,
346                           strings.icount(body.current_thread.text, .email.email) == strings.icount(body.current_thread.text,
347                                                                                                    .email.domain.domain
348                           )
349                   )
350                 )
351               )
352        )
353  
354        // bulk mailers should also never be sending this type of email
355        or all(filter(body.links,
356                      .href_url.domain.domain not in (
357                        "aka.ms",
358                        "mimecast.com",
359                        "mimecastprotect.com",
360                        "cisco.com"
361                      )
362               ),
363               .href_url.domain.root_domain in $bulk_mailer_url_root_domains
364        )
365      ),
366      // in case it's embedded in an image attachment
367      // note: don't use message_screenshot() because it's not limited to current_thread
368      // and may FP
369      any(attachments,
370          .file_type in $file_types_images
371          and any(file.explode(.),
372                  any(ml.nlu_classifier(.scan.ocr.raw).intents,
373                      .name == "cred_theft" and .confidence == "high"
374                  )
375          )
376      ),
377      strings.contains(body.current_thread.text,
378                       "Your mailbox can no longer send or receive messages."
379      ),
380      strings.contains(body.current_thread.text,
381                       "this invoice has been overlooked"
382      ),
383      any(body.links,
384          strings.icontains(.href_url.query_params, 'redirect')
385          or any(.href_url.rewrite.encoders,
386                 strings.icontains(., "open_redirect")
387          )
388      ),
389      // multiple entities displaying urgency
390      length(filter(ml.nlu_classifier(body.current_thread.text).entities,
391                    .name == "urgency"
392             )
393      ) >= 2
394      // and any body links
395      and any(body.links,
396              // display text contains a request
397              any(ml.nlu_classifier(.display_text).entities, .name == "request")
398      ),
399      (
400        any(body.links,
401            .href_url.domain.root_domain in $self_service_creation_platform_domains
402        )
403        and any(ml.nlu_classifier(body.current_thread.text).tags,
404                .name == "invoice" and .confidence == "high"
405        )
406      ),
407      any(body.links,
408          // display text contains a request
409          (
410            any(ml.nlu_classifier(.display_text).entities, .name == "request")
411            or regex.match(.display_text, '^[^a-z]+$')
412          )
413          and (
414            .href_url.domain.domain in $url_shorteners
415            or .href_url.domain.domain in $social_landing_hosts
416            or .href_url.domain.root_domain in $url_shorteners
417            or .href_url.domain.root_domain in $social_landing_hosts
418            or .href_url.domain.domain in $free_file_hosts
419            or (
420              .href_url.domain.root_domain in (
421                "mimecast.com",
422                "mimecastprotect.com"
423              )
424              and any(.href_url.query_params_decoded['domain'],
425                      strings.parse_url(strings.concat("https://", .)).domain.domain in $url_shorteners
426                      or strings.parse_url(strings.concat("https://", .)).domain.root_domain in $url_shorteners
427                      or strings.parse_url(strings.concat("https://", .)).domain.domain in $free_file_hosts
428                      or strings.parse_url(strings.concat("https://", .)).domain.root_domain in $free_subdomain_hosts
429                      or strings.parse_url(strings.concat("https://", .)).domain.domain in $social_landing_hosts
430                      or strings.parse_url(strings.concat("https://", .)).domain.root_domain in $social_landing_hosts
431              )
432            )
433          )
434      ),
435      // common greetings via email.local_part
436      any(recipients.to,
437          length(.email.local_part) > 2
438          and 
439          // use count to ensure the email address is not part of a disclaimer
440          strings.icount(body.current_thread.text, .email.local_part) > 
441          // sum allows us to add more logic as needed
442          strings.icount(body.current_thread.text,
443                         strings.concat('was sent to ', .email.email)
444          ) + strings.icount(body.current_thread.text,
445                             strings.concat('intended for ', .email.email)
446          )
447      )
448    )
449    or (
450      (
451        // recipient's email address is in the body
452        any(recipients.to,
453            // use count to ensure the email address is not part of a disclaimer
454            strings.icount(body.current_thread.text, .email.email) > 
455            // sum allows us to add more logic as needed
456            sum([
457                  strings.icount(body.current_thread.text,
458                                 strings.concat('was sent to ', .email.email)
459                  ),
460                  strings.icount(body.current_thread.text,
461                                 strings.concat('intended for ', .email.email)
462                  )
463                ]
464            )
465        )
466        // suspicious display text
467        or (
468          length(body.links) == 1
469          and all(body.links,
470                  strings.ilike(.display_text, "*click here*", "*password*")
471          )
472        )
473      )
474      // link leads to a suspicious TLD or contains an IP address or contains multiple redirects
475      and any(body.links,
476              (
477                ml.link_analysis(., mode="aggressive").effective_url.domain.tld in $suspicious_tlds
478                or length(distinct(map(ml.link_analysis(., mode="aggressive").redirect_history,
479                                       .domain.root_domain
480                                   )
481                          )
482                ) >= 4
483                or (
484                  any(body.ips,
485                      any(body.links, strings.icontains(.href_url.url, ..ip))
486                  )
487                )
488              )
489      )
490    )
491  )
492  // exclude Google shared calendar messages
493  // Subject: "<sender name> has shared a calendar with you"
494  and headers.return_path.domain.domain != "calendar-server.bounces.google.com"
495  // negate calendar invites
496  and not (
497    0 < length(attachments) < 3
498    and all(attachments, .content_type in ("text/calendar", "application/ics"))
499  )
500  // negate replies
501  and (
502    (
503      (length(headers.references) > 0 or headers.in_reply_to is null)
504      and not (
505        (
506          strings.istarts_with(subject.subject, "RE:")
507          or strings.istarts_with(subject.subject, "R:")
508          or strings.istarts_with(subject.subject, "ODG:")
509          or strings.istarts_with(subject.subject, "答复:")
510          or strings.istarts_with(subject.subject, "AW:")
511          or strings.istarts_with(subject.subject, "TR:")
512          or strings.istarts_with(subject.subject, "FWD:")
513          or regex.icontains(subject.subject,
514                             '^(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:'
515          )
516        )
517      )
518    )
519    or length(headers.references) == 0
520  )
521  // bounce-back and DMARC report negations
522  and not (
523    strings.like(sender.email.local_part,
524                 "*postmaster*",
525                 "*mailer-daemon*",
526                 "*administrator*"
527    )
528    and (
529      any(attachments,
530          .content_type in (
531            "message/rfc822",
532            "message/delivery-status",
533            "text/calendar"
534          )
535      )
536      or (
537        length(attachments) == 1
538        and all(attachments, .content_type in ("application/gzip"))
539        and regex.icontains(subject.subject,
540                            '(?:(Report\sDomain).*(Submitter).*(Report-ID))'
541        )
542      )
543    )
544  )
545  and (
546    (
547      profile.by_sender().prevalence != "common"
548      and not profile.by_sender_email().solicited
549    )
550    or (
551      profile.by_sender().any_messages_malicious_or_spam
552      and not profile.by_sender().any_messages_benign
553    )
554  )
555  // negate highly trusted sender domains unless they fail DMARC authentication
556  and (
557    (
558      sender.email.domain.root_domain in $high_trust_sender_root_domains
559      and not headers.auth_summary.dmarc.pass
560    )
561    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
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"
to-top