Detection rules › Sublime MQL

Sublime MQL rules: recipients

Link: Free subdomain host with undisclosed recipients

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

Detects messages with undisclosed recipients, containing links to free subdomain hosts

Threat classification

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

CategoryValues
Tactics and techniquesFree subdomain host

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • body.links
  • headers
  • headers.hops
  • recipients
  • recipients.to
  • type

Rule body

type.inbound
and any(body.links,
        .href_url.domain.root_domain in $free_subdomain_hosts
        and .href_url.domain.subdomain is not null
        and .href_url.domain.subdomain != "www"
        and not (
          .href_url.domain.root_domain == "googleusercontent.com"
          and strings.istarts_with(.href_url.path, "/mail-sig")
        )
)
and (
  length(recipients.to) == 0
  or all(recipients.to, .display_name == "Undisclosed recipients")
)
and length(recipients.cc) == 0
and length(recipients.bcc) == 0

// negate listmailers & benign threads
and not (
  any(headers.hops, any(.fields, .name == "List-Unsubscribe"))
  or any(ml.nlu_classifier(body.current_thread.text).intents,
         .name == "benign" and .confidence == "high"
  )
)
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.

Detects messages with undisclosed recipients, containing links to free subdomain hosts

  1. inbound message
  2. any of body.links where all hold:
    • .href_url.domain.root_domain in $free_subdomain_hosts
    • .href_url.domain.subdomain is set
    • .href_url.domain.subdomain is not 'www'
    • not:
      • all of:
        • .href_url.domain.root_domain is 'googleusercontent.com'
        • .href_url.path starts with '/mail-sig'
  3. any of:
    • length(recipients.to) is 0
    • all of recipients.to where:
      • .display_name is 'Undisclosed recipients'
  4. length(recipients.cc) is 0
  5. length(recipients.bcc) is 0
  6. none of:
    • any of headers.hops where:
      • any of .fields where:
        • .name is 'List-Unsubscribe'
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'benign'
      • .confidence is 'high'
  7. any of:
    • profile.by_sender().prevalence in ('new', 'outlier')
    • profile.by_sender().any_messages_malicious_or_spam
  8. not:
    • profile.by_sender().any_messages_benign

Inspects: body.current_thread.text, body.links, body.links[].href_url.domain.root_domain, body.links[].href_url.domain.subdomain, body.links[].href_url.path, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, recipients.bcc, recipients.cc, recipients.to, recipients.to[].display_name, type.inbound. Sensors: ml.nlu_classifier, profile.by_sender, strings.istarts_with. Reference lists: $free_subdomain_hosts.

Indicators matched (1)

FieldMatchValue
recipients.to[].display_nameequalsUndisclosed recipients

Stages and Predicates

Stage 1: mql_rule

and
  any(body.links)
    and
      not
        and
          body.links.href_url.domain.root_domain eq "googleusercontent.com"
          body.links.href_url.path starts_with "/mail-sig"
      body.links.href_url.domain.subdomain is_not_null
      body.links.href_url.domain.subdomain ne "www"
       macro "body.links[].href_url.domain.root_domain in free_subdomain_hosts"
  not
    or
      any(headers.hops)
        any(headers.hops.fields)
          headers.hops.fields.name eq "List-Unsubscribe"
      any(ml.nlu_classifier(body.current_thread.text).intents)
        and
          ml.nlu_classifier(body.current_thread.text).intents.confidence eq "high"
          ml.nlu_classifier(body.current_thread.text).intents.name eq "benign"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  or
    profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    profile.by_sender func_call "profile.by_sender().prevalence in (new, outlier)"
  or
    recipients.to length_compare "0"
     macro "all(recipients.to)"
  recipients.bcc length_compare "0"
  recipients.cc length_compare "0"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops
ml.nlu_classifier(body.current_thread.text).intentsarray_any(no value, null check)excludes:ml.nlu_classifier(body.current_thread.text).intents

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Suspicious recipients pattern with NLU credential theft indicators

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

Detects messages with undisclosed recipients (likely all bcc) and NLU identified a credential theft intent with medium to high confidence from a suspicious low reputation link domain

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • body.links
  • recipients
  • recipients.to
  • type

Rule body

type.inbound
and (
  length(recipients.to) == 0
  or all(recipients.to, strings.ilike(.display_name, "undisclosed?recipients"))
)
and length(recipients.cc) == 0
and 0 <= length(recipients.bcc) <= 1
and any(body.links, .href_url.domain.root_domain not in $tranco_1m)
and (
  any(body.links,
      regex.icontains(.display_text,
                      '(view|click|download|goto)?(attachment|download|file|online|document)s?'
      )
      or all(body.links, regex.match(.display_text, "[A-Z ]+"))
  )
)
and any(ml.nlu_classifier(body.current_thread.text).intents,
        .name in ("cred_theft") and .confidence in ("medium", "high")
)

Detection logic

Scope: inbound message.

Detects messages with undisclosed recipients (likely all bcc) and NLU identified a credential theft intent with medium to high confidence from a suspicious low reputation link domain

  1. inbound message
  2. any of:
    • length(recipients.to) is 0
    • all of recipients.to where:
      • .display_name matches 'undisclosed?recipients'
  3. length(recipients.cc) is 0
  4. all of:
    • length(recipients.bcc) ≥ 0
    • length(recipients.bcc) ≤ 1
  5. any of body.links where:
    • .href_url.domain.root_domain not in $tranco_1m
  6. any of body.links where any holds:
    • .display_text matches '(view|click|download|goto)?(attachment|download|file|online|document)s?'
    • all of body.links where:
      • .display_text matches '[A-Z ]+'
  7. any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
    • .name in ('cred_theft')
    • .confidence in ('medium', 'high')

Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.root_domain, recipients.bcc, recipients.cc, recipients.to, recipients.to[].display_name, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, regex.match, strings.ilike. Reference lists: $tranco_1m.

Indicators matched (6)

FieldMatchValue
strings.ilikesubstringundisclosed?recipients
regex.icontainsregex(view|click|download|goto)?(attachment|download|file|online|document)s?
regex.matchregex[A-Z ]+
ml.nlu_classifier(body.current_thread.text).intents[].namemembercred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidencemembermedium
ml.nlu_classifier(body.current_thread.text).intents[].confidencememberhigh

Stages and Predicates

Stage 1: mql_rule

and
  any(body.links)
    or
      body.links.display_text regex_match "(view|click|download|goto)?(attachment|download|file|online|document)s?"
       macro "all(body.links)"
  any(ml.nlu_classifier(body.current_thread.text).intents)
    and
      ml.nlu_classifier(body.current_thread.text).intents.confidence in ["high", "medium"]
      ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
  or
    recipients.to length_compare "0"
     macro "all(recipients.to)"
  any(body.links)
     macro "body.links[].href_url.domain.root_domain not in tranco_1m"
  recipients.bcc length_compare "0"
  recipients.bcc length_compare "1"
  recipients.cc length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Suspicious recipients pattern with no Compauth pass and suspicious content

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

Detects messages with undisclosed recipients (likely all bcc), where the Compauth verdict is not 'pass', and ML has identified suspicious language or credential phishing links.

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • headers.hops
  • recipients
  • recipients.to
  • sender.email
  • type

Rule body

type.inbound
and (
  length(recipients.to) == 0
  or all(recipients.to, .display_name == "Undisclosed recipients")
)
and length(recipients.cc) == 0
and length(recipients.bcc) == 0
and 2 of (
  (
    any(headers.hops,
        .authentication_results.compauth.verdict is not null
        and .authentication_results.compauth.verdict not in ("pass", "softpass")
    )
  ),
  (
    any(ml.nlu_classifier(body.current_thread.text).intents,
        .name in ("bec", "cred_theft", "advance_fee") and .confidence == "high"
    )
  ),
  (
    any(body.links,
        any([ml.link_analysis(.)],
            .credphish.disposition == "phishing"
            and .credphish.confidence in ("high")
        )
    )
  )
)
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
  )
)
// 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 messages with undisclosed recipients (likely all bcc), where the Compauth verdict is not 'pass', and ML has identified suspicious language or credential phishing links.

  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. at least 2 of:
    • any of headers.hops where all hold:
      • .authentication_results.compauth.verdict is set
      • .authentication_results.compauth.verdict not in ('pass', 'softpass')
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name in ('bec', 'cred_theft', 'advance_fee')
      • .confidence is 'high'
    • any of body.links where:
      • any of [ml.link_analysis(.)] where all hold:
        • .credphish.disposition is 'phishing'
        • .credphish.confidence in ('high')
  6. 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
  7. 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, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].authentication_results.compauth.verdict, recipients.bcc, recipients.cc, recipients.to, recipients.to[].display_name, sender.email.domain.root_domain, type.inbound. Sensors: ml.link_analysis, ml.nlu_classifier, profile.by_sender. Reference lists: $high_trust_sender_root_domains.

Indicators matched (7)

FieldMatchValue
recipients.to[].display_nameequalsUndisclosed recipients
ml.nlu_classifier(body.current_thread.text).intents[].namememberbec
ml.nlu_classifier(body.current_thread.text).intents[].namemembercred_theft
ml.nlu_classifier(body.current_thread.text).intents[].namememberadvance_fee
ml.nlu_classifier(body.current_thread.text).intents[].confidenceequalshigh
[ml.link_analysis(body.links[])][].credphish.dispositionequalsphishing
[ml.link_analysis(body.links[])][].credphish.confidencememberhigh

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(body.links)
      any([ml.link_analysis(body.links)])
        and
          [ml.link_analysis(body.links[])][].credphish.confidence eq "high"
          [ml.link_analysis(body.links[])][].credphish.disposition eq "phishing"
    any(headers.hops)
      and
        not
          headers.hops.authentication_results.compauth.verdict in ["pass", "softpass"]
        headers.hops.authentication_results.compauth.verdict is_not_null
    any(ml.nlu_classifier(body.current_thread.text).intents)
      and
        ml.nlu_classifier(body.current_thread.text).intents.confidence eq "high"
        ml.nlu_classifier(body.current_thread.text).intents.name in ["advance_fee", "bec", "cred_theft"]
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    profile.by_sender func_call "profile.by_sender().prevalence in (new, outlier)"
  or
    recipients.to length_compare "0"
     macro "all(recipients.to)"
  recipients.bcc length_compare "0"
  recipients.cc length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"