Credential phishing: Email delivery failure impersonation

Detects phishing emails impersonating email system notifications claiming delivery failures, rejected messages, or email system issues requiring user action to 'fix' or 'recover' email functionality. These attacks typically claim incoming emails couldn't be delivered and direct users to malicious portals to harvest credentials.

Sublime rule (View on GitHub)

  1name: "Credential phishing: Email delivery failure impersonation"
  2description: |
  3  Detects phishing emails impersonating email system notifications claiming delivery failures, 
  4  rejected messages, or email system issues requiring user action to 'fix' or 'recover' email functionality.
  5  These attacks typically claim incoming emails couldn't be delivered and direct users to malicious 
  6  portals to harvest credentials.  
  7type: "rule"
  8severity: "high"
  9source: |
 10  type.inbound
 11  and (
 12    any(ml.nlu_classifier(body.current_thread.text).intents,
 13        .name == "cred_theft" and .confidence == "high"
 14    )
 15    or (
 16      length(body.current_thread.text) < 250
 17      and any(recipients.to,
 18              strings.icontains(body.current_thread.text, .email.domain.sld)
 19              or strings.icontains(body.current_thread.text, .email.local_part)
 20      )
 21    )
 22  )
 23  and (
 24    regex.icontains(subject.subject, '(e)?mail(s)?')
 25    or (
 26      length(body.current_thread.text) < 700
 27      and strings.ilike(body.current_thread.text, '*mail*')
 28    )
 29    or (length(subject.base) == 0 or subject.base is null)
 30  )
 31  and 3 of (
 32    strings.ilike(body.current_thread.text, "*incoming messages*"),
 33    strings.ilike(body.current_thread.text, "*server error*"),
 34    strings.ilike(body.current_thread.text, "*blocked*"),
 35    strings.ilike(body.current_thread.text, "*prevented*"),
 36    strings.ilike(body.current_thread.text, "*notification*"),
 37    strings.ilike(body.current_thread.text, "*fix email issues*"),
 38    strings.ilike(body.current_thread.text, "*rejected*"),
 39    strings.ilike(body.current_thread.text, "*recover and prevent*"),
 40    strings.ilike(body.current_thread.text, "*failure*"),
 41    strings.ilike(body.current_thread.text, "*rejection*"),
 42    strings.ilike(body.current_thread.text, "*failed*"),
 43    strings.ilike(body.current_thread.text, "*deleted in 24 hours*"),
 44    strings.ilike(body.current_thread.text, "*immediate attention*"),
 45    strings.ilike(body.current_thread.text, "*restore these messages*"),
 46    strings.ilike(body.current_thread.text, "*take action if needed*"),
 47    strings.ilike(body.current_thread.text, "*##year##*"),
 48    strings.ilike(body.current_thread.text, "*mail delivery subsystem*"),
 49    regex.icontains(body.current_thread.text,
 50                    '#\d+(?:\.\d+)*\s+The email account does not exist'
 51    )
 52  )
 53  and (
 54    any(body.links,
 55        regex.icontains(.display_text,
 56                        "view",
 57                        "messages",
 58                        "recover",
 59                        "fix",
 60                        "portal",
 61                        "connect",
 62                        "confirm"
 63        )
 64        and not .display_text == "View Report"
 65    )
 66    or (
 67      length(body.links) < 3
 68      and any(body.links,
 69              .mismatched
 70              and any(recipients.to,
 71                      .email.domain.root_domain == ..display_url.domain.root_domain
 72              )
 73      )
 74    )
 75    or (all(recipients.to, .email.local_part == sender.display_name))
 76    or any(body.links,
 77           any(.href_url.rewrite.encoders, . == "proofpoint")
 78           and .href_url.domain.root_domain not in $tranco_50k
 79           and .href_url.domain.root_domain not in $org_domains
 80    )
 81    or any(recipients.to,
 82           strings.icontains(sender.display_name,
 83                             strings.concat('MyReport For ', .email.local_part)
 84           )
 85    )
 86  )
 87  and not any(body.links,
 88              regex.icontains(.display_text,
 89                              "view document",
 90                              "review (&|and) sign document"
 91              )
 92  )
 93  and sender.email.domain.root_domain not in (
 94    "bing.com",
 95    "microsoft.com",
 96    "microsoftonline.com",
 97    "microsoftsupport.com",
 98    "microsoft365.com",
 99    "office.com",
100    "office365.com",
101    "onedrive.com",
102    "sharepointonline.com",
103    "yammer.com",
104    "ppops.net",
105    "opentext.com",
106    "getsentry.com"
107  )
108  
109  // negate org domains unless they fail DMARC authentication
110  and (
111    (
112      sender.email.domain.root_domain in $org_domains
113      and (
114        not headers.auth_summary.dmarc.pass
115        // MS  emails from an org domain are router "internally" to MS, therefore, there is no authentication information
116        or not (
117          headers.auth_summary.dmarc.pass is null
118          and all(headers.domains,
119                  .root_domain in ("outlook.com", "office365.com")
120          )
121          // typical emails from freemail Outlook accounts are from prod.outlook.com
122          and strings.ends_with(headers.message_id, "protection.outlook.com>")
123        )
124      )
125    )
126    or sender.email.domain.root_domain not in $org_domains
127  )
128  
129  // negate highly trusted sender domains unless they fail DMARC authentication
130  and not (
131    sender.email.domain.root_domain in $high_trust_sender_root_domains
132    and coalesce(headers.auth_summary.dmarc.pass, false)
133  )
134  and not profile.by_sender().solicited
135  and not profile.by_sender().any_messages_benign
136    
137attack_types:
138  - "Credential Phishing"
139tactics_and_techniques:
140  - "Impersonation: Brand"
141  - "Social engineering"
142detection_methods:
143  - "Content analysis"
144  - "Natural Language Understanding"
145  - "Sender analysis"
146id: "ee318b89-0d4e-5c94-80ad-08991d3958b2"
to-top