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"
to-top