Detection rules › Sublime MQL

Sublime MQL rules: tax

BEC: Tax document request

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

Detects messages requesting W-2 tax documents or related tax information that exhibit authentication failures such as DMARC or SPF failures, or mismatched reply-to addresses. The rule identifies senders using common administrative local parts and filters for messages containing W-2 language combined with request entities detected through natural language processing.

Threat Classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesSocial engineering, Spoofing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • headers.reply_to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
// searching for common sender emails
and sender.email.local_part in~ (
  "contact",
  "no-reply",
  "noreply",
  "info",
  "admin"
)
// sender emails unmatched
and (
  length(headers.reply_to) > 0
  and all(headers.reply_to,
          .email.domain.root_domain != sender.email.domain.root_domain
  )
)
// subject lines with words correlating to tax information
and (
  strings.icontains(subject.base, 'wage')
  or strings.icontains(strings.replace_confusables(subject.base), 'Ŵ-2')
  or regex.icontains(subject.base, 'tax (?:form|state?ment|year)')
  or regex.icontains(subject.base, '\bw-?2?\b')
  or regex.icontains(strings.replace_confusables(subject.base), '\birs\b')
)
// body text containing variations of "w2" or "wage statements"
and (
  (
    strings.icontains(strings.replace_confusables(body.current_thread.text),
                      'Ẇ-2'
    )
    or strings.icontains(body.current_thread.text, "wage statements")
    or regex.icontains(body.current_thread.text, 'w-?2[a-z]?\b')
  )
)
// ml classifying for requests
and any(ml.nlu_classifier(body.current_thread.text).entities,
        .name == "request"
)
// exclude legitimate senders or domains
and not any(ml.nlu_classifier(body.current_thread.text).intents,
            .name == "benign" and .confidence == "high"
)
and not (
  sender.email.domain.domain in $org_domains
  and coalesce(headers.auth_summary.dmarc.pass, false)
)
and not (
  sender.email.domain.root_domain in (
    "excel.com",
    "sharepoint.com",
    "sharepointonline.com",
    "powerpoint.com",
    "onenote.com",
    "microsoft.com",
    "jotform.com",
    "wetrasnfer.com"
  )
  and coalesce(headers.auth_summary.dmarc.pass, false)
)
// negate highly trusted sender domains unless they fail DMARC authentication
and not (
  sender.email.domain.root_domain in $high_trust_sender_root_domains
  and coalesce(headers.auth_summary.dmarc.pass, false)
)

Detection Logic

Scope: inbound message.

Detects messages requesting W-2 tax documents or related tax information that exhibit authentication failures such as DMARC or SPF failures, or mismatched reply-to addresses. The rule identifies senders using common administrative local parts and filters for messages containing W-2 language combined with request entities detected through natural language processing.

  1. inbound message
  2. sender.email.local_part in ('contact', 'no-reply', 'noreply', 'info', 'admin')
  3. all of:
    • length(headers.reply_to) > 0
    • all of headers.reply_to where:
      • .email.domain.root_domain is not sender.email.domain.root_domain
  4. any of:
    • subject.base contains 'wage'
    • strings.icontains(strings.replace_confusables(subject.base), 'Ŵ-2')
    • subject.base matches 'tax (?:form|state?ment|year)'
    • subject.base matches '\\bw-?2?\\b'
    • regex.icontains(strings.replace_confusables(subject.base), '\birs\b')
  5. any of:
    • strings.icontains(strings.replace_confusables(body.current_thread.text), 'Ẇ-2' )
    • body.current_thread.text contains 'wage statements'
    • body.current_thread.text matches 'w-?2[a-z]?\\b'
  6. any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request" )
  7. not:
    • any(ml.nlu_classifier(body.current_thread.text).intents, .name == "benign" and .confidence == "high" )
  8. not:
    • all of:
      • sender.email.domain.domain in $org_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)
  9. not:
    • all of:
      • sender.email.domain.root_domain in ('excel.com', 'sharepoint.com', 'sharepointonline.com', 'powerpoint.com', 'onenote.com', 'microsoft.com', 'jotform.com', 'wetrasnfer.com')
      • coalesce(headers.auth_summary.dmarc.pass, false)
  10. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.reply_to, headers.reply_to[].email.domain.root_domain, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.local_part, subject.base, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, strings.icontains, strings.replace_confusables. Reference lists: $high_trust_sender_root_domains, $org_domains.

Indicators Matched (14)

FieldMatchValue
sender.email.local_partmembercontact
sender.email.local_partmemberno-reply
sender.email.local_partmembernoreply
sender.email.local_partmemberinfo
sender.email.local_partmemberadmin
strings.icontainssubstringwage
strings.icontainssubstringŴ-2
regex.icontainsregextax (?:form|state?ment|year)
regex.icontainsregex\bw-?2?\b
regex.icontainsregex\birs\b
strings.icontainssubstringẆ-2
strings.icontainssubstringwage statements
2 more
regex.icontainsregexw-?2[a-z]?\b
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsrequest

Stages and Predicates

Stage 1: mql_rule

and
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.domain macro "sender.email.domain.domain in org_domains"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain in ["excel.com", "jotform.com", "microsoft.com", "onenote.com", "powerpoint.com", "sharepoint.com", "sharepointonline.com", "wetrasnfer.com"]
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  or
    body.current_thread.text contains "wage statements"
    body.current_thread.text regex_match "w-?2[a-z]?\\b"
    strings.icontains func_call "strings.icontains(strings.replace_confusables(body.current_thread.text),\n                      'Ẇ-2'\n    )"
  or
    regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.base), '\\birs\\b')"
    strings.icontains func_call "strings.icontains(strings.replace_confusables(subject.base), 'Ŵ-2')"
    subject.base contains "wage"
    subject.base regex_match "\\bw-?2?\\b"
    subject.base regex_match "tax (?:form|state?ment|year)"
  not
     macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n            .name == \"benign\" and .confidence == \"high\"\n)"
  headers.reply_to length_compare "0"
  sender.email.local_part in ["admin", "contact", "info", "no-reply", "noreply"]
  type.inbound eq "true"
   macro "all(headers.reply_to,\n          .email.domain.root_domain != sender.email.domain.root_domain\n  )"
   macro "any(ml.nlu_classifier(body.current_thread.text).entities,\n        .name == \"request\"\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • wage statements
field:"body.current_thread.text" kind:contains value:"wage statements"
body.current_thread.textregex_match
  • w-?2[a-z]?\b
field:"body.current_thread.text" kind:regex_match value:"w-?2[a-z]?\b"
sender.email.local_partin
  • admin
  • contact
  • info corpus 2 (mql 2)
  • no-reply corpus 2 (mql 2)
  • noreply corpus 2 (mql 2)
field:"sender.email.local_part" kind:in
subject.basecontains
  • wage corpus 2 (mql 2)
field:"subject.base" kind:contains value:"wage"
subject.baseregex_match
  • \bw-?2?\b
  • tax (?:form|state?ment|year)
field:"subject.base" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass
sender.email.domain.root_domaininexcel.com, jotform.com, microsoft.com, onenote.com, powerpoint.com, sharepoint.com, sharepointonline.com, wetrasnfer.comexcludes:sender.email.domain.root_domain

Tax Form: W-8BEN solicitation

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

Detects messages containing references to W-8BEN tax forms, commonly used in tax-related fraud schemes targeting individuals and businesses.

Threat Classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesSocial engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • body.current_thread
  • body.links
  • headers
  • headers.return_path
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and (
  // few links
  0 < length(body.links) < 20
  and any(body.links, network.whois(.href_url.domain).days_old <= 60)
  // fewer unique root domain links
  and length(distinct(body.links, .href_url.domain.root_domain)) < 10
  // sender domain matches no body domains
  and all(body.links,
          .href_url.domain.root_domain != sender.email.domain.root_domain
  )
)

// sender domain and return path are the same
and (sender.email.domain.root_domain == headers.return_path.domain.domain)
and not (sender.email.domain.root_domain != headers.return_path.domain.domain)
and (
  regex.icontains(subject.subject, ".*Foreign Tax*")
  or regex.icontains(subject.subject, ".*W-8BEN*")
)
// or any([body.current_thread.text, body.html.display_text, body.plain.raw],
and any([body.current_thread.text],
        regex.icontains(.,
                        'tax form',
                        'W-8BEN',
                        'Foreign Tax',
                        'tax return',
                        'tax preparation',
                        'tax documentation',
                        'regulatory',
                        'withholding',
                        'approve',
                        'non-US tax',
                        'treaty',
                        'Renew Documentation',
                        'Dear Client'
        )
)

// Registrant domain registered to China
and (
  any(body.links,
      network.whois(.href_url.domain).registrant_country_code =~ "CN"
  )
  or any(body.links,
         strings.icontains(network.whois(.href_url.domain).registrant_country,
                           "china"
         )
  )
)

// Alibaba Cloud nameservers
and all(network.whois(sender.email.domain).name_servers,
        .root_domain == "hichina.com"
)

Detection Logic

Scope: inbound message.

Detects messages containing references to W-8BEN tax forms, commonly used in tax-related fraud schemes targeting individuals and businesses.

  1. inbound message
  2. all of:
    • all of:
      • (0) < (length(body.links))
      • (length(body.links)) < (20)
    • any of body.links where:
      • network.whois(.href_url.domain).days_old <= 60
    • length(distinct(body.links, .href_url.domain.root_domain)) < 10
    • all of body.links where:
      • .href_url.domain.root_domain is not sender.email.domain.root_domain
  3. sender.email.domain.root_domain is headers.return_path.domain.domain
  4. not:
    • sender.email.domain.root_domain is not headers.return_path.domain.domain
  5. any of:
    • subject.subject matches '.*Foreign Tax*'
    • subject.subject matches '.*W-8BEN*'
  6. any([body.current_thread.text], regex.icontains(., 'tax form', 'W-8BEN', 'Foreign Tax', 'tax return', 'tax preparation', 'tax documentation', 'regulatory', 'withholding', 'approve', 'non-US tax', 'treaty', 'Renew Documentation', 'Dear Client' ) )
  7. any of:
    • any of body.links where:
      • network.whois(.href_url.domain).registrant_country_code =~ "CN"
    • any of body.links where:
      • strings.icontains(network.whois(.href_url.domain).registrant_country, "china" )
  8. all(network.whois(sender.email.domain).name_servers, .root_domain == "hichina.com" )

Inspects: body.current_thread.text, body.links, body.links[].href_url.domain, body.links[].href_url.domain.root_domain, headers.return_path.domain.domain, sender.email.domain, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: network.whois, regex.icontains, strings.icontains.

Indicators Matched (17)

FieldMatchValue
regex.icontainsregex.*Foreign Tax*
regex.icontainsregex.*W-8BEN*
regex.icontainsregextax form
regex.icontainsregexW-8BEN
regex.icontainsregexForeign Tax
regex.icontainsregextax return
regex.icontainsregextax preparation
regex.icontainsregextax documentation
regex.icontainsregexregulatory
regex.icontainsregexwithholding
regex.icontainsregexapprove
regex.icontainsregexnon-US tax
5 more
regex.icontainsregextreaty
regex.icontainsregexRenew Documentation
regex.icontainsregexDear Client
strings.icontainssubstringchina
network.whois(sender.email.domain).name_servers[].root_domainequalshichina.com

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(body.links)
      network.whois func_call "network.whois(.href_url.domain).registrant_country_code =~ \"CN\""
    any(body.links)
      strings.icontains func_call "strings.icontains(network.whois(.href_url.domain).registrant_country,\n                           \"china\"\n         )"
  any(body.links)
    network.whois func_call "network.whois(.href_url.domain).days_old <= 60"
  not
    sender.email.domain.root_domain cross_field_compare "headers.return_path.domain.domain"
  or
    subject.subject regex_match ".*Foreign Tax*"
    subject.subject regex_match ".*W-8BEN*"
  body.links length_compare "0"
  body.links length_compare "20"
  length func_call "length(distinct(body.links, .href_url.domain.root_domain)) < 10"
  sender.email.domain.root_domain cross_field_compare "headers.return_path.domain.domain"
  type.inbound eq "true"
   macro "all(body.links,\n          .href_url.domain.root_domain != sender.email.domain.root_domain\n  )"
   macro "all(network.whois(sender.email.domain).name_servers,\n        .root_domain == \"hichina.com\"\n)"
   macro "any([body.current_thread.text],\n        regex.icontains(.,\n                        'tax form',\n                        'W-8BEN',\n                        'Foreign Tax',\n                        'tax return',\n                        'tax preparation',\n                        'tax documentation',\n                        'regulatory',\n                        'withholding',\n                        'approve',\n                        'non-US tax',\n                        'treaty',\n                        'Renew Documentation',\n                        'Dear Client'\n        )\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
subject.subjectregex_match
  • .*Foreign Tax*
  • .*W-8BEN*
field:"subject.subject" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
sender.email.domain.root_domaincross_field_compareheaders.return_path.domain.domainexcludes:sender.email.domain.root_domain field:"sender.email.domain.root_domain" value:"headers.return_path.domain.domain"

Back to all Sublime MQL rules