Detection rules › Sublime MQL
Sublime MQL rules: zoom
| Rule | Severity |
|---|---|
| Service Abuse: Zoom with freemail reply-to and recipient address in greeting | medium |
| Zoom Events newsletter abuse | medium |
Service Abuse: Zoom with freemail reply-to and recipient address in greeting
#Detects messages impersonating Zoom that use a freemail provider for the reply-to address, have a new and unsolicited reply-to profile, and contain the recipient's email address in the greeting line where a name would normally appear.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Spam |
| Tactics and techniques | Free email provider, Social engineering |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message attributes
Rule body
type.inbound
// is from zoom
and sender.email.email == "no-reply@zoom.us"
// has a freemail for a reply-to address
and headers.reply_to[0].email.domain.domain in $free_email_providers
// the reply-to address is new
and beta.profile.by_reply_to().prevalence == "new"
and not beta.profile.by_reply_to().solicited
// the "greeting" line contains an email address matching the recipient's email root domain
// this is normally a name
and any(regex.iextract(body.current_thread.text,
'^\S+\s+(?P<last_word>\S+?),?(?:\n|\z)'
),
strings.parse_email(.named_groups["last_word"]).domain.root_domain == recipients.to[0].email.domain.root_domain
)
Detection logic
Scope: inbound message.
Detects messages impersonating Zoom that use a freemail provider for the reply-to address, have a new and unsolicited reply-to profile, and contain the recipient's email address in the greeting line where a name would normally appear.
- inbound message
- sender.email.email is 'no-reply@zoom.us'
- headers.reply_to[0].email.domain.domain in $free_email_providers
- beta.profile.by_reply_to().prevalence is 'new'
not:
- beta.profile.by_reply_to().solicited
any of
regex.iextract(body.current_thread.text)where:- strings.parse_email(.named_groups['last_word']).domain.root_domain is recipients.to[0].email.domain.root_domain
Inspects: body.current_thread.text, headers.reply_to[0].email.domain.domain, recipients.to[0].email.domain.root_domain, sender.email.email, type.inbound. Sensors: beta.profile.by_reply_to, regex.iextract, strings.parse_email. Reference lists: $free_email_providers.
Indicators matched (2)
| Field | Match | Value |
|---|---|---|
sender.email.email | equals | no-reply@zoom.us |
regex.iextract | regex | ^\S+\s+(?P<last_word>\S+?),?(?:\n|\z) |
Stages and Predicates
Stage 1: mql_rule
and
not
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().solicited"
any(regex.iextract(body.current_thread.text))
strings.parse_email func_call "strings.parse_email(regex.iextract(body.current_thread.text)[].named_groups['last_word']).domain.root_domain == recipients.to[0].email.domain.root_domain"
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().prevalence == new"
sender.email.email eq "no-reply@zoom.us"
type.inbound eq "true"
macro "headers.reply_to[0].email.domain.domain in free_email_providers"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
sender.email.email | eq |
| field:"sender.email.email" kind:eq value:"no-reply@zoom.us" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Zoom Events newsletter abuse
#Detects suspicious content in Zoom Events notifications that contain credential theft language and links to file hosting sites.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Free file host, Free subdomain host, Social engineering, Impersonation: Brand |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message attributes
Rule body
type.inbound
and sender.email.email == "noreply-zoomevents@zoom.us"
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
// extract the actor controlled content from the email body (excluding the
// static Zoom copyright/unsubscribe footer) and pass it to NLU
and any(html.xpath(body.html,
"//div[@class='eb-content css-1l7xmti']//td[@data-dynamic-style-background-color='email.bodyColor.color' and contains(@style, 'background-color: rgb(255, 255, 255)')]/*[not(.//*[contains(text(), 'Copyright') or contains(text(), 'unsubscribe')])]"
).nodes,
any(ml.nlu_classifier(.display_text).intents,
.name == "cred_theft" and .confidence != "low"
)
)
Detection logic
Scope: inbound message.
Detects suspicious content in Zoom Events notifications that contain credential theft language and links to file hosting sites.
- inbound message
- sender.email.email is 'noreply-zoomevents@zoom.us'
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of
html.xpath(body.html, "//div[@class='eb-content css-1l7xmti']//td[@data-dynamic-style-background-color='email.bodyColor.color' and contains(@style, 'background-color: rgb(255, 255, 255)')]/*[not(.//*[contains(text(), 'Copyright') or contains(text(), 'unsubscribe')])]").nodeswhere:any of
ml.nlu_classifier(.display_text).intentswhere all hold:- .name is 'cred_theft'
- .confidence is not 'low'
Inspects: body.html, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.email, type.inbound. Sensors: html.xpath, ml.nlu_classifier.
Indicators matched (2)
| Field | Match | Value |
|---|---|---|
sender.email.email | equals | noreply-zoomevents@zoom.us |
ml.nlu_classifier(html.xpath(body.html, "//div[@class='eb-content css-1l7xmti']//td[@data-dynamic-style-background-color='email.bodyColor.color' and contains(@style, 'background-color: rgb(255, 255, 255)')]/*[not(.//*[contains(text(), 'Copyright') or contains(text(), 'unsubscribe')])]").nodes[].display_text).intents[].name | equals | cred_theft |
Stages and Predicates
Stage 1: mql_rule
and
any(html.xpath(body.html, "//div[@class='eb-content css-1l7xmti']//td[@data-dynamic-style-background-color='email.bodyColor.color' and contains(@style, 'background-color: rgb(255, 255, 255)')]/*[not(.//*[contains(text(), 'Copyright') or contains(text(), 'unsubscribe')])]").nodes)
any(ml.nlu_classifier(html.xpath(body.html, "//div[@class='eb-content css-1l7xmti']//td[@data-dynamic-style-background-color='email.bodyColor.color' and contains(@style, 'background-color: rgb(255, 255, 255)')]/*[not(.//*[contains(text(), 'Copyright') or contains(text(), 'unsubscribe')])]").nodes.display_text).intents)
and
ml.nlu_classifier(html.xpath(body.html, "//div[@class='eb-content css-1l7xmti']//td[@data-dynamic-style-background-color='email.bodyColor.color' and contains(@style, 'background-color: rgb(255, 255, 255)')]/*[not(.//*[contains(text(), 'Copyright') or contains(text(), 'unsubscribe')])]").nodes[].display_text).intents[].confidence ne "low"
ml.nlu_classifier(html.xpath(body.html, "//div[@class='eb-content css-1l7xmti']//td[@data-dynamic-style-background-color='email.bodyColor.color' and contains(@style, 'background-color: rgb(255, 255, 255)')]/*[not(.//*[contains(text(), 'Copyright') or contains(text(), 'unsubscribe')])]").nodes[].display_text).intents[].name eq "cred_theft"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
sender.email.email eq "noreply-zoomevents@zoom.us"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.