Detection rules › Sublime MQL

Credential Phishing: Suspicious language, link, recipients and other indicators

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

The rule flags inbound messages with no visible recipients, contain all-caps text, and include links from certain free hosts. It also checks for signs of credential theft using machine learning classifiers and is from an untrusted sender.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion

Event coverage

Rule body MQL

type.inbound

// no recipients defined
and (
  length(recipients.to) == 0
  or all(recipients.to, .display_name == "Undisclosed recipients")
)
and length(recipients.cc) == 0
and length(recipients.bcc) == 0
and any(body.links,

        // suspicious link
        // we've particularly seen 1drv.ms abused
        // if using the full list causes FPs, we can reduce the 
        // scope to a hard-coded list or add exclusions
        (
          .href_url.domain.domain in $free_file_hosts
          or .href_url.domain.root_domain in $free_file_hosts
          or .href_url.domain.root_domain in $free_subdomain_hosts
        )

        // link text is in all caps
        and regex.match(.display_text, "[A-Z ]+")
)

// any confidence cred_theft classification
and any(ml.nlu_classifier(body.current_thread.text).intents,
        .name == "cred_theft"
)

// 'org' entity is in all caps
and any(ml.nlu_classifier(body.current_thread.text).entities,
        .name == "org" and regex.match(.text, "[A-Z ]+")
)

// subject is in all caps
and regex.match(subject.subject, "[A-Z ]+")
and (
  profile.by_sender().prevalence in ("new", "outlier")
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection logic

Scope: inbound message.

The rule flags inbound messages with no visible recipients, contain all-caps text, and include links from certain free hosts. It also checks for signs of credential theft using machine learning classifiers and is from an untrusted sender.

  1. inbound message
  2. any of:
    • length(recipients.to) is 0
    • all of recipients.to where:
      • .display_name is 'Undisclosed recipients'
  3. length(recipients.cc) is 0
  4. length(recipients.bcc) is 0
  5. any of body.links where all hold:
    • any of:
      • .href_url.domain.domain in $free_file_hosts
      • .href_url.domain.root_domain in $free_file_hosts
      • .href_url.domain.root_domain in $free_subdomain_hosts
    • .display_text matches '[A-Z ]+'
  6. any of ml.nlu_classifier(body.current_thread.text).intents where:
    • .name is 'cred_theft'
  7. any of ml.nlu_classifier(body.current_thread.text).entities where all hold:
    • .name is 'org'
    • .text matches '[A-Z ]+'
  8. subject.subject matches '[A-Z ]+'
  9. any of:
    • profile.by_sender().prevalence in ('new', 'outlier')
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.domain, body.links[].href_url.domain.root_domain, recipients.bcc, recipients.cc, recipients.to, recipients.to[].display_name, subject.subject, type.inbound. Sensors: ml.nlu_classifier, profile.by_sender, regex.match. Reference lists: $free_file_hosts, $free_subdomain_hosts.

Indicators matched (4)

FieldMatchValue
recipients.to[].display_nameequalsUndisclosed recipients
regex.matchregex[A-Z ]+
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsorg