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 == "new"
  5. not:
    • beta.profile.by_reply_to().solicited
  6. 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 )

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"
  beta.profile.by_reply_to func_call "beta.profile.by_reply_to().prevalence == \"new\""
  headers.reply_to[0].email.domain.domain macro "headers.reply_to[0].email.domain.domain in free_email_providers"
  sender.email.email eq "no-reply@zoom.us"
  type.inbound eq "true"
   macro "any(regex.iextract(body.current_thread.text,\n                       '^\\S+\\s+(?P<last_word>\\S+?),?(?:\\n|\\z)'\n        ),\n        strings.parse_email(.named_groups[\"last_word\"]).domain.root_domain == recipients.to[0].email.domain.root_domain\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
sender.email.emaileq
  • no-reply@zoom.us corpus 3 (mql 3)
field:"sender.email.email" kind:eq value:"no-reply@zoom.us"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

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(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" ) )

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
  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"
   macro "any(html.xpath(body.html,\n                   \"//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')])]\"\n        ).nodes,\n        any(ml.nlu_classifier(.display_text).intents,\n            .name == \"cred_theft\" and .confidence != \"low\"\n        )\n)"

Indicators

These rows show field, operator, and value matches.

Back to all Sublime MQL rules