Detection rules › Sublime MQL
Credential Phishing: Suspicious language, link, recipients and other indicators
The rule flags inbound messages with no visible recipients, contain all-caps text, and include links from certain free hosts. It also checks for signs of credential theft using machine learning classifiers and is from an untrusted sender.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Evasion |
Event coverage
Rule body MQL
type.inbound
// no recipients defined
and (
length(recipients.to) == 0
or all(recipients.to, .display_name == "Undisclosed recipients")
)
and length(recipients.cc) == 0
and length(recipients.bcc) == 0
and any(body.links,
// suspicious link
// we've particularly seen 1drv.ms abused
// if using the full list causes FPs, we can reduce the
// scope to a hard-coded list or add exclusions
(
.href_url.domain.domain in $free_file_hosts
or .href_url.domain.root_domain in $free_file_hosts
or .href_url.domain.root_domain in $free_subdomain_hosts
)
// link text is in all caps
and regex.match(.display_text, "[A-Z ]+")
)
// any confidence cred_theft classification
and any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "cred_theft"
)
// 'org' entity is in all caps
and any(ml.nlu_classifier(body.current_thread.text).entities,
.name == "org" and regex.match(.text, "[A-Z ]+")
)
// subject is in all caps
and regex.match(subject.subject, "[A-Z ]+")
and (
profile.by_sender().prevalence in ("new", "outlier")
or (
profile.by_sender().any_messages_malicious_or_spam
and not profile.by_sender().any_messages_benign
)
)
Detection logic
Scope: inbound message.
The rule flags inbound messages with no visible recipients, contain all-caps text, and include links from certain free hosts. It also checks for signs of credential theft using machine learning classifiers and is from an untrusted sender.
- inbound message
any of:
- length(recipients.to) is 0
all of
recipients.towhere:- .display_name is 'Undisclosed recipients'
- length(recipients.cc) is 0
- length(recipients.bcc) is 0
any of
body.linkswhere all hold:any of:
- .href_url.domain.domain in $free_file_hosts
- .href_url.domain.root_domain in $free_file_hosts
- .href_url.domain.root_domain in $free_subdomain_hosts
- .display_text matches '[A-Z ]+'
any of
ml.nlu_classifier(body.current_thread.text).intentswhere:- .name is 'cred_theft'
any of
ml.nlu_classifier(body.current_thread.text).entitieswhere all hold:- .name is 'org'
- .text matches '[A-Z ]+'
- subject.subject matches '[A-Z ]+'
any of:
- profile.by_sender().prevalence in ('new', 'outlier')
all of:
- profile.by_sender().any_messages_malicious_or_spam
not:
- profile.by_sender().any_messages_benign
Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.domain, body.links[].href_url.domain.root_domain, recipients.bcc, recipients.cc, recipients.to, recipients.to[].display_name, subject.subject, type.inbound. Sensors: ml.nlu_classifier, profile.by_sender, regex.match. Reference lists: $free_file_hosts, $free_subdomain_hosts.
Indicators matched (4)
| Field | Match | Value |
|---|---|---|
recipients.to[].display_name | equals | Undisclosed recipients |
regex.match | regex | [A-Z ]+ |
ml.nlu_classifier(body.current_thread.text).intents[].name | equals | cred_theft |
ml.nlu_classifier(body.current_thread.text).entities[].name | equals | org |