Detection rules › Sublime MQL

Sublime MQL rules: vendor

Vendor impersonation: Thread hijacking with typosquat domain

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

Detects potential thread hijacking where the sender uses a domain similar to known senders, exhibits BEC behavior, and shows signs of compromised thread continuity through domain spoofing or thread manipulation.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesLookalike domain, Social engineering, Spoofing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • body.current_thread
  • body.previous_threads
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and subject.is_reply
and sender.email.domain.root_domain not in $sender_domains
// current sender has not been seen in the thread before
and any(body.previous_threads, .sender.email.domain.domain not in $org_domains)
and all(body.previous_threads,
        .sender.email.domain.domain != sender.email.domain.domain
        and all(.recipients.to,
                .email.domain.domain != sender.email.domain.domain
        )
        and all(.recipients.cc,
                .email.domain.domain != sender.email.domain.domain
        )
)
and any($sender_domains,
        0 < strings.ilevenshtein(., sender.email.domain.root_domain) < 3
)
and any(ml.nlu_classifier(body.current_thread.text).intents,
        .name == "bec" and .confidence != "low"
)
// risky category
and any(ml.nlu_classifier(body.current_thread.text).topics,
        .name in (
          "Financial Communications",
          "E-Signature",
          "Benefit Enrollment"
        )
        and .confidence == "high"
)
and 1 of (
  not network.whois(sender.email.domain).found,
  any(body.previous_threads, strings.icontains(.preamble, sender.display_name))
)
and (
  profile.by_sender_domain().prevalence == "new"
  or profile.by_sender_domain().days_known < 3
)

Detection Logic

Scope: inbound message.

Detects potential thread hijacking where the sender uses a domain similar to known senders, exhibits BEC behavior, and shows signs of compromised thread continuity through domain spoofing or thread manipulation.

  1. inbound message
  2. subject.is_reply
  3. sender.email.domain.root_domain not in $sender_domains
  4. any of body.previous_threads where:
    • .sender.email.domain.domain not in $org_domains
  5. all of body.previous_threads where all hold:
    • .sender.email.domain.domain is not sender.email.domain.domain
    • all of .recipients.to where:
      • .email.domain.domain is not sender.email.domain.domain
    • all of .recipients.cc where:
      • .email.domain.domain is not sender.email.domain.domain
  6. any($sender_domains, 0 < strings.ilevenshtein(., sender.email.domain.root_domain) < 3 )
  7. any(ml.nlu_classifier(body.current_thread.text).intents, .name == "bec" and .confidence != "low" )
  8. any(ml.nlu_classifier(body.current_thread.text).topics, .name in ( "Financial Communications", "E-Signature", "Benefit Enrollment" ) and .confidence == "high" )
  9. at least 1 of:
    • not:
      • network.whois(sender.email.domain).found
    • any of body.previous_threads where:
      • strings.icontains(.preamble, sender.display_name)
  10. any of:
    • profile.by_sender_domain().prevalence == "new"
    • profile.by_sender_domain().days_known < 3

Inspects: body.current_thread.text, body.previous_threads, body.previous_threads[].preamble, body.previous_threads[].recipients.cc, body.previous_threads[].recipients.cc[].email.domain.domain, body.previous_threads[].recipients.to, body.previous_threads[].recipients.to[].email.domain.domain, body.previous_threads[].sender.email.domain.domain, sender.display_name, sender.email.domain, sender.email.domain.domain, sender.email.domain.root_domain, subject.is_reply, type.inbound. Sensors: ml.nlu_classifier, network.whois, profile.by_sender_domain, strings.icontains, strings.ilevenshtein. Reference lists: $org_domains, $sender_domains.

Indicators Matched (5)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).intents[].nameequalsbec
ml.nlu_classifier(body.current_thread.text).topics[].namememberFinancial Communications
ml.nlu_classifier(body.current_thread.text).topics[].namememberE-Signature
ml.nlu_classifier(body.current_thread.text).topics[].namememberBenefit Enrollment
ml.nlu_classifier(body.current_thread.text).topics[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  or
    not
      network.whois func_call "network.whois(sender.email.domain).found"
    any(body.previous_threads)
      strings.icontains func_call "strings.icontains(.preamble, sender.display_name)"
  any(body.previous_threads)
    body.previous_threads.sender.email.domain.domain macro "body.previous_threads[].sender.email.domain.domain not in org_domains"
  or
    profile.by_sender_domain func_call "profile.by_sender_domain().days_known < 3"
    profile.by_sender_domain func_call "profile.by_sender_domain().prevalence == \"new\""
  sender.email.domain.root_domain macro "sender.email.domain.root_domain not in sender_domains"
  subject.is_reply eq "true"
  type.inbound eq "true"
   macro "all(body.previous_threads,\n        .sender.email.domain.domain != sender.email.domain.domain\n        and all(.recipients.to,\n                .email.domain.domain != sender.email.domain.domain\n        )\n        and all(.recipients.cc,\n                .email.domain.domain != sender.email.domain.domain\n        )\n)"
   macro "any($sender_domains,\n        0 < strings.ilevenshtein(., sender.email.domain.root_domain) < 3\n)"
   macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n        .name == \"bec\" and .confidence != \"low\"\n)"
   macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n        .name in (\n          \"Financial Communications\",\n          \"E-Signature\",\n          \"Benefit Enrollment\"\n        )\n        and .confidence == \"high\"\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
subject.is_replyeq
  • true transforms: boolean corpus 11 (mql 11)
field:"subject.is_reply" kind:eq value:"true"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Back to all Sublime MQL rules