Detection rules › Sublime MQL

Fake message thread with a suspicious link and engaging language from an unknown sender

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

Detects fake message threads with suspicious links and financial request language

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesSocial engineering

Event coverage

Rule body MQL

type.inbound
and length(body.links) < 10

// fake thread check
and (subject.is_reply or subject.is_forward)

// Check for the Presence of References or In-Reply-To properties
and (
  (length(headers.references) == 0 and headers.in_reply_to is null)
  or headers.in_reply_to is null
)

// sender's domain is not in body, and body has > 0 links
and length(body.links) > 0
and sender.email.domain.root_domain not in $free_email_providers
and not any(body.links,
            .href_url.domain.root_domain == sender.email.domain.root_domain
)

// unusual sender (email address rarely sends to your organization)
and sender.email.email not in $sender_emails

// unusual sender domain (domain rarely sends to your organization)
and sender.email.domain.domain not in $sender_domains
and 4 of (
  // language attempting to engage
  (
    any(ml.nlu_classifier(body.current_thread.text).entities,
        .name == "request"
    )
    and any(ml.nlu_classifier(body.current_thread.text).entities,
            .name == "financial"
    )
  ),

  // invoicing language
  any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice"),

  // urgency request
  any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency"),

  // cred_theft detection
  any(ml.nlu_classifier(body.current_thread.text).intents,
      .name == "cred_theft" and .confidence in~ ("medium", "high")
  ),

  // commonly abused sender TLD
  strings.ilike(sender.email.domain.tld, "*.jp"),

  // headers traverse abused TLD
  any(headers.domains, strings.ilike(.tld, "*.jp")),

  // known suspicious pattern in the URL path
  any(body.links, regex.match(.href_url.path, '\/[a-z]{3}\d[a-z]')),

  // link display text is in all caps
  any(body.links, regex.match(.display_text, '[A-Z ]+')),

  // display name contains an email
  regex.contains(sender.display_name, '[a-z0-9]+@[a-z]+'),

  // Sender domain is empty
  sender.email.domain.domain == "",

  // sender domain matches no body domains
  all(body.links,
      .href_url.domain.root_domain != sender.email.domain.root_domain
  ),
)

// 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
)

Detection logic

Scope: inbound message.

Detects fake message threads with suspicious links and financial request language

  1. inbound message
  2. length(body.links) < 10
  3. any of:
    • subject.is_reply
    • subject.is_forward
  4. any of:
    • all of:
      • length(headers.references) is 0
      • headers.in_reply_to is missing
    • headers.in_reply_to is missing
  5. length(body.links) > 0
  6. sender.email.domain.root_domain not in $free_email_providers
  7. not:
    • any of body.links where:
      • .href_url.domain.root_domain is sender.email.domain.root_domain
  8. sender.email.email not in $sender_emails
  9. sender.email.domain.domain not in $sender_domains
  10. at least 4 of:
    • all of:
      • any of ml.nlu_classifier(body.current_thread.text).entities where:
        • .name is 'request'
      • any of ml.nlu_classifier(body.current_thread.text).entities where:
        • .name is 'financial'
    • any of ml.nlu_classifier(body.current_thread.text).tags where:
      • .name is 'invoice'
    • any of ml.nlu_classifier(body.current_thread.text).entities where:
      • .name is 'urgency'
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'cred_theft'
      • .confidence in ('medium', 'high')
    • sender.email.domain.tld matches '*.jp'
    • any of headers.domains where:
      • .tld matches '*.jp'
    • any of body.links where:
      • .href_url.path matches '\\/[a-z]{3}\\d[a-z]'
    • any of body.links where:
      • .display_text matches '[A-Z ]+'
    • sender.display_name matches '[a-z0-9]+@[a-z]+'
    • sender.email.domain.domain is ''
    • all of body.links where:
      • .href_url.domain.root_domain is not sender.email.domain.root_domain
  11. 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

Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.root_domain, body.links[].href_url.path, headers.auth_summary.dmarc.pass, headers.domains, headers.domains[].tld, headers.in_reply_to, headers.references, sender.display_name, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.domain.tld, sender.email.email, subject.is_forward, subject.is_reply, type.inbound. Sensors: ml.nlu_classifier, regex.contains, regex.match, strings.ilike. Reference lists: $free_email_providers, $high_trust_sender_root_domains, $sender_domains, $sender_emails.

Indicators matched (12)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsrequest
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsfinancial
ml.nlu_classifier(body.current_thread.text).tags[].nameequalsinvoice
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsurgency
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidencemembermedium
ml.nlu_classifier(body.current_thread.text).intents[].confidencememberhigh
strings.ilikesubstring*.jp
regex.matchregex\/[a-z]{3}\d[a-z]
regex.matchregex[A-Z ]+
regex.containsregex[a-z0-9]+@[a-z]+
sender.email.domain.domainequals