Detection rules › Sublime MQL

Credential phishing: Email delivery failure impersonation

Severity
high
Type
rule
Source
github.com/sublime-security/sublime-rules

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.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, Social engineering

Event coverage

Rule body MQL

type.inbound
and length(body.links) < 10
and (
  any(ml.nlu_classifier(body.current_thread.text).intents,
      .name == "cred_theft" and .confidence == "high"
  )
  or (
    length(body.current_thread.text) < 250
    and any(recipients.to,
            strings.icontains(body.current_thread.text, .email.domain.sld)
            or strings.icontains(body.current_thread.text, .email.local_part)
    )
  )
)
and (
  regex.icontains(subject.subject, '(e)?mail(s)?')
  or (
    length(body.current_thread.text) < 700
    and strings.ilike(body.current_thread.text, '*mail*')
  )
)
and 3 of (
  strings.ilike(body.current_thread.text, "*incoming messages*"),
  strings.ilike(body.current_thread.text, "*server error*"),
  strings.ilike(body.current_thread.text, "*blocked*"),
  strings.ilike(body.current_thread.text, "*prevented*"),
  strings.ilike(body.current_thread.text, "*notification*"),
  strings.ilike(body.current_thread.text, "*fix email issues*"),
  strings.ilike(body.current_thread.text, "*rejected*"),
  strings.ilike(body.current_thread.text, "*recover and prevent*"),
  strings.ilike(body.current_thread.text, "*failure*"),
  strings.ilike(body.current_thread.text, "*rejection*"),
  strings.ilike(body.current_thread.text, "*failed*")
)
and (
  any(body.links,
      regex.icontains(.display_text,
                      "view",
                      "messages",
                      "recover",
                      "fix",
                      "portal",
                      "connect"
      )
      and not .display_text == "View Report"
      and .href_url.domain.root_domain in ("gmass.co")
  )
  or (
    length(body.links) < 3
    and any(body.links,
            any(recipients.to,
                .email.domain.root_domain == ..display_url.domain.root_domain
                and ..mismatched
            )
    )
  )
  or (all(recipients.to, .email.local_part == sender.display_name))
  or any(body.links,
         any(.href_url.rewrite.encoders, . == "proofpoint")
         and .href_url.domain.root_domain not in $tranco_50k
         and .href_url.domain.root_domain not in $org_domains
  )
)
and not any(body.links,
            regex.icontains(.display_text,
                            "view document",
                            "review (&|and) sign document"
            )
)
and sender.email.domain.root_domain not in (
  "bing.com",
  "microsoft.com",
  "microsoftonline.com",
  "microsoftsupport.com",
  "microsoft365.com",
  "office.com",
  "office365.com",
  "onedrive.com",
  "sharepointonline.com",
  "yammer.com",
  "ppops.net"
)

// negate org domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $org_domains
    and (
      not headers.auth_summary.dmarc.pass
      // MS  emails from an org domain are router "internally" to MS, therefore, there is no authentication information
      or not (
        headers.auth_summary.dmarc.pass is null
        and all(headers.domains,
                .root_domain in ("outlook.com", "office365.com")
        )
        // typical emails from freemail Outlook accounts are from prod.outlook.com
        and strings.ends_with(headers.message_id, "protection.outlook.com>")
      )
    )
  )
  or sender.email.domain.root_domain not in $org_domains
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and not profile.by_sender().solicited
and not profile.by_sender().any_messages_benign

Detection logic

Scope: inbound message.

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.

  1. inbound message
  2. length(body.links) < 10
  3. any of:
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'cred_theft'
      • .confidence is 'high'
    • all of:
      • length(body.current_thread.text) < 250
      • any of recipients.to where any holds:
        • strings.icontains(body.current_thread.text)
        • strings.icontains(body.current_thread.text)
  4. any of:
    • subject.subject matches '(e)?mail(s)?'
    • all of:
      • length(body.current_thread.text) < 700
      • body.current_thread.text matches '*mail*'
  5. at least 3 of 11: body.current_thread.text matches any of 11 patterns
    • *incoming messages*
    • *server error*
    • *blocked*
    • *prevented*
    • *notification*
    • *fix email issues*
    • *rejected*
    • *recover and prevent*
    • *failure*
    • *rejection*
    • *failed*
  6. any of:
    • any of body.links where all hold:
      • .display_text matches any of 6 patterns
        • view
        • messages
        • recover
        • fix
        • portal
        • connect
      • not:
        • .display_text is 'View Report'
      • .href_url.domain.root_domain in ('gmass.co')
    • all of:
      • length(body.links) < 3
      • any of body.links where:
        • any of recipients.to where all hold:
          • .email.domain.root_domain is .display_url.domain.root_domain
          • .mismatched
    • all of recipients.to where:
      • .email.local_part is sender.display_name
    • any of body.links where all hold:
      • any of .href_url.rewrite.encoders where:
        • . is 'proofpoint'
      • .href_url.domain.root_domain not in $tranco_50k
      • .href_url.domain.root_domain not in $org_domains
  7. not:
    • any of body.links where:
      • .display_text matches any of 2 patterns
        • view document
        • review (&|and) sign document
  8. sender.email.domain.root_domain not in ('bing.com', 'microsoft.com', 'microsoftonline.com', 'microsoftsupport.com', 'microsoft365.com', 'office.com', 'office365.com', 'onedrive.com', 'sharepointonline.com', 'yammer.com', 'ppops.net')
  9. any of:
    • all of:
      • sender.email.domain.root_domain in $org_domains
      • any of:
        • not:
          • headers.auth_summary.dmarc.pass
        • not:
          • all of:
            • headers.auth_summary.dmarc.pass is missing
            • all of headers.domains where:
              • .root_domain in ('outlook.com', 'office365.com')
            • headers.message_id ends with 'protection.outlook.com>'
    • sender.email.domain.root_domain not in $org_domains
  10. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  11. not:
    • profile.by_sender().solicited
  12. not:
    • profile.by_sender().any_messages_benign

Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].display_url.domain.root_domain, body.links[].href_url.domain.root_domain, body.links[].href_url.rewrite.encoders, body.links[].mismatched, headers.auth_summary.dmarc.pass, headers.domains, headers.domains[].root_domain, headers.message_id, recipients.to, recipients.to[].email.domain.root_domain, recipients.to[].email.domain.sld, recipients.to[].email.local_part, sender.display_name, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: ml.nlu_classifier, profile.by_sender, regex.icontains, strings.ends_with, strings.icontains, strings.ilike. Reference lists: $high_trust_sender_root_domains, $org_domains, $tranco_50k.

Indicators matched (40)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidenceequalshigh
regex.icontainsregex(e)?mail(s)?
strings.ilikesubstring*mail*
strings.ilikesubstring*incoming messages*
strings.ilikesubstring*server error*
strings.ilikesubstring*blocked*
strings.ilikesubstring*prevented*
strings.ilikesubstring*notification*
strings.ilikesubstring*fix email issues*
strings.ilikesubstring*rejected*
strings.ilikesubstring*recover and prevent*
28 more
strings.ilikesubstring*failure*
strings.ilikesubstring*rejection*
strings.ilikesubstring*failed*
regex.icontainsregexview
regex.icontainsregexmessages
regex.icontainsregexrecover
regex.icontainsregexfix
regex.icontainsregexportal
regex.icontainsregexconnect
body.links[].display_textequalsView Report
body.links[].href_url.domain.root_domainmembergmass.co
body.links[].href_url.rewrite.encoders[]equalsproofpoint
regex.icontainsregexview document
regex.icontainsregexreview (&|and) sign document
sender.email.domain.root_domainmemberbing.com
sender.email.domain.root_domainmembermicrosoft.com
sender.email.domain.root_domainmembermicrosoftonline.com
sender.email.domain.root_domainmembermicrosoftsupport.com
sender.email.domain.root_domainmembermicrosoft365.com
sender.email.domain.root_domainmemberoffice.com
sender.email.domain.root_domainmemberoffice365.com
sender.email.domain.root_domainmemberonedrive.com
sender.email.domain.root_domainmembersharepointonline.com
sender.email.domain.root_domainmemberyammer.com
sender.email.domain.root_domainmemberppops.net
headers.domains[].root_domainmemberoutlook.com
headers.domains[].root_domainmemberoffice365.com
strings.ends_withsuffixprotection.outlook.com>