Detection rules › Sublime MQL
Employee impersonation: Payroll fraud
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).
| Category | Values |
|---|---|
| Attack types | BEC/Fraud |
| Tactics and techniques | Impersonation: 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.
- inbound message
- sender.display_name contains ' '
- sender.display_name in $org_display_names
- length(attachments) is 0
- length(body.links) < 10
- length(body.current_thread.text) < 800
any of:
- sender.email.domain.root_domain not in $org_domains
- sender.email.domain.root_domain in $free_email_providers
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)'
any of:
not:
- profile.by_sender_email().solicited
- profile.by_sender().any_messages_malicious_or_spam
not:
- profile.by_sender().any_messages_benign
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)
| Field | Match | Value |
|---|---|---|
strings.contains | substring | |
regex.icontains | regex | (?: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 | regex | (?: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.ilike | substring | *fail |