Detection rules › Sublime MQL
VIP impersonation with w2 request with reply-to mismatch
This rule detects emails attempting to impersonate a VIP requesting a W-2 with a reply-to mismatch.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | BEC/Fraud |
| Tactics and techniques | Impersonation: VIP |
Event coverage
Rule body MQL
type.inbound
and (
any($org_vips, strings.contains(sender.display_name, .display_name))
or any(regex.extract(sender.display_name, '^(?<first>\S+)\s+(?<second>\S+)$'),
any($org_vips,
strings.contains(.display_name, ..named_groups["first"])
and strings.contains(.display_name, ..named_groups["second"])
)
)
)
and not (
sender.email.domain.domain in $org_domains
and coalesce(headers.auth_summary.dmarc.pass, false)
)
// W-2 Language with a request
and (
strings.contains(strings.replace_confusables(subject.base), 'W-2')
or strings.icontains(subject.base, 'w2')
or strings.icontains(subject.base, 'wage')
or strings.icontains(subject.base, 'tax form')
or strings.icontains(subject.base, 'irs')
)
and strings.contains(body.current_thread.text, 'W-2')
and any(ml.nlu_classifier(body.current_thread.text).entities,
.name == "request"
)
// different reply-to address
and length(headers.reply_to) > 0
and sender.email.email not in map(headers.reply_to, .email.email)
// negate highly trusted sender domains unless they fail DMARC authentication
and not (
sender.email.domain.root_domain in $high_trust_sender_root_domains
and coalesce(headers.auth_summary.dmarc.pass, false)
)
Detection logic
Scope: inbound message.
This rule detects emails attempting to impersonate a VIP requesting a W-2 with a reply-to mismatch.
- inbound message
any of:
any of
$org_vipswhere:- strings.contains(sender.display_name)
any of
regex.extract(sender.display_name)where:any of
$org_vipswhere all hold:- strings.contains(.display_name)
- strings.contains(.display_name)
not:
all of:
- sender.email.domain.domain in $org_domains
- coalesce(headers.auth_summary.dmarc.pass)
any of:
- strings.replace_confusables(subject.base) contains 'W-2'
- subject.base contains 'w2'
- subject.base contains 'wage'
- subject.base contains 'tax form'
- subject.base contains 'irs'
- body.current_thread.text contains 'W-2'
any of
ml.nlu_classifier(body.current_thread.text).entitieswhere:- .name is 'request'
- length(headers.reply_to) > 0
- sender.email.email not in map(headers.reply_to, .email.email)
not:
all of:
- sender.email.domain.root_domain in $high_trust_sender_root_domains
- coalesce(headers.auth_summary.dmarc.pass)
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.reply_to, headers.reply_to[].email.email, sender.display_name, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.email, subject.base, type.inbound. Sensors: ml.nlu_classifier, regex.extract, strings.contains, strings.icontains, strings.replace_confusables. Reference lists: $high_trust_sender_root_domains, $org_domains, $org_vips.
Indicators matched (7)
| Field | Match | Value |
|---|---|---|
regex.extract | regex | ^(?<first>\S+)\s+(?<second>\S+)$ |
strings.contains | substring | W-2 |
strings.icontains | substring | w2 |
strings.icontains | substring | wage |
strings.icontains | substring | tax form |
strings.icontains | substring | irs |
ml.nlu_classifier(body.current_thread.text).entities[].name | equals | request |