Detection rules › Sublime MQL
Attachment: Web files with suspicious comments
Detects HTML or SVG files under 100KB that contain duplicate or padding text in the form of literary quotes or common sayings within code comments.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing, Malware/Ransomware |
| Tactics and techniques | HTML smuggling, Evasion |
Event coverage
| Message attribute |
|---|
| attachments (collection) |
| type |
Rule body MQL
type.inbound
and any(attachments,
(
(
.file_type in ("html", "svg")
or .file_extension in ("html", "xhtml", "mhtml", "svg")
or .content_type in ("text/html", "text/plain")
)
and .size < 100000
)
and (
(
// targeting comments that pad the file with quotes from literature
// examples: "// Echoes of the past linger in silence.", "// The wind whispered secrets unknown.", "// Shadows tell stories in the dark."
// count all HTML code comments that match our pattern
regex.count(file.parse_text(.).text, '// [A-Z][ a-z ]+\.') /
// divide by the count of all UNIQUE HTML code comments that match our pattern
length(distinct(regex.extract(file.parse_text(.).text,
'// [A-Z][ a-z ]+\.'
),
.full_match
)
)
// at least 50% of the comments are duplicates
>= 2
)
or (
// targeting comments that pad the file with sayings
// examples: "<!-- <span> No gain without pain. </span> -->", "<!-- <p> Beauty is only skin deep. </p> -->", "<!-- <span> Actions speak louder than words. </span> -->"
regex.count(file.parse_text(.).text,
'<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\. (</[a-z]+>)? +-->'
)
) > 2
or (
// targeting comments inside hidden HTML elements
// example: "<h1 style="display:none;"> Self-confidence inspires others to believe in you. </h1>"
regex.count(file.parse_text(.).text,
'<[a-z0-9]+ style="display:none;">(<[a-z]+>)? [A-Z].*\. </[a-z0-9]+>'
)
) > 2
)
)
Detection logic
Scope: inbound message.
Detects HTML or SVG files under 100KB that contain duplicate or padding text in the form of literary quotes or common sayings within code comments.
- inbound message
any of
attachmentswhere all hold:all of:
any of:
- .file_type in ('html', 'svg')
- .file_extension in ('html', 'xhtml', 'mhtml', 'svg')
- .content_type in ('text/html', 'text/plain')
- .size < 100000
any of:
- regex.count(file.parse_text(.).text) / length(distinct(regex.extract(file.parse_text(.).text, '// [A-Z][ a-z ]+\\.'), .full_match)) ≥ 2
- regex.count(file.parse_text(.).text, '<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\\. (</[a-z]+>)? +-->') > 2
- regex.count(file.parse_text(.).text, '<[a-z0-9]+ style="display:none;">(<[a-z]+>)? [A-Z].*\\. </[a-z0-9]+>') > 2
Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.parse_text, regex.count.
Indicators matched (10)
| Field | Match | Value |
|---|---|---|
attachments[].file_type | member | html |
attachments[].file_type | member | svg |
attachments[].file_extension | member | html |
attachments[].file_extension | member | xhtml |
attachments[].file_extension | member | mhtml |
attachments[].file_extension | member | svg |
attachments[].content_type | member | text/html |
attachments[].content_type | member | text/plain |
regex.count | regex | <!-- +(<[a-z]+>)? [A-Z][ a-z ]+\. (</[a-z]+>)? +--> |
regex.count | regex | <[a-z0-9]+ style="display:none;">(<[a-z]+>)? [A-Z].*\. </[a-z0-9]+> |