Detection rules › Sublime MQL
Business Email Compromise: Request for mobile number via reply thread hijacking
This rule detects BEC attacks that use reply threads to solicit mobile numbers, evading detection rules that exclude RE: subjects.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | BEC/Fraud |
| Tactics and techniques | Social engineering |
Event coverage
Rule body MQL
type.inbound
and 0 < length(body.previous_threads) < 3
and length(attachments) == 0
// Check previous_threads for mobile solicitation patterns
and any(body.previous_threads,
(
length(.text) < 500
// ignore disclaimers in body length calculation
or (
any(map(filter(ml.nlu_classifier(.text).entities,
.name == "disclaimer"
),
.text
),
(length(..text) - length(.)) < 500
)
)
)
and regex.icontains(.text,
'(?:mobile|suitable|contact|current|cell|call|another).{0,10}(phone|number|#|\bno)|whatsapp|\bcell|personalcell|(?:reliable|recent).{0,30}(?:phone|number).{0,15}contact|(?:share|send|confirm).{0,20}number.{0,25}(?:text|sms|whatsapp|contact|reach\syou[\s,.\?](?:by|whether|when|for))'
)
)
// NLU analysis on previous_threads content
and (
any(body.previous_threads,
any(ml.nlu_classifier(.text).intents,
.name in ("bec", "advance_fee") and .confidence in ("medium", "high")
)
)
or (
// confidence can be low on very short bodies
any(body.previous_threads, length(.text) < 550)
and (
any(body.previous_threads,
any(ml.nlu_classifier(.text).intents, .name == "bec")
)
or any(ml.nlu_classifier(sender.display_name).intents, .name == "bec")
or any(body.previous_threads,
any(ml.nlu_classifier(.text).entities,
strings.icontains(.text, "kindly")
)
)
)
)
)
// Sender analysis
and (
not profile.by_sender().solicited
or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign
// not high trust sender domains
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
)
// Ensure this is likely a hijacked thread (sender doesn't match thread participants)
and (length(headers.references) > 0 or headers.in_reply_to is not null)
Detection logic
Scope: inbound message.
This rule detects BEC attacks that use reply threads to solicit mobile numbers, evading detection rules that exclude RE: subjects.
- inbound message
all of:
- length(body.previous_threads) > 0
- length(body.previous_threads) < 3
- length(attachments) is 0
any of
body.previous_threadswhere all hold:any of:
- length(.text) < 500
any of
map(...)where:- length(.text) - length(.) < 500
- .text matches '(?:mobile|suitable|contact|current|cell|call|another).{0,10}(phone|number|#|\\bno)|whatsapp|\\bcell|personalcell|(?:reliable|recent).{0,30}(?:phone|number).{0,15}contact|(?:share|send|confirm).{0,20}number.{0,25}(?:text|sms|whatsapp|contact|reach\\syou[\\s,.\\?](?:by|whether|when|for))'
any of:
any of
body.previous_threadswhere:any of
ml.nlu_classifier(.text).intentswhere all hold:- .name in ('bec', 'advance_fee')
- .confidence in ('medium', 'high')
all of:
any of
body.previous_threadswhere:- length(.text) < 550
any of:
any of
body.previous_threadswhere:any of
ml.nlu_classifier(.text).intentswhere:- .name is 'bec'
any of
ml.nlu_classifier(sender.display_name).intentswhere:- .name is 'bec'
any of
body.previous_threadswhere:any of
ml.nlu_classifier(.text).entitieswhere:- .text contains 'kindly'
any of:
not:
- profile.by_sender().solicited
- profile.by_sender().any_messages_malicious_or_spam
not:
- profile.by_sender().any_messages_benign
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
any of:
- length(headers.references) > 0
- headers.in_reply_to is set
Inspects: body.previous_threads, body.previous_threads[].text, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, sender.display_name, sender.email.domain.root_domain, type.inbound. Sensors: ml.nlu_classifier, profile.by_sender, regex.icontains, strings.icontains. Reference lists: $high_trust_sender_root_domains.
Indicators matched (9)
| Field | Match | Value |
|---|---|---|
ml.nlu_classifier(body.previous_threads[].text).entities[].name | equals | disclaimer |
regex.icontains | regex | (?:mobile|suitable|contact|current|cell|call|another).{0,10}(phone|number|#|\bno)|whatsapp|\bcell|personalcell|(?:reliable|recent).{0,30}(?:phone|number).{0,15}contact|(?:share|send|confirm).{0,20}number.{0,25}(?:text|sms|whatsapp|contact|reach\syou[\s,.\?](?:by|whether|when|for)) |
ml.nlu_classifier(body.previous_threads[].text).intents[].name | member | bec |
ml.nlu_classifier(body.previous_threads[].text).intents[].name | member | advance_fee |
ml.nlu_classifier(body.previous_threads[].text).intents[].confidence | member | medium |
ml.nlu_classifier(body.previous_threads[].text).intents[].confidence | member | high |
ml.nlu_classifier(body.previous_threads[].text).intents[].name | equals | bec |
ml.nlu_classifier(sender.display_name).intents[].name | equals | bec |
strings.icontains | substring | kindly |