Detection rules › Sublime MQL
Attachment: EML file contains HTML attachment with login portal indicators
Attached EML file contains an HTML attachment with suspicious login indicators. Known credential theft technique.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Evasion, HTML smuggling |
Event coverage
Rule body MQL
type.inbound
// exclude bounce backs & read receipts
and not strings.like(sender.email.local_part,
"*postmaster*",
"*mailer-daemon*",
"*administrator*"
)
and not regex.imatch(subject.subject, "(undeliverable|read:).*")
and not any(attachments, .content_type == "message/delivery-status")
// if the "References" is in the body of the message, it's probably a bounce
and not any(headers.references, strings.contains(body.html.display_text, .))
and (
(length(headers.references) == 0 and headers.in_reply_to is null)
or (
not strings.istarts_with(subject.subject, "re:")
and headers.in_reply_to is null
and not any(headers.hops, strings.ilike(.signature.headers, "*:reply-to"))
)
)
and any(attachments,
(.content_type == "message/rfc822" or .file_extension in ('eml'))
and any(file.explode(.),
// suspicious strings found in javascript
length(filter(.scan.javascript.strings,
strings.ilike(.,
"*username*",
"*login-form*",
"*email-form*",
"*Incorrect password. Please try again.*",
"*Password Incomplete, please try again*"
)
)
) >= 3
or (
// suspicious strings found outside of javascript, but binexplode'd file still of HTML type
.flavors.mime in~ ("text/html", "text/plain")
and 3 of (
any(.scan.strings.strings, strings.ilike(., "*username*")),
any(.scan.strings.strings, strings.ilike(., "*login-form*")),
any(.scan.strings.strings, strings.ilike(., "*email-form*")),
any(.scan.strings.strings,
strings.ilike(.,
"*Incorrect password. Please try again.*"
)
),
any(.scan.strings.strings,
strings.ilike(.,
"*Password Incomplete, please try again*"
)
)
)
)
or
// Known phishing obfuscation
2 of (
// Enter password
any(.scan.strings.strings,
strings.ilike(.,
"*Enter passwor&#100*"
)
),
// Forgotten my password
any(.scan.strings.strings,
strings.ilike(.,
"*Forgotten my passwor&#100*"
)
),
// Sign in
any(.scan.strings.strings,
strings.ilike(.,
"*Sign i&#110*"
)
)
)
)
)
Detection logic
Scope: inbound message.
Attached EML file contains an HTML attachment with suspicious login indicators. Known credential theft technique.
- inbound message
not:
sender.email.local_part matches any of 3 patterns
*postmaster**mailer-daemon**administrator*
not:
- subject.subject matches '(undeliverable|read:).*'
not:
any of
attachmentswhere:- .content_type is 'message/delivery-status'
not:
any of
headers.referenceswhere:- strings.contains(body.html.display_text)
any of:
all of:
- length(headers.references) is 0
- headers.in_reply_to is missing
all of:
not:
- subject.subject starts with 're:'
- headers.in_reply_to is missing
not:
any of
headers.hopswhere:- .signature.headers matches '*:reply-to'
any of
attachmentswhere all hold:any of:
- .content_type is 'message/rfc822'
- .file_extension in ('eml')
any of
file.explode(.)where any holds:- length(filter(.scan.javascript.strings, strings.ilike(., '*username*', '*login-form*', '*email-form*', '*Incorrect password. Please try again.*', '*Password Incomplete, please try again*'))) ≥ 3
all of:
- .flavors.mime in ('text/html', 'text/plain')
at least 3 of:
any of
.scan.strings.stringswhere:- . matches '*username*'
any of
.scan.strings.stringswhere:- . matches '*login-form*'
any of
.scan.strings.stringswhere:- . matches '*email-form*'
any of
.scan.strings.stringswhere:- . matches '*Incorrect password. Please try again.*'
any of
.scan.strings.stringswhere:- . matches '*Password Incomplete, please try again*'
at least 2 of:
any of
.scan.strings.stringswhere:- . matches '*Enter passwor&#100*'
any of
.scan.strings.stringswhere:- . matches '*Forgotten my passwor&#100*'
any of
.scan.strings.stringswhere:- . matches '*Sign i&#110*'
Inspects: attachments[].content_type, attachments[].file_extension, body.html.display_text, headers.hops, headers.hops[].signature.headers, headers.in_reply_to, headers.references, sender.email.local_part, subject.subject, type.inbound. Sensors: file.explode, regex.imatch, strings.contains, strings.ilike, strings.istarts_with, strings.like.
Indicators matched (19)
| Field | Match | Value |
|---|---|---|
strings.like | substring | *postmaster* |
strings.like | substring | *mailer-daemon* |
strings.like | substring | *administrator* |
regex.imatch | regex | (undeliverable|read:).* |
attachments[].content_type | equals | message/delivery-status |
strings.istarts_with | prefix | re: |
strings.ilike | substring | *:reply-to |
attachments[].content_type | equals | message/rfc822 |
attachments[].file_extension | member | eml |
strings.ilike | substring | *username* |
strings.ilike | substring | *login-form* |
strings.ilike | substring | *email-form* |
7 more
strings.ilike | substring | *Incorrect password. Please try again.* |
strings.ilike | substring | *Password Incomplete, please try again* |
file.explode(attachments[])[].flavors.mime | member | text/html |
file.explode(attachments[])[].flavors.mime | member | text/plain |
strings.ilike | substring | *Enter passwor&#100* |
strings.ilike | substring | *Forgotten my passwor&#100* |
strings.ilike | substring | *Sign i&#110* |