Detection rules › Sublime MQL
Sublime MQL rules: vendor
| Rule | Severity |
|---|---|
| Vendor impersonation: Thread hijacking with typosquat domain | high |
Vendor impersonation: Thread hijacking with typosquat domain
#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).
| Category | Values |
|---|---|
| Attack types | BEC/Fraud |
| Tactics and techniques | Lookalike domain, Social engineering, Spoofing |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message attributes
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.
- inbound message
- subject.is_reply
- sender.email.domain.root_domain not in $sender_domains
any of
body.previous_threadswhere:- .sender.email.domain.domain not in $org_domains
all of
body.previous_threadswhere all hold:- .sender.email.domain.domain is not sender.email.domain.domain
all of
.recipients.towhere:- .email.domain.domain is not sender.email.domain.domain
all of
.recipients.ccwhere:- .email.domain.domain is not sender.email.domain.domain
any of
$sender_domainswhere all hold:- strings.ilevenshtein(.) > 0
- strings.ilevenshtein(.) < 3
any of
ml.nlu_classifier(body.current_thread.text).intentswhere all hold:- .name is 'bec'
- .confidence is not 'low'
any of
ml.nlu_classifier(body.current_thread.text).topicswhere all hold:- .name in ('Financial Communications', 'E-Signature', 'Benefit Enrollment')
- .confidence is 'high'
at least 1 of:
not:
- network.whois(sender.email.domain).found
any of
body.previous_threadswhere:- strings.icontains(.preamble)
any of:
- profile.by_sender_domain().prevalence is '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)
| Field | Match | Value |
|---|---|---|
ml.nlu_classifier(body.current_thread.text).intents[].name | equals | bec |
ml.nlu_classifier(body.current_thread.text).topics[].name | member | Financial Communications |
ml.nlu_classifier(body.current_thread.text).topics[].name | member | E-Signature |
ml.nlu_classifier(body.current_thread.text).topics[].name | member | Benefit Enrollment |
ml.nlu_classifier(body.current_thread.text).topics[].confidence | equals | high |
Stages and Predicates
Stage 1: mql_rule
and
any(ml.nlu_classifier(body.current_thread.text).intents)
and
ml.nlu_classifier(body.current_thread.text).intents.confidence ne "low"
ml.nlu_classifier(body.current_thread.text).intents.name eq "bec"
any(ml.nlu_classifier(body.current_thread.text).topics)
and
ml.nlu_classifier(body.current_thread.text).topics.confidence eq "high"
ml.nlu_classifier(body.current_thread.text).topics.name in ["Benefit Enrollment", "E-Signature", "Financial Communications"]
or
not
network.whois func_call "network.whois(sender.email.domain).found"
any(body.previous_threads)
strings.icontains func_call "strings.icontains(body.previous_threads[].preamble)"
any($sender_domains)
and
strings.ilevenshtein func_call "strings.ilevenshtein($sender_domains[]) < 3"
strings.ilevenshtein func_call "strings.ilevenshtein($sender_domains[]) > 0"
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"
any(body.previous_threads)
macro "body.previous_threads[].sender.email.domain.domain not in org_domains"
subject.is_reply eq "true"
type.inbound eq "true"
macro "all(body.previous_threads)"
macro "sender.email.domain.root_domain not in sender_domains"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
subject.is_reply | eq |
| field:"subject.is_reply" kind:eq value:"true" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |