Detection rules › Sublime MQL

Employee impersonation: Payroll fraud

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

This rule detects messages impersonating employees, from unsolicited senders attempting to reroute payroll or alter payment details.

Threat classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesImpersonation: Employee, Free email provider, Social engineering

Event coverage

Rule body MQL

type.inbound

// ensure the display name contains a space to avoid single named process accounts eg. 'billing, payment'
and strings.contains(sender.display_name, " ")
and sender.display_name in~ $org_display_names
and length(attachments) == 0
and length(body.links) < 10
and length(body.current_thread.text) < 800
and (
  sender.email.domain.root_domain not in $org_domains
  or sender.email.domain.root_domain in $free_email_providers
)
and 1 of (
  regex.icontains(body.current_thread.text,
                  '(?:pay\s?(?:roll|check|date|day)|direct deposit|(?:acct|account) rephrase|paid.{0,50}problems|\bACH\b|\bdd\b|gehalt|salario|salary|employee self[-\s]?service|\bESS\b.{0,30}(?:portal|access|log[-\s]?in)|access.{0,30}(?:HR|employee).{0,30}portal)'
  ),
  regex.icontains(subject.subject,
                  '(?:pay\s?(?:roll|check|date|day)|direct deposit|(?:acct|account) rephrase|paid.{0,50}problems|\bACH\b|\bdd\b|gehalt|salario|salary|employee self[-\s]?service|\bESS\b.{0,15}portal)'
  )
)
and (
  not profile.by_sender_email().solicited
  or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and (
      any(distinct(headers.hops, .authentication_results.dmarc is not null),
          strings.ilike(.authentication_results.dmarc, "*fail")
      )
    )
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection logic

Scope: inbound message.

This rule detects messages impersonating employees, from unsolicited senders attempting to reroute payroll or alter payment details.

  1. inbound message
  2. sender.display_name contains ' '
  3. sender.display_name in $org_display_names
  4. length(attachments) is 0
  5. length(body.links) < 10
  6. length(body.current_thread.text) < 800
  7. any of:
    • sender.email.domain.root_domain not in $org_domains
    • sender.email.domain.root_domain in $free_email_providers
  8. at least 1 of:
    • body.current_thread.text matches '(?:pay\\s?(?:roll|check|date|day)|direct deposit|(?:acct|account) rephrase|paid.{0,50}problems|\\bACH\\b|\\bdd\\b|gehalt|salario|salary|employee self[-\\s]?service|\\bESS\\b.{0,30}(?:portal|access|log[-\\s]?in)|access.{0,30}(?:HR|employee).{0,30}portal)'
    • subject.subject matches '(?:pay\\s?(?:roll|check|date|day)|direct deposit|(?:acct|account) rephrase|paid.{0,50}problems|\\bACH\\b|\\bdd\\b|gehalt|salario|salary|employee self[-\\s]?service|\\bESS\\b.{0,15}portal)'
  9. any of:
    • not:
      • profile.by_sender_email().solicited
    • profile.by_sender().any_messages_malicious_or_spam
  10. not:
    • profile.by_sender().any_messages_benign
  11. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • any of distinct(headers.hops) where:
        • .authentication_results.dmarc matches '*fail'
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: body.current_thread.text, body.links, headers.hops, headers.hops[].authentication_results.dmarc, sender.display_name, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: profile.by_sender, profile.by_sender_email, regex.icontains, strings.contains, strings.ilike. Reference lists: $free_email_providers, $high_trust_sender_root_domains, $org_display_names, $org_domains.

Indicators matched (4)

FieldMatchValue
strings.containssubstring
regex.icontainsregex(?:pay\s?(?:roll|check|date|day)|direct deposit|(?:acct|account) rephrase|paid.{0,50}problems|\bACH\b|\bdd\b|gehalt|salario|salary|employee self[-\s]?service|\bESS\b.{0,30}(?:portal|access|log[-\s]?in)|access.{0,30}(?:HR|employee).{0,30}portal)
regex.icontainsregex(?:pay\s?(?:roll|check|date|day)|direct deposit|(?:acct|account) rephrase|paid.{0,50}problems|\bACH\b|\bdd\b|gehalt|salario|salary|employee self[-\s]?service|\bESS\b.{0,15}portal)
strings.ilikesubstring*fail