Detection rules › Sublime MQL

Sublime MQL rules: zoom

Service Abuse: Zoom with freemail reply-to and recipient address in greeting

#
Severity
medium
Type
rule
Source
github.com/sublime-security/sublime-rules

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).

CategoryValues
Attack typesSpam
Tactics and techniquesFree email provider, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • headers
  • headers.reply_to[0]
  • recipients
  • recipients.to[0]
  • sender.email
  • type

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.

  1. inbound message
  2. sender.email.email is 'no-reply@zoom.us'
  3. headers.reply_to[0].email.domain.domain in $free_email_providers
  4. beta.profile.by_reply_to().prevalence is 'new'
  5. not:
    • beta.profile.by_reply_to().solicited
  6. 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)

FieldMatchValue
sender.email.emailequalsno-reply@zoom.us
regex.iextractregex^\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.

Zoom Events newsletter abuse

#
Severity
medium
Type
rule
Source
github.com/sublime-security/sublime-rules

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).

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree file host, Free subdomain host, Social engineering, Impersonation: Brand

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • headers
  • headers.auth_summary
  • sender.email
  • type

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.

  1. inbound message
  2. sender.email.email is 'noreply-zoomevents@zoom.us'
  3. any of:
    • headers.auth_summary.spf.pass
    • headers.auth_summary.dmarc.pass
  4. 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')])]").nodes where:
    • any of ml.nlu_classifier(.display_text).intents where 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)

FieldMatchValue
sender.email.emailequalsnoreply-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[].nameequalscred_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.