Detection rules › Sublime MQL

Sublime MQL rules: lookalike

Lookalike sender domain (untrusted sender)

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

Sender's domain is a lookalike of one of your organization's domains and is untrusted.

Threat classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing, Malware/Ransomware
Tactics and techniquesLookalike domain, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule body

type.inbound
and length(sender.email.domain.sld) > 3
and sender.email.domain.domain not in $org_domains
and any($org_domains,
        // this rule can be duplicated in order to tune the threshold
        strings.ilevenshtein(sender.email.domain.domain, .) == 1
)
and (
  (
    profile.by_sender_email().prevalence in ("new", "outlier")
    and not profile.by_sender_email().solicited
  )
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().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
)
and not profile.by_sender_email().any_messages_benign

Detection logic

Scope: inbound message.

Sender's domain is a lookalike of one of your organization's domains and is untrusted.

  1. inbound message
  2. length(sender.email.domain.sld) > 3
  3. sender.email.domain.domain not in $org_domains
  4. any of $org_domains where:
    • strings.ilevenshtein(sender.email.domain.domain) is 1
  5. any of:
    • all of:
      • profile.by_sender_email().prevalence in ('new', 'outlier')
      • not:
        • profile.by_sender_email().solicited
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
  6. 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
  7. not:
    • profile.by_sender_email().any_messages_benign

Inspects: headers.auth_summary.dmarc.pass, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.domain.sld, type.inbound. Sensors: profile.by_sender_email, strings.ilevenshtein. Reference lists: $high_trust_sender_root_domains, $org_domains.

Stages and Predicates

Stage 1: mql_rule

and
  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_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().solicited"
      profile.by_sender_email func_call "profile.by_sender_email().prevalence in (new, outlier)"
  not
    profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
  any($org_domains)
    strings.ilevenshtein func_call "strings.ilevenshtein(sender.email.domain.domain) == 1"
  sender.email.domain.sld length_compare "3"
  type.inbound eq "true"
   macro "sender.email.domain.domain not in org_domains"

Indicators

These rows show field, operator, and value matches.

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

Suspected lookalike domain with suspicious language

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

This rule identifies messages where links use typosquatting or lookalike domains similar to the sender domain, with at least one domain being either unregistered or recently registered (≤90 days). The messages must also contain indicators of business email compromise (BEC), credential theft, or abusive language patterns like financial terms or polite phrasing such as kindly. This layered approach targets phishing attempts combining domain deception with manipulative content

Threat classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesEvasion, Lookalike domain, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • body.links
  • sender.email
  • type

Rule body

type.inbound

// levenshtein distance (edit distance) between the SLD of the link and the sender domain is greater than 0 and less than or equal to 2.
// This detects typosquatting or domains that are deceptively similar to the sender.
and any(body.links,
        length(.href_url.domain.sld) > 3
        and 0 < strings.levenshtein(.href_url.domain.sld,
                                    sender.email.domain.sld
        ) <= 2
        // exclude onmicrosoft.com
        and not sender.email.domain.root_domain == "onmicrosoft.com"
        and (
          // domains are not registered or registered within 90d
          // network.whois(.href_url.domain).found == false
          network.whois(.href_url.domain).days_old <= 90
          or network.whois(sender.email.domain).found == false
          or network.whois(sender.email.domain).days_old <= 90
        )
)
// the mesasge is intent is BEC or Cred Theft, or is talking about financial invoicing/banking language, or a request contains "kindly"
and any(ml.nlu_classifier(body.current_thread.text).intents,
        .name in ("bec", "cred_theft")
        or any(ml.nlu_classifier(body.current_thread.text).entities,
               .name == "financial"
               and (
                 .text in ("invoice", "banking information")
                 or .name == "request" and strings.icontains(.text, "kindly")
               )
        )
)

Detection logic

Scope: inbound message.

This rule identifies messages where links use typosquatting or lookalike domains similar to the sender domain, with at least one domain being either unregistered or recently registered (≤90 days). The messages must also contain indicators of business email compromise (BEC), credential theft, or abusive language patterns like financial terms or polite phrasing such as kindly. This layered approach targets phishing attempts combining domain deception with manipulative content

  1. inbound message
  2. any of body.links where all hold:
    • length(.href_url.domain.sld) > 3
    • all of:
      • strings.levenshtein(.href_url.domain.sld) > 0
      • strings.levenshtein(.href_url.domain.sld) ≤ 2
    • not:
      • sender.email.domain.root_domain is 'onmicrosoft.com'
    • any of:
      • network.whois(.href_url.domain).days_old ≤ 90
      • network.whois(sender.email.domain).found is False
      • network.whois(sender.email.domain).days_old ≤ 90
  3. any of ml.nlu_classifier(body.current_thread.text).intents where any holds:
    • .name in ('bec', 'cred_theft')
    • any of ml.nlu_classifier(body.current_thread.text).entities where all hold:
      • .name is 'financial'
      • any of:
        • .text in ('invoice', 'banking information')
        • all of:
          • .name is 'request'
          • .text contains 'kindly'

Inspects: body.current_thread.text, body.links, body.links[].href_url.domain, body.links[].href_url.domain.sld, sender.email.domain, sender.email.domain.root_domain, sender.email.domain.sld, type.inbound. Sensors: ml.nlu_classifier, network.whois, strings.icontains, strings.levenshtein.

Indicators matched (7)

FieldMatchValue
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).entities[].nameequalsfinancial
ml.nlu_classifier(body.current_thread.text).entities[].textmemberinvoice
ml.nlu_classifier(body.current_thread.text).entities[].textmemberbanking information
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsrequest
strings.icontainssubstringkindly

Stages and Predicates

Stage 1: mql_rule

and
  any(ml.nlu_classifier(body.current_thread.text).intents)
    or
      any(ml.nlu_classifier(body.current_thread.text).entities)
        and
          or
            and
              ml.nlu_classifier(body.current_thread.text).entities.name eq "request"
              ml.nlu_classifier(body.current_thread.text).entities.text contains "kindly"
            ml.nlu_classifier(body.current_thread.text).entities.text in ["banking information", "invoice"]
          ml.nlu_classifier(body.current_thread.text).entities.name eq "financial"
      ml.nlu_classifier(body.current_thread.text).intents.name in ["bec", "cred_theft"]
  any(body.links)
    and
      or
        network.whois func_call "network.whois(body.links[].href_url.domain).days_old <= 90"
        network.whois func_call "network.whois(sender.email.domain).days_old <= 90"
        network.whois func_call "network.whois(sender.email.domain).found == false"
      not
        sender.email.domain.root_domain eq "onmicrosoft.com"
      body.links.href_url.domain.sld length_compare "3"
      strings.levenshtein func_call "strings.levenshtein(body.links[].href_url.domain.sld) <= 2"
      strings.levenshtein func_call "strings.levenshtein(body.links[].href_url.domain.sld) > 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"