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) == 0
    • all of recipients.to where:
      • .display_name is 'Undisclosed recipients'
  4. length(recipients.cc) == 0
  5. length(recipients.bcc) == 0
  6. none of:
    • any of headers.hops where:
      • any of .fields where:
        • .name is 'List-Unsubscribe'
    • any(ml.nlu_classifier(body.current_thread.text).intents, .name == "benign" and .confidence == "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.root_domain macro "body.links[].href_url.domain.root_domain in free_subdomain_hosts"
      body.links.href_url.domain.subdomain is_not_null
      body.links.href_url.domain.subdomain ne "www"
  not
    or
      any(headers.hops)
        any(headers.hops.fields)
          headers.hops.fields.name eq "List-Unsubscribe"
       macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n         .name == \"benign\" and .confidence == \"high\"\n  )"
  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, .display_name == \"Undisclosed recipients\")"
  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 corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops

Suspicious recipients pattern with NLU credential theft indicators

#

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) == 0
    • all of recipients.to where:
      • .display_name is 'Undisclosed recipients'
  3. length(recipients.cc) == 0
  4. length(recipients.bcc) == 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(ml.nlu_classifier(body.current_thread.text).intents, .name in ("bec", "cred_theft", "advance_fee") and .confidence == "high" ) )
    • any of body.links where:
      • any([ml.link_analysis(.)], .credphish.disposition == "phishing" and .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
    and
      any(headers.hops)
        and
          not
            headers.hops.authentication_results.compauth.verdict in ["pass", "softpass"]
          headers.hops.authentication_results.compauth.verdict is_not_null
      any(body.links)
         macro "any([ml.link_analysis(.)],\n            .credphish.disposition == \"phishing\"\n            and .credphish.confidence in (\"high\")\n        )"
    and
      any(headers.hops)
        and
          not
            headers.hops.authentication_results.compauth.verdict in ["pass", "softpass"]
          headers.hops.authentication_results.compauth.verdict is_not_null
       macro "(\n    any(ml.nlu_classifier(body.current_thread.text).intents,\n        .name in (\"bec\", \"cred_theft\", \"advance_fee\") and .confidence == \"high\"\n    )\n  )"
    and
      any(body.links)
         macro "any([ml.link_analysis(.)],\n            .credphish.disposition == \"phishing\"\n            and .credphish.confidence in (\"high\")\n        )"
       macro "(\n    any(ml.nlu_classifier(body.current_thread.text).intents,\n        .name in (\"bec\", \"cred_theft\", \"advance_fee\") and .confidence == \"high\"\n    )\n  )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain 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, .display_name == \"Undisclosed recipients\")"
  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 corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Back to all Sublime MQL rules