Detection rules › Sublime MQL
Sublime MQL rules: evasion
| Rule | Severity |
|---|---|
| Evasion: Hidden content divs from freemail sender | medium |
| Evasion: Suspicious TLD link redirecting to Wikipedia | low |
| Link: Credential harvesting with excess padding evasion | low |
Evasion: Suspicious TLD link redirecting to Wikipedia
#Flags inbound messages containing links with domains registered under suspicious top-level domains that redirect to Wikipedia when analyzed. This behavior indicates the link is detecting automated sandbox or security analysis tools and serving benign content to evade detection, while likely delivering malicious content to real users.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing, Spam |
| Tactics and techniques | Evasion, Open redirect |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message attributes
Rule body
type.inbound
and any(body.current_thread.links,
.href_url.domain.tld in $suspicious_tlds
and ml.link_analysis(.).effective_url.url in (
'https://www.wikipedia.org/'
)
)
Detection logic
Scope: inbound message.
Flags inbound messages containing links with domains registered under suspicious top-level domains that redirect to Wikipedia when analyzed. This behavior indicates the link is detecting automated sandbox or security analysis tools and serving benign content to evade detection, while likely delivering malicious content to real users.
- inbound message
any of
body.current_thread.linkswhere all hold:- .href_url.domain.tld in $suspicious_tlds
- ml.link_analysis(.).effective_url.url in ('https://www.wikipedia.org/')
Inspects: body.current_thread.links, body.current_thread.links[].href_url.domain.tld, type.inbound. Sensors: ml.link_analysis. Reference lists: $suspicious_tlds.
Stages and Predicates
Stage 1: mql_rule
and
any(body.current_thread.links)
and
ml.link_analysis func_call "ml.link_analysis(body.current_thread.links[]).effective_url.url in (https://www.wikipedia.org/)"
macro "body.current_thread.links[].href_url.domain.tld in suspicious_tlds"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Link: Credential harvesting with excess padding evasion
#Detects inbound messages containing credential-related action links with tall screenshot images and HTML padding techniques used to evade detection. The rule identifies messages with excessive empty div tags, non-breaking spaces, or large margin-top values that artificially increase content height while hiding malicious intent.
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
// CTA link with action-oriented display text pointing to a different domain than the sender
and any(body.current_thread.links,
regex.icontains(.display_text,
'(?:open|sign.?in|log.?in|retain|credential|secure|confirm|accept|release|review|document|deliver)'
)
and .href_url.domain.root_domain != sender.email.domain.root_domain
and not regex.icontains(.display_text, 'open source')
)
// tall rendered email with low word density
and beta.parse_exif(file.message_screenshot()).image_height > 1500
and beta.parse_exif(file.message_screenshot()).image_height * 100 / regex.count(body.html.display_text,
'\S+'
) > 500
// html whitespace stuffing patterns
and (
// bare div-br blocks repeated 30+ times
regex.icontains(body.html.raw, '(?:<div>\s*<br\s*/?\s*>\s*</div>\s*){30,}')
// style div-br blocks repeated 20+ times
or regex.icontains(body.html.raw,
'(?:<div\s+style="[^"]+"\s*[^>]*>\s*<br\s*/?\s*>\s*</div>\s*){20,}'
)
// attributed empty div-nbsp blocks repeated 20+ times (styled/classed empty divs, e.g. Outlook Aptos)
// requires an attribute to avoid bare <div>&nbsp;</div> newsletter spacers
or (
regex.icontains(body.html.raw,
'(?:<div\s+[^>]+>\s*(?:&nbsp;|&#160;)\s*</div>\s*){20,}'
)
// exclude collapsed/hidden empty divs (display:none, font-size:0, line-height:0)
// these render to zero height and are ESP preheader artifacts, not visible stuffing
and not regex.icontains(body.html.raw,
'(?:<div\s+[^>]*(?:display\s*:\s*none|font-size\s*:\s*0|line-height\s*:\s*0)[^>]*>\s*(?:&nbsp;|&#160;)\s*</div>\s*){20,}'
)
)
// p-nbsp blocks repeated 25+ times
or regex.icontains(body.html.raw,
'(?:<p>\s*(?:&nbsp;|&#160;)\s*</p>\s*){25,}'
)
// css margin-top or padding-top pushdown >= 1500px
or (
regex.icontains(body.html.raw,
'(?:margin|padding)-top\s*:\s*(?:1[5-9]\d{2}|[2-9]\d{3}|\d{5,})px'
)
and not regex.icontains(body.html.raw,
'position\s*:\s*absolute[^"]*(?:margin|padding)-top\s*:\s*(?:1[5-9]\d{2}|[2-9]\d{3}|\d{5,})px'
)
and not regex.icontains(body.html.raw,
'margin-left\s*:\s*\d{3,}px[^"]*(?:margin|padding)-top\s*:\s*(?:1[5-9]\d{2}|[2-9]\d{3}|\d{5,})px'
)
)
)
Detection logic
Scope: inbound message.
Detects inbound messages containing credential-related action links with tall screenshot images and HTML padding techniques used to evade detection. The rule identifies messages with excessive empty div tags, non-breaking spaces, or large margin-top values that artificially increase content height while hiding malicious intent.
- inbound message
any of
body.current_thread.linkswhere all hold:- .display_text matches '(?:open|sign.?in|log.?in|retain|credential|secure|confirm|accept|release|review|document|deliver)'
- .href_url.domain.root_domain is not sender.email.domain.root_domain
not:
- .display_text matches 'open source'
- beta.parse_exif(file.message_screenshot()).image_height > 1500
- beta.parse_exif(file.message_screenshot()).image_height * 100 / regex.count(body.html.display_text) > 500
any of:
- body.html.raw matches '(?:<div>\\s*<br\\s*/?\\s*>\\s*</div>\\s*){30,}'
- body.html.raw matches '(?:<div\\s+style="[^"]+"\\s*[^>]*>\\s*<br\\s*/?\\s*>\\s*</div>\\s*){20,}'
all of:
- body.html.raw matches '(?:<div\\s+[^>]+>\\s*(?:&nbsp;|&#160;)\\s*</div>\\s*){20,}'
not:
- body.html.raw matches '(?:<div\\s+[^>]*(?:display\\s*:\\s*none|font-size\\s*:\\s*0|line-height\\s*:\\s*0)[^>]*>\\s*(?:&nbsp;|&#160;)\\s*</div>\\s*){20,}'
- body.html.raw matches '(?:<p>\\s*(?:&nbsp;|&#160;)\\s*</p>\\s*){25,}'
all of:
- body.html.raw matches '(?:margin|padding)-top\\s*:\\s*(?:1[5-9]\\d{2}|[2-9]\\d{3}|\\d{5,})px'
not:
- body.html.raw matches 'position\\s*:\\s*absolute[^"]*(?:margin|padding)-top\\s*:\\s*(?:1[5-9]\\d{2}|[2-9]\\d{3}|\\d{5,})px'
not:
- body.html.raw matches 'margin-left\\s*:\\s*\\d{3,}px[^"]*(?:margin|padding)-top\\s*:\\s*(?:1[5-9]\\d{2}|[2-9]\\d{3}|\\d{5,})px'
Inspects: body.current_thread.links, body.current_thread.links[].display_text, body.current_thread.links[].href_url.domain.root_domain, body.html.raw, sender.email.domain.root_domain, type.inbound. Sensors: beta.parse_exif, file.message_screenshot, regex.icontains.
Indicators matched (6)
| Field | Match | Value |
|---|---|---|
regex.icontains | regex | (?:open|sign.?in|log.?in|retain|credential|secure|confirm|accept|release|review|document|deliver) |
regex.icontains | regex | (?:<div>\s*<br\s*/?\s*>\s*</div>\s*){30,} |
regex.icontains | regex | (?:<div\s+style="[^"]+"\s*[^>]*>\s*<br\s*/?\s*>\s*</div>\s*){20,} |
regex.icontains | regex | (?:<div\s+[^>]+>\s*(?:&nbsp;|&#160;)\s*</div>\s*){20,} |
regex.icontains | regex | (?:<p>\s*(?:&nbsp;|&#160;)\s*</p>\s*){25,} |
regex.icontains | regex | (?:margin|padding)-top\s*:\s*(?:1[5-9]\d{2}|[2-9]\d{3}|\d{5,})px |
Stages and Predicates
Stage 1: mql_rule
and
any(body.current_thread.links)
and
not
body.current_thread.links.display_text regex_match "open source"
body.current_thread.links.display_text regex_match "(?:open|sign.?in|log.?in|retain|credential|secure|confirm|accept|release|review|document|deliver)"
body.current_thread.links.href_url.domain.root_domain cross_field_compare "sender.email.domain.root_domain"
or
and
not
body.html.raw regex_match "(?:<div\\s+[^>]*(?:display\\s*:\\s*none|font-size\\s*:\\s*0|line-height\\s*:\\s*0)[^>]*>\\s*(?:&nbsp;|&#160;)\\s*</div>\\s*){20,}"
body.html.raw regex_match "(?:<div\\s+[^>]+>\\s*(?:&nbsp;|&#160;)\\s*</div>\\s*){20,}"
and
not
body.html.raw regex_match "margin-left\\s*:\\s*\\d{3,}px[^\"]*(?:margin|padding)-top\\s*:\\s*(?:1[5-9]\\d{2}|[2-9]\\d{3}|\\d{5,})px"
not
body.html.raw regex_match "position\\s*:\\s*absolute[^\"]*(?:margin|padding)-top\\s*:\\s*(?:1[5-9]\\d{2}|[2-9]\\d{3}|\\d{5,})px"
body.html.raw regex_match "(?:margin|padding)-top\\s*:\\s*(?:1[5-9]\\d{2}|[2-9]\\d{3}|\\d{5,})px"
body.html.raw regex_match "(?:<div>\\s*<br\\s*/?\\s*>\\s*</div>\\s*){30,}"
body.html.raw regex_match "(?:<div\\s+style=\"[^\"]+\"\\s*[^>]*>\\s*<br\\s*/?\\s*>\\s*</div>\\s*){20,}"
body.html.raw regex_match "(?:<p>\\s*(?:&nbsp;|&#160;)\\s*</p>\\s*){25,}"
beta.parse_exif func_call "beta.parse_exif(file.message_screenshot()).image_height > 1500"
type.inbound eq "true"
macro "((beta.parse_exif(file.message_screenshot()).image_height * 100) / regex.count(body.html.display_text)) > 500"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.html.raw | regex_match |
| field:"body.html.raw" kind:regex_match |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |