Detection rules › Sublime MQL
Sublime MQL rules: recipient
| Rule | Severity |
|---|---|
| Body HTML: Recipient SLD in HTML class | medium |
Body HTML: Recipient SLD in HTML class
#Detects when there is a single recipient within $org_domains where the domain SLD is concealed within HTML class attributes. The message comes from either an unauthenticated trusted sender or an untrusted source.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Evasion, Social engineering |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message attributes
Rule body
type.inbound
// not an org_domain which passed dmarc
and not (
sender.email.domain.domain in $org_domains
and coalesce(headers.auth_summary.dmarc.pass, false)
)
// a single recipient within the org_domains
and (
length(recipients.to) == 1
and all(recipients.to, .email.domain.domain in $org_domains)
)
// there are more than 30 class attributes containing the recipient's SLD
and length(filter(html.xpath(body.html, '//@class').nodes,
any(recipients.to,
// the class name is the same
..raw =~ .email.domain.sld
// a specific observed pattern with a prefix of x_hz
or strings.istarts_with(..raw,
strings.concat('x_hz',
.email.domain.sld
)
)
)
)
) > 30
// 80% or more the class attributes contain the recipient's SLD
and ratio(html.xpath(body.html, '//@class').nodes,
any(recipients.to,
// the class name is the same
..raw =~ .email.domain.sld
// a specific observed pattern with a prefix of x_hz
or strings.istarts_with(..raw,
strings.concat('x_hz', .email.domain.sld)
)
)
) > 0.80
// not replies
and not (length(headers.references) > 0 or headers.in_reply_to is not null)
// 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
)
Detection logic
Scope: inbound message.
Detects when there is a single recipient within $org_domains where the domain SLD is concealed within HTML class attributes. The message comes from either an unauthenticated trusted sender or an untrusted source.
- inbound message
not:
all of:
- sender.email.domain.domain in $org_domains
- coalesce(headers.auth_summary.dmarc.pass)
all of:
- length(recipients.to) is 1
all of
recipients.towhere:- .email.domain.domain in $org_domains
- length(filter(html.xpath(body.html, '//@class').nodes, any(recipients.to, ..raw =~ .email.domain.sld or strings.istarts_with(..raw, strings.concat('x_hz', .email.domain.sld))))) > 30
- ratio(html.xpath(body.html, '//@class').nodes) > 0.8
none of:
- length(headers.references) > 0
- headers.in_reply_to is set
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
Inspects: body.html, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, recipients.to, recipients.to[].email.domain.domain, recipients.to[].email.domain.sld, sender.email.domain.domain, sender.email.domain.root_domain, type.inbound. Sensors: html.xpath, strings.concat, strings.istarts_with. 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"
not
and
coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
macro "sender.email.domain.domain in org_domains"
not
or
headers.in_reply_to is_not_null
headers.references length_compare "0"
filter(html.xpath(body.html, '//@class').nodes, any(recipients.to, ..raw =~ .email.domain.sld or strings.istarts_with(..raw, strings.concat('x_hz', .email.domain.sld)))) length_compare "30"
ratio func_call "ratio(html.xpath(body.html, '//@class').nodes) > 0.8"
recipients.to length_compare "1"
type.inbound eq "true"
macro "all(recipients.to)"Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
headers.in_reply_to | is_not_null | excludes:headers.in_reply_to | |
headers.references | length_compare | 0 | excludes:headers.references field:"headers.references" value:"0" |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |