Detection rules › Sublime MQL
Sublime MQL rules: callback
Brand impersonation: GitHub with callback scam indicators
#Detects messages using GitHub's noreply address that contain callback scam language, brand impersonation tactics, or fraudulent purchase/payment content with phone numbers for victim contact.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and sender.email.email == 'noreply@github.com'
and length(attachments) == 0
and (
any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "callback_scam" and .confidence != "low"
)
or (
regex.icontains(body.current_thread.text,
(
"mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck"
)
)
and (
3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*'),
strings.ilike(body.current_thread.text, '*host key*')
)
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(.,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
)
)
Detection Logic
Scope: inbound message.
Detects messages using GitHub's noreply address that contain callback scam language, brand impersonation tactics, or fraudulent purchase/payment content with phone numbers for victim contact.
- inbound message
- sender.email.email is 'noreply@github.com'
- length(attachments) == 0
any of:
- any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" and .confidence != "low" )
all of:
- body.current_thread.text matches 'mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck'
at least 3 of 14: body.current_thread.text matches any of 14 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**receipt**invoice**call**cancel**renew**refund**host key*
- any([body.current_thread.text, subject.subject], regex.icontains(., '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ) )
Inspects: body.current_thread.text, sender.email.email, subject.subject, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, strings.ilike.
Indicators Matched (19)
| Field | Match | Value |
|---|---|---|
sender.email.email | equals | noreply@github.com |
ml.nlu_classifier(body.current_thread.text).intents[].name | equals | callback_scam |
regex.icontains | regex | mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
strings.ilike | substring | *receipt* |
strings.ilike | substring | *invoice* |
7 more
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
strings.ilike | substring | *host key* |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
Stages and Predicates
Stage 1: mql_rule
and
or
and
body.current_thread.text regex_match "mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck"
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*'),\n strings.ilike(body.current_thread.text, '*host key*')\n )"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(.,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )\n )"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name == \"callback_scam\" and .confidence != \"low\"\n )"
attachments length_compare "0"
sender.email.email eq "noreply@github.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
sender.email.email | eq |
| field:"sender.email.email" kind:eq value:"noreply@github.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing in body or attachment (untrusted sender)
#Detects callback scams by analyzing text within images of receipts or invoices from untrusted senders.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) < 5
and (
any(attachments,
(
.file_type in $file_types_images
or .file_type in ("pdf", "xlsx", "docx")
)
and (
any(ml.nlu_classifier(beta.ocr(.).text).intents,
.name == "callback_scam" and .confidence in ("medium", "high")
)
or any(file.explode(.),
// exclude images taken with mobile cameras and screenshots from android
not any(.scan.exiftool.fields,
.key == "Model"
or (
.key == "Software"
and strings.starts_with(.value, "Android")
)
or (.key == "UserComment" and .value == "Screenshot")
)
and any(ml.nlu_classifier(.scan.ocr.raw).intents,
.name == "callback_scam"
and .confidence in ("medium", "high")
)
)
)
and (
// negate noreply unless a logo is found in the attachment
(
sender.email.local_part in ("no_reply", "noreply")
and any(ml.logo_detect(.).brands,
.name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee")
)
)
or sender.email.local_part not in ("no_reply", "noreply")
)
)
or (
any(ml.nlu_classifier(body.current_thread.text).intents,
.name in ("callback_scam") and .confidence in ("medium", "high")
)
and (
(
270 < length(body.current_thread.text) < 1750
or (
75 < length(body.current_thread.text) < 1750
and (
strings.ilike(body.current_thread.text,
"*PayPal*",
"*Norton*",
"*GeekSquad*",
"*Ebay*",
"*McAfee*",
"*=1"
)
// phone number regex
or regex.icontains(body.current_thread.text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
or 1 of (
strings.icontains(beta.ocr(file.message_screenshot()).text,
"geek squad"
),
strings.icontains(beta.ocr(file.message_screenshot()).text,
"lifelock"
),
strings.icontains(beta.ocr(file.message_screenshot()).text,
"best buy"
),
strings.icontains(beta.ocr(file.message_screenshot()).text,
"mcafee"
),
strings.icontains(beta.ocr(file.message_screenshot()).text,
"norton"
),
strings.icontains(beta.ocr(file.message_screenshot()).text,
"ebay"
),
strings.icontains(beta.ocr(file.message_screenshot()).text,
"paypal"
),
strings.icontains(beta.ocr(file.message_screenshot()).text,
"virus"
),
)
)
)
)
)
)
)
and not (
any(headers.domains, .domain == "smtp-out.gcp.bigcommerce.net")
and strings.icontains(body.html.raw, "bigcommerce.com")
)
and (
not profile.by_sender_email().solicited
or (
profile.by_sender_email().any_messages_malicious_or_spam
and not profile.by_sender_email().any_messages_benign
)
)
// 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)
)
// negate opsgenie email notifications
and not sender.email.email == 'opsgenie@opsgenie.net'
Detection Logic
Scope: inbound message.
Detects callback scams by analyzing text within images of receipts or invoices from untrusted senders.
- inbound message
- length(attachments) < 5
any of:
any of
attachmentswhere all hold:any of:
- .file_type in $file_types_images
- .file_type in ('pdf', 'xlsx', 'docx')
any of:
- any(ml.nlu_classifier(beta.ocr(.).text).intents, .name == "callback_scam" and .confidence in ("medium", "high") )
- any(file.explode(.), // exclude images taken with mobile cameras and screenshots from android not any(.scan.exiftool.fields, .key == "Model" or ( .key == "Software" and strings.starts_with(.value, "Android") ) or (.key == "UserComment" and .value == "Screenshot") ) and any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "callback_scam" and .confidence in ("medium", "high") ) )
any of:
all of:
- sender.email.local_part in ('no_reply', 'noreply')
- any(ml.logo_detect(.).brands, .name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee") )
- sender.email.local_part not in ('no_reply', 'noreply')
all of:
- any(ml.nlu_classifier(body.current_thread.text).intents, .name in ("callback_scam") and .confidence in ("medium", "high") )
any of:
all of:
- (270) < (length(body.current_thread.text))
- (length(body.current_thread.text)) < (1750)
all of:
all of:
- (75) < (length(body.current_thread.text))
- (length(body.current_thread.text)) < (1750)
any of:
body.current_thread.text matches any of 6 patterns
*PayPal**Norton**GeekSquad**Ebay**McAfee**=1
body.current_thread.text matches any of 2 patterns
\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
at least 1 of:
- strings.icontains(beta.ocr(file.message_screenshot()).text, "geek squad" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, "lifelock" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, "best buy" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, "mcafee" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, "norton" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, "ebay" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, "paypal" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, "virus" )
not:
all of:
any of
headers.domainswhere:- .domain is 'smtp-out.gcp.bigcommerce.net'
- body.html.raw contains 'bigcommerce.com'
any of:
not:
- profile.by_sender_email().solicited
all of:
- profile.by_sender_email().any_messages_malicious_or_spam
not:
- profile.by_sender_email().any_messages_benign
not:
all of:
- sender.email.domain.root_domain in $high_trust_sender_root_domains
- coalesce(headers.auth_summary.dmarc.pass, false)
not:
- sender.email.email is 'opsgenie@opsgenie.net'
Inspects: attachments[].file_type, body.current_thread.text, body.html.raw, headers.auth_summary.dmarc.pass, headers.domains, headers.domains[].domain, sender.email.domain.root_domain, sender.email.email, sender.email.local_part, type.inbound. Sensors: beta.ocr, file.explode, file.message_screenshot, ml.logo_detect, ml.nlu_classifier, profile.by_sender_email, regex.icontains, strings.icontains, strings.ilike, strings.starts_with. Reference lists: $file_types_images, $high_trust_sender_root_domains.
Indicators Matched (35)
| Field | Match | Value |
|---|---|---|
attachments[].file_type | member | pdf |
attachments[].file_type | member | xlsx |
attachments[].file_type | member | docx |
ml.nlu_classifier(beta.ocr(attachments[]).text).intents[].name | equals | callback_scam |
ml.nlu_classifier(beta.ocr(attachments[]).text).intents[].confidence | member | medium |
ml.nlu_classifier(beta.ocr(attachments[]).text).intents[].confidence | member | high |
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name | equals | callback_scam |
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence | member | medium |
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence | member | high |
sender.email.local_part | member | no_reply |
sender.email.local_part | member | noreply |
ml.logo_detect(attachments[]).brands[].name | member | PayPal |
23 more
ml.logo_detect(attachments[]).brands[].name | member | Norton |
ml.logo_detect(attachments[]).brands[].name | member | GeekSquad |
ml.logo_detect(attachments[]).brands[].name | member | Ebay |
ml.logo_detect(attachments[]).brands[].name | member | McAfee |
ml.nlu_classifier(body.current_thread.text).intents[].name | member | callback_scam |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | member | medium |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | member | high |
strings.ilike | substring | *PayPal* |
strings.ilike | substring | *Norton* |
strings.ilike | substring | *GeekSquad* |
strings.ilike | substring | *Ebay* |
strings.ilike | substring | *McAfee* |
strings.ilike | substring | *=1 |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
strings.icontains | substring | geek squad |
strings.icontains | substring | lifelock |
strings.icontains | substring | best buy |
strings.icontains | substring | mcafee |
strings.icontains | substring | norton |
strings.icontains | substring | ebay |
strings.icontains | substring | paypal |
strings.icontains | substring | virus |
Stages and Predicates
Stage 1: mql_rule
and
or
and
or
and
or
body.current_thread.text ends_with "=1"
body.current_thread.text match "Ebay"
body.current_thread.text match "GeekSquad"
body.current_thread.text match "McAfee"
body.current_thread.text match "Norton"
body.current_thread.text match "PayPal"
body.current_thread.text regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
body.current_thread.text regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"best buy\"\n )"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"ebay\"\n )"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"geek squad\"\n )"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"lifelock\"\n )"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"mcafee\"\n )"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"norton\"\n )"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"paypal\"\n )"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text,\n \"virus\"\n )"
body.current_thread.text length_compare "75"
body.current_thread.text length_compare "1750"
and
body.current_thread.text length_compare "270"
body.current_thread.text length_compare "1750"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name in (\"callback_scam\") and .confidence in (\"medium\", \"high\")\n )"
any(attachments)
and
or
and
sender.email.local_part in ["no_reply", "noreply"]
macro "any(ml.logo_detect(.).brands,\n .name in (\"PayPal\", \"Norton\", \"GeekSquad\", \"Ebay\", \"McAfee\")\n )"
not
sender.email.local_part in ["no_reply", "noreply"]
or
attachments.file_type in ["docx", "pdf", "xlsx"]
attachments.file_type macro "attachments[].file_type in file_types_images"
or
macro "any(file.explode(.),\n\n // exclude images taken with mobile cameras and screenshots from android\n not any(.scan.exiftool.fields,\n .key == \"Model\"\n or (\n .key == \"Software\"\n and strings.starts_with(.value, \"Android\")\n )\n or (.key == \"UserComment\" and .value == \"Screenshot\")\n )\n and any(ml.nlu_classifier(.scan.ocr.raw).intents,\n .name == \"callback_scam\"\n and .confidence in (\"medium\", \"high\")\n )\n )"
macro "any(ml.nlu_classifier(beta.ocr(.).text).intents,\n .name == \"callback_scam\" and .confidence in (\"medium\", \"high\")\n )"
not
and
any(headers.domains)
headers.domains.domain eq "smtp-out.gcp.bigcommerce.net"
body.html.raw contains "bigcommerce.com"
or
and
not
profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
not
profile.by_sender_email func_call "profile.by_sender_email().solicited"
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"
not
sender.email.email eq "opsgenie@opsgenie.net"
attachments length_compare "5"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
body.current_thread.text | wildcard |
| field:"body.current_thread.text" kind:wildcard |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
headers.domains | array_any | excludes:headers.domains | |
body.html.raw | contains | bigcommerce.com | excludes:body.html.raw field:"body.html.raw" value:"bigcommerce.com" |
headers.auth_summary.dmarc.pass | eq | true | excludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true" |
headers.auth_summary.dmarc.pass | is_not_null | excludes:headers.auth_summary.dmarc.pass | |
sender.email.email | eq | opsgenie@opsgenie.net | excludes:sender.email.email field:"sender.email.email" value:"opsgenie@opsgenie.net" |
Callback phishing via Adobe Sign comment
#This rule inspects messages originating from legitimate Adobe Sign infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Evasion, Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
// Legitimate Docusign sending infratructure
and sender.email.domain.root_domain == 'adobesign.com'
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
and (
// this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
regex.icontains(strings.replace_confusables(body.current_thread.text),
'(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
)
or any(ml.logo_detect(file.message_screenshot()).brands,
.name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T")
)
)
and (
(
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
// caused by messages which mention cancelling or otherwise managing a subscription
// it is also synced and below for message_screenshot OCR output
3 of (
strings.icontains(body.current_thread.text, 'purchase'),
strings.icontains(body.current_thread.text, 'payment'),
strings.icontains(body.current_thread.text, 'transaction'),
strings.icontains(body.current_thread.text, 'subscription'),
strings.icontains(body.current_thread.text, 'antivirus'),
strings.icontains(body.current_thread.text, 'order'),
strings.icontains(body.current_thread.text, 'support'),
strings.icontains(body.current_thread.text, 'help line'),
strings.icontains(body.current_thread.text, 'receipt'),
strings.icontains(body.current_thread.text, 'invoice'),
strings.icontains(body.current_thread.text, 'call'),
strings.icontains(body.current_thread.text, 'cancel'),
strings.icontains(body.current_thread.text, 'renew'),
strings.icontains(body.current_thread.text, 'refund'),
regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
strings.icontains(body.current_thread.text, "+1"),
strings.icontains(body.current_thread.text, "amount"),
strings.icontains(body.current_thread.text, "charged"),
strings.icontains(body.current_thread.text, "crypto"),
strings.icontains(body.current_thread.text, "wallet address"),
regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
)
// phone number regex
and regex.icontains(body.current_thread.text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
or (
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// and above for current_thread.text
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
3 of (
strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'subscription'
),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
regex.icontains(beta.ocr(file.message_screenshot()).text,
"(?:reach|contact) us at"
),
strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'wallet address'
),
regex.icontains(beta.ocr(file.message_screenshot()).text,
'\$\d{3}\.\d{2}\b'
),
)
// phone number regex
and regex.icontains(beta.ocr(file.message_screenshot()).text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
// negate messages with previous threads. While callback phishing with thread hijacking or with current_thread
// padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
and not regex.icount(beta.ocr(file.message_screenshot()).text,
'(?:from|to|sent|date|cc|subject):'
) > 3
// this notation of previous threads often only occurs once
and not regex.icontains(beta.ocr(file.message_screenshot()).text,
'wrote:[\r\n]'
)
)
)
Detection Logic
Scope: inbound message.
This rule inspects messages originating from legitimate Adobe Sign infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
- inbound message
- length(attachments) == 0
- sender.email.domain.root_domain is 'adobesign.com'
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)' )
- any(ml.logo_detect(file.message_screenshot()).brands, .name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T") )
any of:
all of:
at least 3 of:
- body.current_thread.text contains 'purchase'
- body.current_thread.text contains 'payment'
- body.current_thread.text contains 'transaction'
- body.current_thread.text contains 'subscription'
- body.current_thread.text contains 'antivirus'
- body.current_thread.text contains 'order'
- body.current_thread.text contains 'support'
- body.current_thread.text contains 'help line'
- body.current_thread.text contains 'receipt'
- body.current_thread.text contains 'invoice'
- body.current_thread.text contains 'call'
- body.current_thread.text contains 'cancel'
- body.current_thread.text contains 'renew'
- body.current_thread.text contains 'refund'
- body.current_thread.text matches '(?:reach|contact) us at'
- body.current_thread.text contains '+1'
- body.current_thread.text contains 'amount'
- body.current_thread.text contains 'charged'
- body.current_thread.text contains 'crypto'
- body.current_thread.text contains 'wallet address'
- body.current_thread.text matches '\\$\\d{3}\\.\\d{2}\\b'
body.current_thread.text matches any of 2 patterns
\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
all of:
at least 3 of:
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'subscription' )
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'order')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'support')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'call')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund')
- regex.icontains(beta.ocr(file.message_screenshot()).text, "(?:reach|contact) us at" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, '+1')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'wallet address' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\$\d{3}\.\d{2}\b' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' )
not:
- regex.icount(beta.ocr(file.message_screenshot()).text, '(?:from|to|sent|date|cc|subject):' ) > 3
not:
- regex.icontains(beta.ocr(file.message_screenshot()).text, 'wrote:[\r\n]' )
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.ocr, file.message_screenshot, ml.logo_detect, regex.icontains, regex.icount, strings.icontains, strings.replace_confusables.
Indicators Matched (32)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | adobesign.com |
regex.icontains | regex | (p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t) |
ml.logo_detect(file.message_screenshot()).brands[].name | member | PayPal |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Norton |
ml.logo_detect(file.message_screenshot()).brands[].name | member | GeekSquad |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Ebay |
ml.logo_detect(file.message_screenshot()).brands[].name | member | McAfee |
ml.logo_detect(file.message_screenshot()).brands[].name | member | AT&T |
strings.icontains | substring | purchase |
strings.icontains | substring | payment |
strings.icontains | substring | transaction |
strings.icontains | substring | subscription |
20 more
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | help line |
strings.icontains | substring | receipt |
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
regex.icontains | regex | (?:reach|contact) us at |
strings.icontains | substring | +1 |
strings.icontains | substring | amount |
strings.icontains | substring | charged |
strings.icontains | substring | crypto |
strings.icontains | substring | wallet address |
regex.icontains | regex | \$\d{3}\.\d{2}\b |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
strings.icontains | substring | helpdesk |
Stages and Predicates
Stage 1: mql_rule
and
or
and
or
body.current_thread.text regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
body.current_thread.text regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
macro "3 of (\n strings.icontains(body.current_thread.text, 'purchase'),\n strings.icontains(body.current_thread.text, 'payment'),\n strings.icontains(body.current_thread.text, 'transaction'),\n strings.icontains(body.current_thread.text, 'subscription'),\n strings.icontains(body.current_thread.text, 'antivirus'),\n strings.icontains(body.current_thread.text, 'order'),\n strings.icontains(body.current_thread.text, 'support'),\n strings.icontains(body.current_thread.text, 'help line'),\n strings.icontains(body.current_thread.text, 'receipt'),\n strings.icontains(body.current_thread.text, 'invoice'),\n strings.icontains(body.current_thread.text, 'call'),\n strings.icontains(body.current_thread.text, 'cancel'),\n strings.icontains(body.current_thread.text, 'renew'),\n strings.icontains(body.current_thread.text, 'refund'),\n regex.icontains(body.current_thread.text, \"(?:reach|contact) us at\"),\n strings.icontains(body.current_thread.text, \"+1\"),\n strings.icontains(body.current_thread.text, \"amount\"),\n strings.icontains(body.current_thread.text, \"charged\"),\n strings.icontains(body.current_thread.text, \"crypto\"),\n strings.icontains(body.current_thread.text, \"wallet address\"),\n regex.icontains(body.current_thread.text, '\\$\\d{3}\\.\\d{2}\\b'),\n )"
and
not
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n 'wrote:[\\r\\n]'\n )"
not
regex.icount func_call "regex.icount(beta.ocr(file.message_screenshot()).text,\n '(?:from|to|sent|date|cc|subject):'\n ) > 3"
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )"
macro "3 of (\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'subscription'\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n \"(?:reach|contact) us at\"\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'wallet address'\n ),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\$\\d{3}\\.\\d{2}\\b'\n ),\n )"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
or
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'\n )"
macro "any(ml.logo_detect(file.message_screenshot()).brands,\n .name in (\"PayPal\", \"Norton\", \"GeekSquad\", \"Ebay\", \"McAfee\", \"AT&T\")\n )"
attachments length_compare "0"
sender.email.domain.root_domain eq "adobesign.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"adobesign.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via calendar invite
#Detects calendar invites containing callback phishing language in the DESCRIPTION or SUMMARY of the invite.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Social engineering, Evasion, ICS Phishing |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) > 0
and all(attachments, .content_type in ("text/calendar", "application/ics"))
and any(attachments,
// extract the calendar invite summary or description and use NLU against it
any(file.explode(.),
any(.scan.ics.calendars,
any(.components,
any(ml.nlu_classifier(.summary).intents,
.name == "callback_scam" and .confidence == "high"
)
or (
any(ml.nlu_classifier(.description).intents,
.name == "callback_scam"
)
or any(ml.nlu_classifier(strings.parse_html(.description).display_text
).intents,
.name == "callback_scam"
)
or (
any(ml.nlu_classifier(.description).topics,
.name == "Request to View Invoice"
and .confidence == "high"
)
// emoji regex
and regex.contains(.description,
'[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{FE00}-\x{FE0F}\x{200D}\x{20E3}\x{E0020}-\x{E007F}]'
)
)
)
)
)
)
)
and (
not profile.by_sender_email().solicited
and not profile.by_sender_email().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 not coalesce(headers.auth_summary.dmarc.pass, false)
)
or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
Detection Logic
Scope: inbound message.
Detects calendar invites containing callback phishing language in the DESCRIPTION or SUMMARY of the invite.
- inbound message
- length(attachments) > 0
all of
attachmentswhere:- .content_type in ('text/calendar', 'application/ics')
any of
attachmentswhere:- any(file.explode(.), any(.scan.ics.calendars, any(.components, any(ml.nlu_classifier(.summary).intents, .name == "callback_scam" and .confidence == "high" ) or ( any(ml.nlu_classifier(.description).intents, .name == "callback_scam" ) or any(ml.nlu_classifier(strings.parse_html(.description).display_text ).intents, .name == "callback_scam" ) or ( any(ml.nlu_classifier(.description).topics, .name == "Request to View Invoice" and .confidence == "high" ) // emoji regex and regex.contains(.description, '[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{FE00}-\x{FE0F}\x{200D}\x{20E3}\x{E0020}-\x{E007F}]' ) ) ) ) ) )
all of:
not:
- profile.by_sender_email().solicited
not:
- profile.by_sender_email().any_messages_benign
any of:
all of:
- sender.email.domain.root_domain in $high_trust_sender_root_domains
not:
- coalesce(headers.auth_summary.dmarc.pass, false)
- sender.email.domain.root_domain not in $high_trust_sender_root_domains
Inspects: attachments[].content_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.nlu_classifier, profile.by_sender_email, regex.contains, strings.parse_html. Reference lists: $high_trust_sender_root_domains.
Indicators Matched (9)
| Field | Match | Value |
|---|---|---|
attachments[].content_type | member | text/calendar |
attachments[].content_type | member | application/ics |
ml.nlu_classifier(file.explode(attachments[])[].scan.ics.calendars[].components[].summary).intents[].name | equals | callback_scam |
ml.nlu_classifier(file.explode(attachments[])[].scan.ics.calendars[].components[].summary).intents[].confidence | equals | high |
ml.nlu_classifier(file.explode(attachments[])[].scan.ics.calendars[].components[].description).intents[].name | equals | callback_scam |
ml.nlu_classifier(strings.parse_html(file.explode(attachments[])[].scan.ics.calendars[].components[].description).display_text).intents[].name | equals | callback_scam |
ml.nlu_classifier(file.explode(attachments[])[].scan.ics.calendars[].components[].description).topics[].name | equals | Request to View Invoice |
ml.nlu_classifier(file.explode(attachments[])[].scan.ics.calendars[].components[].description).topics[].confidence | equals | high |
regex.contains | regex | [\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{FE00}-\x{FE0F}\x{200D}\x{20E3}\x{E0020}-\x{E007F}] |
Stages and Predicates
Stage 1: mql_rule
and
or
and
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"
sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
not
profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
not
profile.by_sender_email func_call "profile.by_sender_email().solicited"
any(attachments)
macro "any(file.explode(.),\n any(.scan.ics.calendars,\n any(.components,\n any(ml.nlu_classifier(.summary).intents,\n .name == \"callback_scam\" and .confidence == \"high\"\n )\n or (\n any(ml.nlu_classifier(.description).intents,\n .name == \"callback_scam\"\n )\n or any(ml.nlu_classifier(strings.parse_html(.description).display_text\n ).intents,\n .name == \"callback_scam\"\n )\n or (\n any(ml.nlu_classifier(.description).topics,\n .name == \"Request to View Invoice\"\n and .confidence == \"high\"\n )\n // emoji regex\n and regex.contains(.description,\n '[\\x{1F600}-\\x{1F64F}\\x{1F300}-\\x{1F5FF}\\x{1F680}-\\x{1F6FF}\\x{1F900}-\\x{1F9FF}\\x{2600}-\\x{26FF}\\x{2700}-\\x{27BF}\\x{FE00}-\\x{FE0F}\\x{200D}\\x{20E3}\\x{E0020}-\\x{E007F}]'\n )\n )\n )\n )\n )\n )"
attachments length_compare "0"
type.inbound eq "true"
macro "all(attachments, .content_type in (\"text/calendar\", \"application/ics\"))"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via DocuSign comment
#This rule inspects messages originating from legitimate DocuSign infrastructure, with a DocuSign logo that match Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Evasion, Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
// Legitimate Docusign sending infratructure
and sender.email.domain.root_domain == 'docusign.net'
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
// Docusign Logo
and any(ml.logo_detect(file.message_screenshot()).brands, .name == "DocuSign")
// Callback Phishing
and regex.icontains(body.current_thread.text,
(
"mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck"
)
)
and 3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*')
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(.,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
Detection Logic
Scope: inbound message.
This rule inspects messages originating from legitimate DocuSign infrastructure, with a DocuSign logo that match Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
- inbound message
- length(attachments) == 0
- sender.email.domain.root_domain is 'docusign.net'
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
- any(ml.logo_detect(file.message_screenshot()).brands, .name == "DocuSign")
- body.current_thread.text matches 'mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck'
at least 3 of 14: body.current_thread.text matches any of 14 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**help line**receipt**invoice**call**cancel**renew**refund*
- any([body.current_thread.text, subject.subject], regex.icontains(., '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ) )
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.message_screenshot, ml.logo_detect, regex.icontains, strings.ilike.
Indicators Matched (19)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | docusign.net |
ml.logo_detect(file.message_screenshot()).brands[].name | equals | DocuSign |
regex.icontains | regex | mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
strings.ilike | substring | *help line* |
strings.ilike | substring | *receipt* |
7 more
strings.ilike | substring | *invoice* |
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
Stages and Predicates
Stage 1: mql_rule
and
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
attachments length_compare "0"
body.current_thread.text regex_match "mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck"
sender.email.domain.root_domain eq "docusign.net"
type.inbound eq "true"
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*')\n)"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(.,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )\n)"
macro "any(ml.logo_detect(file.message_screenshot()).brands, .name == \"DocuSign\")"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"docusign.net" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via e-signature service
#Detects messages containing e-signature topics combined with tech support keywords and phone numbers. Message includes brand impersonation (PayPal, Norton, McAfee, etc.) and transaction-related language, with no attachments and reply-to addresses from free email providers.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Free email provider, Impersonation: Brand, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
and any(headers.reply_to, .email.domain.root_domain in $free_email_providers)
and any(beta.ml_topic(body.current_thread.text).topics, .name == "E-Signature")
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
and (
// this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
regex.icontains(strings.replace_confusables(body.current_thread.text),
'(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
)
or any(ml.logo_detect(file.message_screenshot()).brands,
.name in (
"PayPal",
"Norton",
"GeekSquad",
"Ebay",
"McAfee",
"AT&T",
"Microsoft"
)
)
)
and (
(
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
// caused by messages which mention cancelling or otherwise managing a subscription
// it is also synced and below for message_screenshot OCR output
3 of (
strings.icontains(body.current_thread.text, 'purchase'),
strings.icontains(body.current_thread.text, 'payment'),
strings.icontains(body.current_thread.text, 'transaction'),
strings.icontains(body.current_thread.text, 'subscription'),
strings.icontains(body.current_thread.text, 'antivirus'),
strings.icontains(body.current_thread.text, 'order'),
strings.icontains(body.current_thread.text, 'support'),
strings.icontains(body.current_thread.text, 'help line'),
strings.icontains(body.current_thread.text, 'receipt'),
strings.icontains(body.current_thread.text, 'invoice'),
strings.icontains(body.current_thread.text, 'call'),
strings.icontains(body.current_thread.text, 'cancel'),
strings.icontains(body.current_thread.text, 'renew'),
strings.icontains(body.current_thread.text, 'refund'),
regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
strings.icontains(body.current_thread.text, "+1"),
strings.icontains(body.current_thread.text, "amount"),
strings.icontains(body.current_thread.text, "charged"),
strings.icontains(body.current_thread.text, "crypto"),
strings.icontains(body.current_thread.text, "wallet address"),
regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
)
// phone number regex
and regex.icontains(body.current_thread.text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
or (
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// and above for current_thread.text
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
3 of (
strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'subscription'
),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
regex.icontains(beta.ocr(file.message_screenshot()).text,
"(?:reach|contact) us at"
),
strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'wallet address'
),
regex.icontains(beta.ocr(file.message_screenshot()).text,
'\$\d{3}\.\d{2}\b'
),
)
// phone number regex
and regex.icontains(beta.ocr(file.message_screenshot()).text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
// negate messages with previous threads. While callback phishing with thread hijacking or with current_thread
// padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
and not regex.icount(beta.ocr(file.message_screenshot()).text,
'(?:from|to|sent|date|cc|subject):'
) > 3
// this notation of previous threads often only occurs once
and not regex.icontains(beta.ocr(file.message_screenshot()).text,
'wrote:[\r\n]'
)
)
)
Detection Logic
Scope: inbound message.
Detects messages containing e-signature topics combined with tech support keywords and phone numbers. Message includes brand impersonation (PayPal, Norton, McAfee, etc.) and transaction-related language, with no attachments and reply-to addresses from free email providers.
- inbound message
- length(attachments) == 0
any of
headers.reply_towhere:- .email.domain.root_domain in $free_email_providers
- any(beta.ml_topic(body.current_thread.text).topics, .name == "E-Signature")
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)' )
- any(ml.logo_detect(file.message_screenshot()).brands, .name in ( "PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T", "Microsoft" ) )
any of:
all of:
at least 3 of:
- body.current_thread.text contains 'purchase'
- body.current_thread.text contains 'payment'
- body.current_thread.text contains 'transaction'
- body.current_thread.text contains 'subscription'
- body.current_thread.text contains 'antivirus'
- body.current_thread.text contains 'order'
- body.current_thread.text contains 'support'
- body.current_thread.text contains 'help line'
- body.current_thread.text contains 'receipt'
- body.current_thread.text contains 'invoice'
- body.current_thread.text contains 'call'
- body.current_thread.text contains 'cancel'
- body.current_thread.text contains 'renew'
- body.current_thread.text contains 'refund'
- body.current_thread.text matches '(?:reach|contact) us at'
- body.current_thread.text contains '+1'
- body.current_thread.text contains 'amount'
- body.current_thread.text contains 'charged'
- body.current_thread.text contains 'crypto'
- body.current_thread.text contains 'wallet address'
- body.current_thread.text matches '\\$\\d{3}\\.\\d{2}\\b'
body.current_thread.text matches any of 2 patterns
\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
all of:
at least 3 of:
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'subscription' )
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'order')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'support')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'call')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund')
- regex.icontains(beta.ocr(file.message_screenshot()).text, "(?:reach|contact) us at" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, '+1')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'wallet address' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\$\d{3}\.\d{2}\b' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' )
not:
- regex.icount(beta.ocr(file.message_screenshot()).text, '(?:from|to|sent|date|cc|subject):' ) > 3
not:
- regex.icontains(beta.ocr(file.message_screenshot()).text, 'wrote:[\r\n]' )
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, headers.reply_to, headers.reply_to[].email.domain.root_domain, type.inbound. Sensors: beta.ml_topic, beta.ocr, file.message_screenshot, ml.logo_detect, regex.icontains, regex.icount, strings.icontains, strings.replace_confusables. Reference lists: $free_email_providers.
Indicators Matched (33)
| Field | Match | Value |
|---|---|---|
beta.ml_topic(body.current_thread.text).topics[].name | equals | E-Signature |
regex.icontains | regex | (p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t) |
ml.logo_detect(file.message_screenshot()).brands[].name | member | PayPal |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Norton |
ml.logo_detect(file.message_screenshot()).brands[].name | member | GeekSquad |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Ebay |
ml.logo_detect(file.message_screenshot()).brands[].name | member | McAfee |
ml.logo_detect(file.message_screenshot()).brands[].name | member | AT&T |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Microsoft |
strings.icontains | substring | purchase |
strings.icontains | substring | payment |
strings.icontains | substring | transaction |
21 more
strings.icontains | substring | subscription |
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | help line |
strings.icontains | substring | receipt |
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
regex.icontains | regex | (?:reach|contact) us at |
strings.icontains | substring | +1 |
strings.icontains | substring | amount |
strings.icontains | substring | charged |
strings.icontains | substring | crypto |
strings.icontains | substring | wallet address |
regex.icontains | regex | \$\d{3}\.\d{2}\b |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
strings.icontains | substring | helpdesk |
Stages and Predicates
Stage 1: mql_rule
and
or
and
or
body.current_thread.text regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
body.current_thread.text regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
macro "3 of (\n strings.icontains(body.current_thread.text, 'purchase'),\n strings.icontains(body.current_thread.text, 'payment'),\n strings.icontains(body.current_thread.text, 'transaction'),\n strings.icontains(body.current_thread.text, 'subscription'),\n strings.icontains(body.current_thread.text, 'antivirus'),\n strings.icontains(body.current_thread.text, 'order'),\n strings.icontains(body.current_thread.text, 'support'),\n strings.icontains(body.current_thread.text, 'help line'),\n strings.icontains(body.current_thread.text, 'receipt'),\n strings.icontains(body.current_thread.text, 'invoice'),\n strings.icontains(body.current_thread.text, 'call'),\n strings.icontains(body.current_thread.text, 'cancel'),\n strings.icontains(body.current_thread.text, 'renew'),\n strings.icontains(body.current_thread.text, 'refund'),\n regex.icontains(body.current_thread.text, \"(?:reach|contact) us at\"),\n strings.icontains(body.current_thread.text, \"+1\"),\n strings.icontains(body.current_thread.text, \"amount\"),\n strings.icontains(body.current_thread.text, \"charged\"),\n strings.icontains(body.current_thread.text, \"crypto\"),\n strings.icontains(body.current_thread.text, \"wallet address\"),\n regex.icontains(body.current_thread.text, '\\$\\d{3}\\.\\d{2}\\b'),\n )"
and
not
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n 'wrote:[\\r\\n]'\n )"
not
regex.icount func_call "regex.icount(beta.ocr(file.message_screenshot()).text,\n '(?:from|to|sent|date|cc|subject):'\n ) > 3"
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )"
macro "3 of (\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'subscription'\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n \"(?:reach|contact) us at\"\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'wallet address'\n ),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\$\\d{3}\\.\\d{2}\\b'\n ),\n )"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
any(headers.reply_to)
headers.reply_to.email.domain.root_domain macro "headers.reply_to[].email.domain.root_domain in free_email_providers"
or
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'\n )"
macro "any(ml.logo_detect(file.message_screenshot()).brands,\n .name in (\n \"PayPal\",\n \"Norton\",\n \"GeekSquad\",\n \"Ebay\",\n \"McAfee\",\n \"AT&T\",\n \"Microsoft\"\n )\n )"
attachments length_compare "0"
type.inbound eq "true"
macro "any(beta.ml_topic(body.current_thread.text).topics, .name == \"E-Signature\")"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via extensionless rfc822 attachment
#This rule detects messages with an unknown file_type (extensionless) and a content_type of 'message/rfc822' containing an image file with Callback Phishing indicators.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Impersonation: Brand, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and any(attachments,
.file_type == "unknown"
and (.content_type == "message/rfc822" or .file_extension in ('eml'))
and any(file.explode(.),
strings.starts_with(.flavors.mime, "image")
// and Image contains callback phishing indicators
and 4 of (
strings.icontains(.scan.ocr.raw, "purchase"),
strings.icontains(.scan.ocr.raw, "subscription"),
strings.icontains(.scan.ocr.raw, "antivirus"),
strings.icontains(.scan.ocr.raw, "order"),
strings.icontains(.scan.ocr.raw, "support"),
strings.icontains(.scan.ocr.raw, "receipt"),
strings.icontains(.scan.ocr.raw, "amount"),
strings.icontains(.scan.ocr.raw, "charged"),
strings.icontains(.scan.ocr.raw, "invoice"),
strings.icontains(.scan.ocr.raw, "call"),
strings.icontains(.scan.ocr.raw, "cancel"),
strings.icontains(.scan.ocr.raw, "renew"),
strings.icontains(.scan.ocr.raw, "refund"),
strings.icontains(.scan.ocr.raw, "+1")
)
)
and any(file.explode(.),
strings.ilike(.scan.ocr.raw,
"*geek*squad*",
"*lifelock*",
"*best buy*",
"*mcafee*",
"*norton*",
"*ebay*",
"*paypal*",
"*secure anywhere*"
)
or any(ml.nlu_classifier(.scan.ocr.raw).intents,
.name in ("callback_scam")
and .confidence == "high"
and length(body.current_thread.text) < 1500
)
)
)
and (
not profile.by_sender().solicited
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 not headers.auth_summary.dmarc.pass
)
or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
Detection Logic
Scope: inbound message.
This rule detects messages with an unknown file_type (extensionless) and a content_type of 'message/rfc822' containing an image file with Callback Phishing indicators.
- inbound message
any of
attachmentswhere all hold:- .file_type is 'unknown'
any of:
- .content_type is 'message/rfc822'
- .file_extension in ('eml')
- any(file.explode(.), strings.starts_with(.flavors.mime, "image") // and Image contains callback phishing indicators and 4 of ( strings.icontains(.scan.ocr.raw, "purchase"), strings.icontains(.scan.ocr.raw, "subscription"), strings.icontains(.scan.ocr.raw, "antivirus"), strings.icontains(.scan.ocr.raw, "order"), strings.icontains(.scan.ocr.raw, "support"), strings.icontains(.scan.ocr.raw, "receipt"), strings.icontains(.scan.ocr.raw, "amount"), strings.icontains(.scan.ocr.raw, "charged"), strings.icontains(.scan.ocr.raw, "invoice"), strings.icontains(.scan.ocr.raw, "call"), strings.icontains(.scan.ocr.raw, "cancel"), strings.icontains(.scan.ocr.raw, "renew"), strings.icontains(.scan.ocr.raw, "refund"), strings.icontains(.scan.ocr.raw, "+1") ) )
- any(file.explode(.), strings.ilike(.scan.ocr.raw, "*geek*squad*", "*lifelock*", "*best buy*", "*mcafee*", "*norton*", "*ebay*", "*paypal*", "*secure anywhere*" ) or any(ml.nlu_classifier(.scan.ocr.raw).intents, .name in ("callback_scam") and .confidence == "high" and length(body.current_thread.text) < 1500 ) )
all of:
not:
- profile.by_sender().solicited
not:
- profile.by_sender().any_messages_benign
any of:
all of:
- sender.email.domain.root_domain in $high_trust_sender_root_domains
not:
- headers.auth_summary.dmarc.pass
- sender.email.domain.root_domain not in $high_trust_sender_root_domains
Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, body.current_thread.text, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.nlu_classifier, profile.by_sender, strings.icontains, strings.ilike, strings.starts_with. Reference lists: $high_trust_sender_root_domains.
Indicators Matched (28)
| Field | Match | Value |
|---|---|---|
attachments[].file_type | equals | unknown |
attachments[].content_type | equals | message/rfc822 |
attachments[].file_extension | member | eml |
strings.starts_with | prefix | image |
strings.icontains | substring | purchase |
strings.icontains | substring | subscription |
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | receipt |
strings.icontains | substring | amount |
strings.icontains | substring | charged |
16 more
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
strings.icontains | substring | +1 |
strings.ilike | substring | *geek*squad* |
strings.ilike | substring | *lifelock* |
strings.ilike | substring | *best buy* |
strings.ilike | substring | *mcafee* |
strings.ilike | substring | *norton* |
strings.ilike | substring | *ebay* |
strings.ilike | substring | *paypal* |
strings.ilike | substring | *secure anywhere* |
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name | member | callback_scam |
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence | equals | high |
Stages and Predicates
Stage 1: mql_rule
and
any(attachments)
and
or
attachments.content_type eq "message/rfc822"
attachments.file_extension eq "eml"
attachments.file_type eq "unknown"
macro "any(file.explode(.),\n strings.ilike(.scan.ocr.raw,\n \"*geek*squad*\",\n \"*lifelock*\",\n \"*best buy*\",\n \"*mcafee*\",\n \"*norton*\",\n \"*ebay*\",\n \"*paypal*\",\n \"*secure anywhere*\"\n )\n or any(ml.nlu_classifier(.scan.ocr.raw).intents,\n .name in (\"callback_scam\")\n and .confidence == \"high\"\n and length(body.current_thread.text) < 1500\n )\n )"
macro "any(file.explode(.),\n strings.starts_with(.flavors.mime, \"image\")\n\n // and Image contains callback phishing indicators\n and 4 of (\n strings.icontains(.scan.ocr.raw, \"purchase\"),\n strings.icontains(.scan.ocr.raw, \"subscription\"),\n strings.icontains(.scan.ocr.raw, \"antivirus\"),\n strings.icontains(.scan.ocr.raw, \"order\"),\n strings.icontains(.scan.ocr.raw, \"support\"),\n strings.icontains(.scan.ocr.raw, \"receipt\"),\n strings.icontains(.scan.ocr.raw, \"amount\"),\n strings.icontains(.scan.ocr.raw, \"charged\"),\n strings.icontains(.scan.ocr.raw, \"invoice\"),\n strings.icontains(.scan.ocr.raw, \"call\"),\n strings.icontains(.scan.ocr.raw, \"cancel\"),\n strings.icontains(.scan.ocr.raw, \"renew\"),\n strings.icontains(.scan.ocr.raw, \"refund\"),\n strings.icontains(.scan.ocr.raw, \"+1\")\n )\n )"
or
and
not
headers.auth_summary.dmarc.pass eq "true"
sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
not
profile.by_sender func_call "profile.by_sender().any_messages_benign"
not
profile.by_sender func_call "profile.by_sender().solicited"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via Google Group abuse
#A fraudulent invoice/receipt found in the body of the message, delivered via a Google Group mailing list.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Free email provider, Impersonation: Brand, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) < 5
and sender.email.domain.domain == "googlegroups.com"
and (
any(attachments,
(.file_type in $file_types_images or .file_type == "pdf")
and (
any(file.explode(.),
// exclude images taken with mobile cameras and screenshots from android
not any(.scan.exiftool.fields,
(
.key == "Model"
or (
.key == "Software"
and strings.starts_with(.value, "Android")
)
)
// exclude images taken with mobile cameras and screenshots from Apple
and (
.key == "DeviceManufacturer"
and .value == "Apple Computer Inc."
)
)
and any(ml.nlu_classifier(.scan.ocr.raw).intents,
.name == "callback_scam" and .confidence == "high"
)
)
)
)
or any(ml.nlu_classifier(body.current_thread.text).intents,
.name in ("callback_scam") and .confidence == "high"
)
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
(
sender.email.domain.root_domain in $high_trust_sender_root_domains
and not headers.auth_summary.dmarc.pass
)
or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
Detection Logic
Scope: inbound message.
A fraudulent invoice/receipt found in the body of the message, delivered via a Google Group mailing list.
- inbound message
- length(attachments) < 5
- sender.email.domain.domain is 'googlegroups.com'
any of:
any of
attachmentswhere all hold:any of:
- .file_type in $file_types_images
- .file_type is 'pdf'
- ( any(file.explode(.), // exclude images taken with mobile cameras and screenshots from android not any(.scan.exiftool.fields, ( .key == "Model" or ( .key == "Software" and strings.starts_with(.value, "Android") ) ) // exclude images taken with mobile cameras and screenshots from Apple and ( .key == "DeviceManufacturer" and .value == "Apple Computer Inc." ) ) and any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "callback_scam" and .confidence == "high" ) ) )
- any(ml.nlu_classifier(body.current_thread.text).intents, .name in ("callback_scam") and .confidence == "high" )
any of:
all of:
- sender.email.domain.root_domain in $high_trust_sender_root_domains
not:
- headers.auth_summary.dmarc.pass
- sender.email.domain.root_domain not in $high_trust_sender_root_domains
Inspects: attachments[].file_type, body.current_thread.text, headers.auth_summary.dmarc.pass, sender.email.domain.domain, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.nlu_classifier, strings.starts_with. Reference lists: $file_types_images, $high_trust_sender_root_domains.
Indicators Matched (6)
| Field | Match | Value |
|---|---|---|
sender.email.domain.domain | equals | googlegroups.com |
attachments[].file_type | equals | pdf |
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name | equals | callback_scam |
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence | equals | high |
ml.nlu_classifier(body.current_thread.text).intents[].name | member | callback_scam |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | equals | high |
Stages and Predicates
Stage 1: mql_rule
and
or
any(attachments)
and
or
attachments.file_type eq "pdf"
attachments.file_type macro "attachments[].file_type in file_types_images"
macro "(\n any(file.explode(.),\n // exclude images taken with mobile cameras and screenshots from android\n not any(.scan.exiftool.fields,\n (\n .key == \"Model\"\n or (\n .key == \"Software\"\n and strings.starts_with(.value, \"Android\")\n )\n )\n // exclude images taken with mobile cameras and screenshots from Apple\n and (\n .key == \"DeviceManufacturer\"\n and .value == \"Apple Computer Inc.\"\n )\n )\n and any(ml.nlu_classifier(.scan.ocr.raw).intents,\n .name == \"callback_scam\" and .confidence == \"high\"\n )\n )\n )"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name in (\"callback_scam\") and .confidence == \"high\"\n )"
or
and
not
headers.auth_summary.dmarc.pass eq "true"
sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
attachments length_compare "5"
sender.email.domain.domain eq "googlegroups.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
sender.email.domain.domain | eq |
| field:"sender.email.domain.domain" kind:eq value:"googlegroups.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via Google Meet
#Detects Google Meet invitations that include callback phishing content in the body, impersonating brands like McAfee, Norton, PayPal, or Best Buy with purchase-related language and phone numbers to solicit victim contact.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Out of band pivot |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 2
and all(attachments,
.content_type == "text/calendar" or .file_extension == "ics"
)
and strings.starts_with(subject.base, "Invitation:")
// Google Meet indicators
and (
any(body.links,
.display_text == "Join with Google Meet"
and .href_url.domain.domain == "meet.google.com"
)
)
and (
(
regex.icontains(body.current_thread.text,
(
"(?:mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock|apple)"
)
)
and 3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*')
)
// toll-free phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(., '\b\+?(\d{1}.)?\(?8\d{2}?\)?.\d{3}.?\d{4}\b')
)
)
)
Detection Logic
Scope: inbound message.
Detects Google Meet invitations that include callback phishing content in the body, impersonating brands like McAfee, Norton, PayPal, or Best Buy with purchase-related language and phone numbers to solicit victim contact.
- inbound message
- length(attachments) == 2
all of
attachmentswhere any holds:- .content_type is 'text/calendar'
- .file_extension is 'ics'
- subject.base starts with 'Invitation:'
any of
body.linkswhere all hold:- .display_text is 'Join with Google Meet'
- .href_url.domain.domain is 'meet.google.com'
all of:
- body.current_thread.text matches '(?:mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock|apple)'
at least 3 of 14: body.current_thread.text matches any of 14 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**help line**receipt**invoice**call**cancel**renew**refund*
- any([body.current_thread.text, subject.subject], regex.icontains(., '\b\+?(\d{1}.)?\(?8\d{2}?\)?.\d{3}.?\d{4}\b') )
Inspects: attachments[].content_type, attachments[].file_extension, body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.domain, subject.base, subject.subject, type.inbound. Sensors: regex.icontains, strings.ilike, strings.starts_with.
Indicators Matched (21)
| Field | Match | Value |
|---|---|---|
attachments[].content_type | equals | text/calendar |
attachments[].file_extension | equals | ics |
strings.starts_with | prefix | Invitation: |
body.links[].display_text | equals | Join with Google Meet |
body.links[].href_url.domain.domain | equals | meet.google.com |
regex.icontains | regex | (?:mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock|apple) |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
9 more
strings.ilike | substring | *support* |
strings.ilike | substring | *help line* |
strings.ilike | substring | *receipt* |
strings.ilike | substring | *invoice* |
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
regex.icontains | regex | \b\+?(\d{1}.)?\(?8\d{2}?\)?.\d{3}.?\d{4}\b |
Stages and Predicates
Stage 1: mql_rule
and
any(body.links)
and
body.links.display_text eq "Join with Google Meet"
body.links.href_url.domain.domain eq "meet.google.com"
attachments length_compare "2"
body.current_thread.text regex_match "(?:mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock|apple)"
subject.base starts_with "Invitation:"
type.inbound eq "true"
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*')\n )"
macro "all(attachments,\n .content_type == \"text/calendar\" or .file_extension == \"ics\"\n)"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(., '\\b\\+?(\\d{1}.)?\\(?8\\d{2}?\\)?.\\d{3}.?\\d{4}\\b')\n )"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match value:"(?:mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock|apple)" |
subject.base | starts_with |
| field:"subject.base" kind:starts_with value:"Invitation:" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via Intuit service abuse
#Callback phishing campaigns have been observed abusing Intuit Quickbooks services to send fraudulent invoices with callback phishing contents.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Evasion, Free email provider, Impersonation: Brand, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
// Legitimate Intuit sending infratructure
and (
sender.email.domain.root_domain in ('intuit.com', 'intuit.co.uk')
// check for SPF or DMARC passed
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
)
and (
// Callback Phishing in body (brand names required)
(
length(attachments) == 0
// brand names are required.
and regex.icontains(strings.replace_confusables(body.current_thread.text),
(
"mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock"
)
)
and 3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*')
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(., '\b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b')
)
)
// Callback Phishing in the "billtoContent"
or
// icontains a phone number
(
regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}.*\n'
)
or regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\+\d{1,3}[ilo0-9]{10}.*\n'
)
// +12028001238
or regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\n'
)
// 202-800-1238
or regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\n'
)
// (202) 800-1238
or regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*\n'
)
// (202)-800-1238
or regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\n'
)
// 202 800 1238
or regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+1\s?[ilo0-9]{3} [ilo0-9]{3} [ilo0-9]{4}.*\n'
) // 8123456789
or (
regex.icontains(strings.replace_confusables(body.html.inner_text),
'(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+8\d{9}.*\n'
)
and regex.icontains(strings.replace_confusables(body.html.inner_text),
'\+1'
)
)
)
// all attachments are PDFs with callback phishing indicators Brands Required
or (
length(attachments) < 3
and all(attachments, .file_extension == "pdf")
// the attachment is a pdf with 1 page, and at least 60 ocr chars
and any(attachments,
(
.file_extension == "pdf"
and any(file.explode(.), .scan.exiftool.page_count < 3)
and any(file.explode(.), length(.scan.ocr.raw) > 60)
// 4 of the following strings are found
and (
any(file.explode(.),
4 of (
strings.icontains(.scan.ocr.raw, "purchase"),
strings.icontains(.scan.ocr.raw, "payment"),
strings.icontains(.scan.ocr.raw, "transaction"),
strings.icontains(.scan.ocr.raw, "subscription"),
strings.icontains(.scan.ocr.raw, "antivirus"),
strings.icontains(.scan.ocr.raw, "order"),
strings.icontains(.scan.ocr.raw, "support"),
strings.icontains(.scan.ocr.raw, "help line"),
strings.icontains(.scan.ocr.raw, "receipt"),
strings.icontains(.scan.ocr.raw, "invoice"),
strings.icontains(.scan.ocr.raw, "call"),
strings.icontains(.scan.ocr.raw, "helpdesk"),
strings.icontains(.scan.ocr.raw, "cancel"),
strings.icontains(.scan.ocr.raw, "renew"),
strings.icontains(.scan.ocr.raw, "refund"),
strings.icontains(.scan.ocr.raw, "amount"),
strings.icontains(.scan.ocr.raw, "crypto"),
strings.icontains(.scan.ocr.raw, "wallet address"),
regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
regex.icontains(.scan.ocr.raw,
'(\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4})'
),
regex.icontains(.scan.ocr.raw,
'\+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4}'
)
)
// 1 of the following strings is found, representing common Callback brands
and (
1 of (
strings.icontains(.scan.ocr.raw, "geek squad"),
strings.icontains(.scan.ocr.raw, "lifelock"),
strings.icontains(.scan.ocr.raw, "best buy"),
strings.icontains(.scan.ocr.raw, "mcafee"),
strings.icontains(.scan.ocr.raw, "norton"),
strings.icontains(.scan.ocr.raw, "ebay"),
strings.icontains(.scan.ocr.raw, "paypal"),
)
// add additional logic for common language for paypal, which is a valid payment method
and not regex.icontains(.scan.ocr.raw,
"paypal[^\n]+accepted"
)
and not regex.icontains(.scan.ocr.raw,
"pay(ment)?.{0,30}(via|by) paypal"
)
and not regex.icontains(.scan.ocr.raw,
'\d{2,4} norton'
) // an address, example: 1234 Norton Road
and not regex.icontains(.scan.ocr.raw,
'sold on.{0,20}ebay'
) // "cannot be sold on Amazon and EBay", from a legit vendor
)
)
or any(ml.logo_detect(.).brands,
.name in ("PayPal", "Norton", "GeekSquad", "Ebay")
)
)
)
)
)
)
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
and (
not beta.profile.by_reply_to().any_messages_benign
or length(headers.reply_to) == 0
)
Detection Logic
Scope: inbound message.
Callback phishing campaigns have been observed abusing Intuit Quickbooks services to send fraudulent invoices with callback phishing contents.
- inbound message
all of:
- sender.email.domain.root_domain in ('intuit.com', 'intuit.co.uk')
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of:
all of:
- length(attachments) == 0
- regex.icontains(strings.replace_confusables(body.current_thread.text), ( "mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock" ) )
at least 3 of 14: body.current_thread.text matches any of 14 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**help line**receipt**invoice**call**cancel**renew**refund*
- any([body.current_thread.text, subject.subject], regex.icontains(., '\b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b') )
any of:
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\+\d{1,3}[ilo0-9]{10}.*\n' )
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+1\s?[ilo0-9]{3} [ilo0-9]{3} [ilo0-9]{4}.*\n' )
all of:
- regex.icontains(strings.replace_confusables(body.html.inner_text), '(?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+8\d{9}.*\n' )
- regex.icontains(strings.replace_confusables(body.html.inner_text), '\+1' )
all of:
- length(attachments) < 3
all of
attachmentswhere:- .file_extension is 'pdf'
any of
attachmentswhere all hold:- .file_extension is 'pdf'
- any(file.explode(.), .scan.exiftool.page_count < 3)
- any(file.explode(.), length(.scan.ocr.raw) > 60)
any of:
- any(file.explode(.), 4 of ( strings.icontains(.scan.ocr.raw, "purchase"), strings.icontains(.scan.ocr.raw, "payment"), strings.icontains(.scan.ocr.raw, "transaction"), strings.icontains(.scan.ocr.raw, "subscription"), strings.icontains(.scan.ocr.raw, "antivirus"), strings.icontains(.scan.ocr.raw, "order"), strings.icontains(.scan.ocr.raw, "support"), strings.icontains(.scan.ocr.raw, "help line"), strings.icontains(.scan.ocr.raw, "receipt"), strings.icontains(.scan.ocr.raw, "invoice"), strings.icontains(.scan.ocr.raw, "call"), strings.icontains(.scan.ocr.raw, "helpdesk"), strings.icontains(.scan.ocr.raw, "cancel"), strings.icontains(.scan.ocr.raw, "renew"), strings.icontains(.scan.ocr.raw, "refund"), strings.icontains(.scan.ocr.raw, "amount"), strings.icontains(.scan.ocr.raw, "crypto"), strings.icontains(.scan.ocr.raw, "wallet address"), regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'), regex.icontains(.scan.ocr.raw, '(\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4})' ), regex.icontains(.scan.ocr.raw, '\+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4}' ) ) // 1 of the following strings is found, representing common Callback brands and ( 1 of ( strings.icontains(.scan.ocr.raw, "geek squad"), strings.icontains(.scan.ocr.raw, "lifelock"), strings.icontains(.scan.ocr.raw, "best buy"), strings.icontains(.scan.ocr.raw, "mcafee"), strings.icontains(.scan.ocr.raw, "norton"), strings.icontains(.scan.ocr.raw, "ebay"), strings.icontains(.scan.ocr.raw, "paypal"), ) // add additional logic for common language for paypal, which is a valid payment method and not regex.icontains(.scan.ocr.raw, "paypal[^\n]+accepted" ) and not regex.icontains(.scan.ocr.raw, "pay(ment)?.{0,30}(via|by) paypal" ) and not regex.icontains(.scan.ocr.raw, '\d{2,4} norton' ) // an address, example: 1234 Norton Road and not regex.icontains(.scan.ocr.raw, 'sold on.{0,20}ebay' ) // "cannot be sold on Amazon and EBay", from a legit vendor ) )
- any(ml.logo_detect(.).brands, .name in ("PayPal", "Norton", "GeekSquad", "Ebay") )
any of:
not:
- beta.profile.by_reply_to().any_messages_benign
- length(headers.reply_to) == 0
Inspects: attachments[].file_extension, body.current_thread.text, body.html.inner_text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, headers.reply_to, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: beta.profile.by_reply_to, file.explode, ml.logo_detect, regex.icontains, strings.icontains, strings.ilike, strings.replace_confusables.
Indicators Matched (60)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | member | intuit.com |
sender.email.domain.root_domain | member | intuit.co.uk |
regex.icontains | regex | mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
strings.ilike | substring | *help line* |
strings.ilike | substring | *receipt* |
48 more
strings.ilike | substring | *invoice* |
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
regex.icontains | regex | \b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}.*\n |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\+\d{1,3}[ilo0-9]{10}.*\n |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\n |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\n |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*\n |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\n |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+1\s?[ilo0-9]{3} [ilo0-9]{3} [ilo0-9]{4}.*\n |
regex.icontains | regex | (?:Sold|Bill)[\s\xa0]To(?:\:\s+|\n)[^\n]+8\d{9}.*\n |
regex.icontains | regex | \+1 |
attachments[].file_extension | equals | pdf |
strings.icontains | substring | purchase |
strings.icontains | substring | payment |
strings.icontains | substring | transaction |
strings.icontains | substring | subscription |
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | help line |
strings.icontains | substring | receipt |
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | helpdesk |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
strings.icontains | substring | amount |
strings.icontains | substring | crypto |
strings.icontains | substring | wallet address |
regex.icontains | regex | \$\d{3}\.\d{2}\b |
regex.icontains | regex | (\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4}) |
regex.icontains | regex | \+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4} |
strings.icontains | substring | geek squad |
strings.icontains | substring | lifelock |
strings.icontains | substring | best buy |
strings.icontains | substring | mcafee |
strings.icontains | substring | norton |
strings.icontains | substring | ebay |
strings.icontains | substring | paypal |
ml.logo_detect(attachments[]).brands[].name | member | PayPal |
ml.logo_detect(attachments[]).brands[].name | member | Norton |
ml.logo_detect(attachments[]).brands[].name | member | GeekSquad |
ml.logo_detect(attachments[]).brands[].name | member | Ebay |
Stages and Predicates
Stage 1: mql_rule
and
or
and
any(attachments)
and
or
macro "any(file.explode(.),\n 4 of (\n strings.icontains(.scan.ocr.raw, \"purchase\"),\n strings.icontains(.scan.ocr.raw, \"payment\"),\n strings.icontains(.scan.ocr.raw, \"transaction\"),\n strings.icontains(.scan.ocr.raw, \"subscription\"),\n strings.icontains(.scan.ocr.raw, \"antivirus\"),\n strings.icontains(.scan.ocr.raw, \"order\"),\n strings.icontains(.scan.ocr.raw, \"support\"),\n strings.icontains(.scan.ocr.raw, \"help line\"),\n strings.icontains(.scan.ocr.raw, \"receipt\"),\n strings.icontains(.scan.ocr.raw, \"invoice\"),\n strings.icontains(.scan.ocr.raw, \"call\"),\n strings.icontains(.scan.ocr.raw, \"helpdesk\"),\n strings.icontains(.scan.ocr.raw, \"cancel\"),\n strings.icontains(.scan.ocr.raw, \"renew\"),\n strings.icontains(.scan.ocr.raw, \"refund\"),\n strings.icontains(.scan.ocr.raw, \"amount\"),\n strings.icontains(.scan.ocr.raw, \"crypto\"),\n strings.icontains(.scan.ocr.raw, \"wallet address\"),\n regex.icontains(.scan.ocr.raw, '\\$\\d{3}\\.\\d{2}\\b'),\n regex.icontains(.scan.ocr.raw,\n '(\\+\\d|1.(\\()?\\d{3}(\\))?\\D\\d{3}\\D\\d{4})'\n ),\n regex.icontains(.scan.ocr.raw,\n '\\+?(\\d{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}\\d{3}[\\s\\.\\-⋅]{0,5}\\d{4}'\n )\n )\n\n // 1 of the following strings is found, representing common Callback brands\n and (\n 1 of (\n strings.icontains(.scan.ocr.raw, \"geek squad\"),\n strings.icontains(.scan.ocr.raw, \"lifelock\"),\n strings.icontains(.scan.ocr.raw, \"best buy\"),\n strings.icontains(.scan.ocr.raw, \"mcafee\"),\n strings.icontains(.scan.ocr.raw, \"norton\"),\n strings.icontains(.scan.ocr.raw, \"ebay\"),\n strings.icontains(.scan.ocr.raw, \"paypal\"),\n )\n // add additional logic for common language for paypal, which is a valid payment method\n and not regex.icontains(.scan.ocr.raw,\n \"paypal[^\\n]+accepted\"\n )\n and not regex.icontains(.scan.ocr.raw,\n \"pay(ment)?.{0,30}(via|by) paypal\"\n )\n and not regex.icontains(.scan.ocr.raw,\n '\\d{2,4} norton'\n ) // an address, example: 1234 Norton Road\n and not regex.icontains(.scan.ocr.raw,\n 'sold on.{0,20}ebay'\n ) // \"cannot be sold on Amazon and EBay\", from a legit vendor\n )\n )"
macro "any(ml.logo_detect(.).brands,\n .name in (\"PayPal\", \"Norton\", \"GeekSquad\", \"Ebay\")\n )"
attachments.file_extension eq "pdf"
macro "any(file.explode(.), .scan.exiftool.page_count < 3)"
macro "any(file.explode(.), length(.scan.ocr.raw) > 60)"
attachments length_compare "3"
macro "all(attachments, .file_extension == \"pdf\")"
and
attachments length_compare "0"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n (\n \"mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock\"\n )\n )"
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*')\n )"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(., '\\b\\+?(\\d{1}.)?\\(?\\d{3}?\\)?.\\d{3}.?\\d{4}\\b')\n )"
and
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '\\+1'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+8\\d{9}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+1\\s?[ilo0-9]{3} [ilo0-9]{3} [ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+[ilo0-9]{3}\\.[ilo0-9]{3}\\.[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+\\([ilo0-9]{3}\\)-[ilo0-9]{3}-[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+\\([ilo0-9]{3}\\)[\\s-]+[ilo0-9]{3}[\\s-]+[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+\\+\\d{1,3}[ilo0-9]{10}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.html.inner_text),\n '(?:Sold|Bill)[\\s\\xa0]To(?:\\:\\s+|\\n)[^\\n]+\\+?(\\d{1}.)?\\(?\\d{3}?\\)?.\\d{3}.?\\d{4}.*\\n'\n )"
or
not
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().any_messages_benign"
headers.reply_to length_compare "0"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
sender.email.domain.root_domain in ["intuit.co.uk", "intuit.com"]
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
Callback phishing via Microsoft comment
#Detects callback scam messages originating from legitimate Microsoft infrastructure but containing fraudulent content designed to trick recipients into calling scammer phone numbers. The message includes typical callback phishing language around purchases, payments, subscriptions, or support services along with embedded phone numbers, while passing Microsoft's authentication checks.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
and length(body.current_thread.text) < 1750
// Legitimate MicrosoftOnline sending infrastructure
// or invites@microsoft.com abuse
and (
(
sender.email.domain.root_domain in ('microsoftonline.com')
or sender.email.email == "invites@microsoft.com"
)
// Callback Phishing
and (
any(ml.nlu_classifier(body.current_thread.text).intents,
.name in ("callback_scam", "cred_theft")
and .confidence in ("medium", "high")
)
or 3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*')
)
or regex.count(body.current_thread.text, '[^\x00-\x7F]') > 20
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(.,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}',
'\(?[ilo0-9]{3}\)?[^ilo0-9]{0,3}\(?[ilo0-9]{3}\)?.?[ilo0-9]{4}'
)
)
)
Detection Logic
Scope: inbound message.
Detects callback scam messages originating from legitimate Microsoft infrastructure but containing fraudulent content designed to trick recipients into calling scammer phone numbers. The message includes typical callback phishing language around purchases, payments, subscriptions, or support services along with embedded phone numbers, while passing Microsoft's authentication checks.
- inbound message
- length(attachments) == 0
- length(body.current_thread.text) < 1750
all of:
any of:
- sender.email.domain.root_domain in ('microsoftonline.com')
- sender.email.email is 'invites@microsoft.com'
any of:
- any(ml.nlu_classifier(body.current_thread.text).intents, .name in ("callback_scam", "cred_theft") and .confidence in ("medium", "high") )
at least 3 of 14: body.current_thread.text matches any of 14 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**help line**receipt**invoice**call**cancel**renew**refund*
- regex.count(body.current_thread.text, '[^\x00-\x7F]') > 20
- any([body.current_thread.text, subject.subject], regex.icontains(., '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}', '\(?[ilo0-9]{3}\)?[^ilo0-9]{0,3}\(?[ilo0-9]{3}\)?.?[ilo0-9]{4}' ) )
Inspects: body.current_thread.text, sender.email.domain.root_domain, sender.email.email, subject.subject, type.inbound. Sensors: ml.nlu_classifier, regex.count, regex.icontains, strings.ilike.
Indicators Matched (24)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | member | microsoftonline.com |
sender.email.email | equals | invites@microsoft.com |
ml.nlu_classifier(body.current_thread.text).intents[].name | member | callback_scam |
ml.nlu_classifier(body.current_thread.text).intents[].name | member | cred_theft |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | member | medium |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | member | high |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
12 more
strings.ilike | substring | *support* |
strings.ilike | substring | *help line* |
strings.ilike | substring | *receipt* |
strings.ilike | substring | *invoice* |
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
regex.count | regex | [^\x00-\x7F] |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
regex.icontains | regex | \(?[ilo0-9]{3}\)?[^ilo0-9]{0,3}\(?[ilo0-9]{3}\)?.?[ilo0-9]{4} |
Stages and Predicates
Stage 1: mql_rule
and
or
regex.count func_call "regex.count(body.current_thread.text, '[^\\x00-\\x7F]') > 20"
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*')\n )"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name in (\"callback_scam\", \"cred_theft\")\n and .confidence in (\"medium\", \"high\")\n )"
or
sender.email.domain.root_domain eq "microsoftonline.com"
sender.email.email eq "invites@microsoft.com"
attachments length_compare "0"
body.current_thread.text length_compare "1750"
type.inbound eq "true"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(.,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}',\n '\\(?[ilo0-9]{3}\\)?[^ilo0-9]{0,3}\\(?[ilo0-9]{3}\\)?.?[ilo0-9]{4}'\n )\n )"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
sender.email.domain.root_domain | in |
| field:"sender.email.domain.root_domain" kind:in value:"microsoftonline.com" |
sender.email.email | eq |
| field:"sender.email.email" kind:eq value:"invites@microsoft.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback Phishing via Signable E-Signature Request
#This rule inspects messages originating from legitimate Signable infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Exploit, Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
and (
not beta.profile.by_reply_to().solicited
or (
beta.profile.by_reply_to().any_messages_malicious_or_spam
and not beta.profile.by_reply_to().any_messages_benign
)
)
// Legitimate Signable sending infratructure
and sender.email.domain.root_domain == 'signable.app'
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
and (
// this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
regex.icontains(strings.replace_confusables(body.current_thread.text),
'(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
)
or any(ml.logo_detect(file.message_screenshot()).brands,
.name in (
"PayPal",
"Norton",
"GeekSquad",
"Ebay",
"McAfee",
"AT&T",
"Microsoft"
)
)
)
and length(body.current_thread.text) < 1750
and (
(
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
// caused by messages which mention cancelling or otherwise managing a subscription
// it is also synced and below for message_screenshot OCR output
3 of (
strings.icontains(body.current_thread.text, 'purchase'),
strings.icontains(body.current_thread.text, 'payment'),
strings.icontains(body.current_thread.text, 'transaction'),
strings.icontains(body.current_thread.text, 'subscription'),
strings.icontains(body.current_thread.text, 'antivirus'),
strings.icontains(body.current_thread.text, 'order'),
strings.icontains(body.current_thread.text, 'support'),
strings.icontains(body.current_thread.text, 'help line'),
strings.icontains(body.current_thread.text, 'receipt'),
strings.icontains(body.current_thread.text, 'invoice'),
strings.icontains(body.current_thread.text, 'call'),
strings.icontains(body.current_thread.text, 'cancel'),
strings.icontains(body.current_thread.text, 'renew'),
strings.icontains(body.current_thread.text, 'refund'),
regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
strings.icontains(body.current_thread.text, "+1"),
strings.icontains(body.current_thread.text, "amount"),
strings.icontains(body.current_thread.text, "charged"),
strings.icontains(body.current_thread.text, "crypto"),
strings.icontains(body.current_thread.text, "wallet address"),
regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
)
// phone number regex
and regex.icontains(body.current_thread.text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
or (
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// and above for current_thread.text
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
3 of (
strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'subscription'
),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
regex.icontains(beta.ocr(file.message_screenshot()).text,
"(?:reach|contact) us at"
),
strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'wallet address'
),
regex.icontains(beta.ocr(file.message_screenshot()).text,
'\$\d{3}\.\d{2}\b'
),
)
// phone number regex
and regex.icontains(beta.ocr(file.message_screenshot()).text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
// negate messages with previous threads. While callback phishing with thread hijacking or with current_thread
// padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
and not regex.icount(beta.ocr(file.message_screenshot()).text,
'(?:from|to|sent|date|cc|subject):'
) > 3
// this notation of previous threads often only occurs once
and not regex.icontains(beta.ocr(file.message_screenshot()).text,
'wrote:[\r\n]'
)
)
)
Detection Logic
Scope: inbound message.
This rule inspects messages originating from legitimate Signable infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
- inbound message
- length(attachments) == 0
any of:
not:
- beta.profile.by_reply_to().solicited
all of:
- beta.profile.by_reply_to().any_messages_malicious_or_spam
not:
- beta.profile.by_reply_to().any_messages_benign
- sender.email.domain.root_domain is 'signable.app'
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)' )
- any(ml.logo_detect(file.message_screenshot()).brands, .name in ( "PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T", "Microsoft" ) )
- length(body.current_thread.text) < 1750
any of:
all of:
at least 3 of:
- body.current_thread.text contains 'purchase'
- body.current_thread.text contains 'payment'
- body.current_thread.text contains 'transaction'
- body.current_thread.text contains 'subscription'
- body.current_thread.text contains 'antivirus'
- body.current_thread.text contains 'order'
- body.current_thread.text contains 'support'
- body.current_thread.text contains 'help line'
- body.current_thread.text contains 'receipt'
- body.current_thread.text contains 'invoice'
- body.current_thread.text contains 'call'
- body.current_thread.text contains 'cancel'
- body.current_thread.text contains 'renew'
- body.current_thread.text contains 'refund'
- body.current_thread.text matches '(?:reach|contact) us at'
- body.current_thread.text contains '+1'
- body.current_thread.text contains 'amount'
- body.current_thread.text contains 'charged'
- body.current_thread.text contains 'crypto'
- body.current_thread.text contains 'wallet address'
- body.current_thread.text matches '\\$\\d{3}\\.\\d{2}\\b'
body.current_thread.text matches any of 2 patterns
\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
all of:
at least 3 of:
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'subscription' )
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'order')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'support')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'call')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund')
- regex.icontains(beta.ocr(file.message_screenshot()).text, "(?:reach|contact) us at" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, '+1')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'wallet address' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\$\d{3}\.\d{2}\b' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' )
not:
- regex.icount(beta.ocr(file.message_screenshot()).text, '(?:from|to|sent|date|cc|subject):' ) > 3
not:
- regex.icontains(beta.ocr(file.message_screenshot()).text, 'wrote:[\r\n]' )
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.ocr, beta.profile.by_reply_to, file.message_screenshot, ml.logo_detect, regex.icontains, regex.icount, strings.icontains, strings.replace_confusables.
Indicators Matched (33)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | signable.app |
regex.icontains | regex | (p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t) |
ml.logo_detect(file.message_screenshot()).brands[].name | member | PayPal |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Norton |
ml.logo_detect(file.message_screenshot()).brands[].name | member | GeekSquad |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Ebay |
ml.logo_detect(file.message_screenshot()).brands[].name | member | McAfee |
ml.logo_detect(file.message_screenshot()).brands[].name | member | AT&T |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Microsoft |
strings.icontains | substring | purchase |
strings.icontains | substring | payment |
strings.icontains | substring | transaction |
21 more
strings.icontains | substring | subscription |
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | help line |
strings.icontains | substring | receipt |
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
regex.icontains | regex | (?:reach|contact) us at |
strings.icontains | substring | +1 |
strings.icontains | substring | amount |
strings.icontains | substring | charged |
strings.icontains | substring | crypto |
strings.icontains | substring | wallet address |
regex.icontains | regex | \$\d{3}\.\d{2}\b |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
strings.icontains | substring | helpdesk |
Stages and Predicates
Stage 1: mql_rule
and
or
and
not
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().any_messages_benign"
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().any_messages_malicious_or_spam"
not
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().solicited"
or
and
or
body.current_thread.text regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
body.current_thread.text regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
macro "3 of (\n strings.icontains(body.current_thread.text, 'purchase'),\n strings.icontains(body.current_thread.text, 'payment'),\n strings.icontains(body.current_thread.text, 'transaction'),\n strings.icontains(body.current_thread.text, 'subscription'),\n strings.icontains(body.current_thread.text, 'antivirus'),\n strings.icontains(body.current_thread.text, 'order'),\n strings.icontains(body.current_thread.text, 'support'),\n strings.icontains(body.current_thread.text, 'help line'),\n strings.icontains(body.current_thread.text, 'receipt'),\n strings.icontains(body.current_thread.text, 'invoice'),\n strings.icontains(body.current_thread.text, 'call'),\n strings.icontains(body.current_thread.text, 'cancel'),\n strings.icontains(body.current_thread.text, 'renew'),\n strings.icontains(body.current_thread.text, 'refund'),\n regex.icontains(body.current_thread.text, \"(?:reach|contact) us at\"),\n strings.icontains(body.current_thread.text, \"+1\"),\n strings.icontains(body.current_thread.text, \"amount\"),\n strings.icontains(body.current_thread.text, \"charged\"),\n strings.icontains(body.current_thread.text, \"crypto\"),\n strings.icontains(body.current_thread.text, \"wallet address\"),\n regex.icontains(body.current_thread.text, '\\$\\d{3}\\.\\d{2}\\b'),\n )"
and
not
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n 'wrote:[\\r\\n]'\n )"
not
regex.icount func_call "regex.icount(beta.ocr(file.message_screenshot()).text,\n '(?:from|to|sent|date|cc|subject):'\n ) > 3"
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )"
macro "3 of (\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'subscription'\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n \"(?:reach|contact) us at\"\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'wallet address'\n ),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\$\\d{3}\\.\\d{2}\\b'\n ),\n )"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
or
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'\n )"
macro "any(ml.logo_detect(file.message_screenshot()).brands,\n .name in (\n \"PayPal\",\n \"Norton\",\n \"GeekSquad\",\n \"Ebay\",\n \"McAfee\",\n \"AT&T\",\n \"Microsoft\"\n )\n )"
attachments length_compare "0"
body.current_thread.text length_compare "1750"
sender.email.domain.root_domain eq "signable.app"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"signable.app" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via SignFree e-signature request
#This rule inspects messages originating from legitimate SignFree infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Exploit, Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
and (
not beta.profile.by_reply_to().solicited
or (
beta.profile.by_reply_to().any_messages_malicious_or_spam
and not beta.profile.by_reply_to().any_messages_benign
)
)
// Legitimate SignFree sending infratructure
and sender.email.domain.root_domain == 'signfree.io'
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
and (
// this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
regex.icontains(strings.replace_confusables(body.current_thread.text),
'(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
)
or any(ml.logo_detect(file.message_screenshot()).brands,
.name in (
"PayPal",
"Norton",
"GeekSquad",
"Ebay",
"McAfee",
"AT&T",
"Microsoft"
)
)
)
and (
(
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
// caused by messages which mention cancelling or otherwise managing a subscription
// it is also synced and below for message_screenshot OCR output
3 of (
strings.icontains(body.current_thread.text, 'purchase'),
strings.icontains(body.current_thread.text, 'payment'),
strings.icontains(body.current_thread.text, 'transaction'),
strings.icontains(body.current_thread.text, 'subscription'),
strings.icontains(body.current_thread.text, 'antivirus'),
strings.icontains(body.current_thread.text, 'order'),
strings.icontains(body.current_thread.text, 'support'),
strings.icontains(body.current_thread.text, 'help line'),
strings.icontains(body.current_thread.text, 'receipt'),
strings.icontains(body.current_thread.text, 'invoice'),
strings.icontains(body.current_thread.text, 'call'),
strings.icontains(body.current_thread.text, 'cancel'),
strings.icontains(body.current_thread.text, 'renew'),
strings.icontains(body.current_thread.text, 'refund'),
regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
strings.icontains(body.current_thread.text, "+1"),
strings.icontains(body.current_thread.text, "amount"),
strings.icontains(body.current_thread.text, "charged"),
strings.icontains(body.current_thread.text, "crypto"),
strings.icontains(body.current_thread.text, "wallet address"),
regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
)
// phone number regex
and regex.icontains(body.current_thread.text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
or (
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// and above for current_thread.text
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
3 of (
strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'subscription'
),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
regex.icontains(beta.ocr(file.message_screenshot()).text,
"(?:reach|contact) us at"
),
strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'wallet address'
),
regex.icontains(beta.ocr(file.message_screenshot()).text,
'\$\d{3}\.\d{2}\b'
),
)
// phone number regex
and regex.icontains(beta.ocr(file.message_screenshot()).text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
// negate messages with previous threads. While callback phishing with thread hijacking or with current_thread
// padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
and not regex.icount(beta.ocr(file.message_screenshot()).text,
'(?:from|to|sent|date|cc|subject):'
) > 3
// this notation of previous threads often only occurs once
and not regex.icontains(beta.ocr(file.message_screenshot()).text,
'wrote:[\r\n]'
)
)
)
Detection Logic
Scope: inbound message.
This rule inspects messages originating from legitimate SignFree infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
- inbound message
- length(attachments) == 0
any of:
not:
- beta.profile.by_reply_to().solicited
all of:
- beta.profile.by_reply_to().any_messages_malicious_or_spam
not:
- beta.profile.by_reply_to().any_messages_benign
- sender.email.domain.root_domain is 'signfree.io'
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)' )
- any(ml.logo_detect(file.message_screenshot()).brands, .name in ( "PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T", "Microsoft" ) )
any of:
all of:
at least 3 of:
- body.current_thread.text contains 'purchase'
- body.current_thread.text contains 'payment'
- body.current_thread.text contains 'transaction'
- body.current_thread.text contains 'subscription'
- body.current_thread.text contains 'antivirus'
- body.current_thread.text contains 'order'
- body.current_thread.text contains 'support'
- body.current_thread.text contains 'help line'
- body.current_thread.text contains 'receipt'
- body.current_thread.text contains 'invoice'
- body.current_thread.text contains 'call'
- body.current_thread.text contains 'cancel'
- body.current_thread.text contains 'renew'
- body.current_thread.text contains 'refund'
- body.current_thread.text matches '(?:reach|contact) us at'
- body.current_thread.text contains '+1'
- body.current_thread.text contains 'amount'
- body.current_thread.text contains 'charged'
- body.current_thread.text contains 'crypto'
- body.current_thread.text contains 'wallet address'
- body.current_thread.text matches '\\$\\d{3}\\.\\d{2}\\b'
body.current_thread.text matches any of 2 patterns
\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
all of:
at least 3 of:
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'subscription' )
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'order')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'support')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'call')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund')
- regex.icontains(beta.ocr(file.message_screenshot()).text, "(?:reach|contact) us at" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, '+1')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'wallet address' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\$\d{3}\.\d{2}\b' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' )
not:
- regex.icount(beta.ocr(file.message_screenshot()).text, '(?:from|to|sent|date|cc|subject):' ) > 3
not:
- regex.icontains(beta.ocr(file.message_screenshot()).text, 'wrote:[\r\n]' )
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.ocr, beta.profile.by_reply_to, file.message_screenshot, ml.logo_detect, regex.icontains, regex.icount, strings.icontains, strings.replace_confusables.
Indicators Matched (33)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | signfree.io |
regex.icontains | regex | (p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t) |
ml.logo_detect(file.message_screenshot()).brands[].name | member | PayPal |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Norton |
ml.logo_detect(file.message_screenshot()).brands[].name | member | GeekSquad |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Ebay |
ml.logo_detect(file.message_screenshot()).brands[].name | member | McAfee |
ml.logo_detect(file.message_screenshot()).brands[].name | member | AT&T |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Microsoft |
strings.icontains | substring | purchase |
strings.icontains | substring | payment |
strings.icontains | substring | transaction |
21 more
strings.icontains | substring | subscription |
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | help line |
strings.icontains | substring | receipt |
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
regex.icontains | regex | (?:reach|contact) us at |
strings.icontains | substring | +1 |
strings.icontains | substring | amount |
strings.icontains | substring | charged |
strings.icontains | substring | crypto |
strings.icontains | substring | wallet address |
regex.icontains | regex | \$\d{3}\.\d{2}\b |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
strings.icontains | substring | helpdesk |
Stages and Predicates
Stage 1: mql_rule
and
or
and
not
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().any_messages_benign"
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().any_messages_malicious_or_spam"
not
beta.profile.by_reply_to func_call "beta.profile.by_reply_to().solicited"
or
and
or
body.current_thread.text regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
body.current_thread.text regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
macro "3 of (\n strings.icontains(body.current_thread.text, 'purchase'),\n strings.icontains(body.current_thread.text, 'payment'),\n strings.icontains(body.current_thread.text, 'transaction'),\n strings.icontains(body.current_thread.text, 'subscription'),\n strings.icontains(body.current_thread.text, 'antivirus'),\n strings.icontains(body.current_thread.text, 'order'),\n strings.icontains(body.current_thread.text, 'support'),\n strings.icontains(body.current_thread.text, 'help line'),\n strings.icontains(body.current_thread.text, 'receipt'),\n strings.icontains(body.current_thread.text, 'invoice'),\n strings.icontains(body.current_thread.text, 'call'),\n strings.icontains(body.current_thread.text, 'cancel'),\n strings.icontains(body.current_thread.text, 'renew'),\n strings.icontains(body.current_thread.text, 'refund'),\n regex.icontains(body.current_thread.text, \"(?:reach|contact) us at\"),\n strings.icontains(body.current_thread.text, \"+1\"),\n strings.icontains(body.current_thread.text, \"amount\"),\n strings.icontains(body.current_thread.text, \"charged\"),\n strings.icontains(body.current_thread.text, \"crypto\"),\n strings.icontains(body.current_thread.text, \"wallet address\"),\n regex.icontains(body.current_thread.text, '\\$\\d{3}\\.\\d{2}\\b'),\n )"
and
not
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n 'wrote:[\\r\\n]'\n )"
not
regex.icount func_call "regex.icount(beta.ocr(file.message_screenshot()).text,\n '(?:from|to|sent|date|cc|subject):'\n ) > 3"
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )"
macro "3 of (\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'subscription'\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n \"(?:reach|contact) us at\"\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'wallet address'\n ),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\$\\d{3}\\.\\d{2}\\b'\n ),\n )"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
or
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'\n )"
macro "any(ml.logo_detect(file.message_screenshot()).brands,\n .name in (\n \"PayPal\",\n \"Norton\",\n \"GeekSquad\",\n \"Ebay\",\n \"McAfee\",\n \"AT&T\",\n \"Microsoft\"\n )\n )"
attachments length_compare "0"
sender.email.domain.root_domain eq "signfree.io"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"signfree.io" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via Xodo Sign comment
#This rule inspects messages originating from legitimate Xodo Sign infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Exploit, Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
and (
not profile.by_sender().solicited
or (
profile.by_sender().any_messages_malicious_or_spam
and not profile.by_sender().any_messages_benign
)
)
// Legitimate Xodo Sign/Eversign sending infratructure
and sender.email.domain.root_domain == 'eversign.com'
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
and (
// this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
regex.icontains(strings.replace_confusables(body.current_thread.text),
'(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
)
or any(ml.logo_detect(file.message_screenshot()).brands,
.name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T")
)
)
and length(body.current_thread.text) < 1750
and (
(
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
// caused by messages which mention cancelling or otherwise managing a subscription
// it is also synced and below for message_screenshot OCR output
3 of (
strings.icontains(body.current_thread.text, 'purchase'),
strings.icontains(body.current_thread.text, 'payment'),
strings.icontains(body.current_thread.text, 'transaction'),
strings.icontains(body.current_thread.text, 'subscription'),
strings.icontains(body.current_thread.text, 'antivirus'),
strings.icontains(body.current_thread.text, 'order'),
strings.icontains(body.current_thread.text, 'support'),
strings.icontains(body.current_thread.text, 'help line'),
strings.icontains(body.current_thread.text, 'receipt'),
strings.icontains(body.current_thread.text, 'invoice'),
strings.icontains(body.current_thread.text, 'call'),
strings.icontains(body.current_thread.text, 'cancel'),
strings.icontains(body.current_thread.text, 'renew'),
strings.icontains(body.current_thread.text, 'refund'),
regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
strings.icontains(body.current_thread.text, "+1"),
strings.icontains(body.current_thread.text, "amount"),
strings.icontains(body.current_thread.text, "charged"),
strings.icontains(body.current_thread.text, "crypto"),
strings.icontains(body.current_thread.text, "wallet address"),
regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
)
// phone number regex
and regex.icontains(body.current_thread.text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
or (
// this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
// and above for current_thread.text
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
3 of (
strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'subscription'
),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
regex.icontains(beta.ocr(file.message_screenshot()).text,
"(?:reach|contact) us at"
),
strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
strings.icontains(beta.ocr(file.message_screenshot()).text,
'wallet address'
),
regex.icontains(beta.ocr(file.message_screenshot()).text,
'\$\d{3}\.\d{2}\b'
),
)
// phone number regex
and regex.icontains(beta.ocr(file.message_screenshot()).text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
// negate messages with previous threads. While callback phishing with thread hijacking or with current_thread
// padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
and not regex.icount(beta.ocr(file.message_screenshot()).text,
'(?:from|to|sent|date|cc|subject):'
) > 3
// this notation of previous threads often only occurs once
and not regex.icontains(beta.ocr(file.message_screenshot()).text,
'wrote:[\r\n]'
)
)
)
Detection Logic
Scope: inbound message.
This rule inspects messages originating from legitimate Xodo Sign infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.
- inbound message
- length(attachments) == 0
any of:
not:
- profile.by_sender().solicited
all of:
- profile.by_sender().any_messages_malicious_or_spam
not:
- profile.by_sender().any_messages_benign
- sender.email.domain.root_domain is 'eversign.com'
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)' )
- any(ml.logo_detect(file.message_screenshot()).brands, .name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T") )
- length(body.current_thread.text) < 1750
any of:
all of:
at least 3 of:
- body.current_thread.text contains 'purchase'
- body.current_thread.text contains 'payment'
- body.current_thread.text contains 'transaction'
- body.current_thread.text contains 'subscription'
- body.current_thread.text contains 'antivirus'
- body.current_thread.text contains 'order'
- body.current_thread.text contains 'support'
- body.current_thread.text contains 'help line'
- body.current_thread.text contains 'receipt'
- body.current_thread.text contains 'invoice'
- body.current_thread.text contains 'call'
- body.current_thread.text contains 'cancel'
- body.current_thread.text contains 'renew'
- body.current_thread.text contains 'refund'
- body.current_thread.text matches '(?:reach|contact) us at'
- body.current_thread.text contains '+1'
- body.current_thread.text contains 'amount'
- body.current_thread.text contains 'charged'
- body.current_thread.text contains 'crypto'
- body.current_thread.text contains 'wallet address'
- body.current_thread.text matches '\\$\\d{3}\\.\\d{2}\\b'
body.current_thread.text matches any of 2 patterns
\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
all of:
at least 3 of:
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'subscription' )
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'order')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'support')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'call')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund')
- regex.icontains(beta.ocr(file.message_screenshot()).text, "(?:reach|contact) us at" )
- strings.icontains(beta.ocr(file.message_screenshot()).text, '+1')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto')
- strings.icontains(beta.ocr(file.message_screenshot()).text, 'wallet address' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\$\d{3}\.\d{2}\b' )
- regex.icontains(beta.ocr(file.message_screenshot()).text, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' )
not:
- regex.icount(beta.ocr(file.message_screenshot()).text, '(?:from|to|sent|date|cc|subject):' ) > 3
not:
- regex.icontains(beta.ocr(file.message_screenshot()).text, 'wrote:[\r\n]' )
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.ocr, file.message_screenshot, ml.logo_detect, profile.by_sender, regex.icontains, regex.icount, strings.icontains, strings.replace_confusables.
Indicators Matched (32)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | eversign.com |
regex.icontains | regex | (p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t) |
ml.logo_detect(file.message_screenshot()).brands[].name | member | PayPal |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Norton |
ml.logo_detect(file.message_screenshot()).brands[].name | member | GeekSquad |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Ebay |
ml.logo_detect(file.message_screenshot()).brands[].name | member | McAfee |
ml.logo_detect(file.message_screenshot()).brands[].name | member | AT&T |
strings.icontains | substring | purchase |
strings.icontains | substring | payment |
strings.icontains | substring | transaction |
strings.icontains | substring | subscription |
20 more
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | help line |
strings.icontains | substring | receipt |
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
regex.icontains | regex | (?:reach|contact) us at |
strings.icontains | substring | +1 |
strings.icontains | substring | amount |
strings.icontains | substring | charged |
strings.icontains | substring | crypto |
strings.icontains | substring | wallet address |
regex.icontains | regex | \$\d{3}\.\d{2}\b |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
strings.icontains | substring | helpdesk |
Stages and Predicates
Stage 1: mql_rule
and
or
and
or
body.current_thread.text regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
body.current_thread.text regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
macro "3 of (\n strings.icontains(body.current_thread.text, 'purchase'),\n strings.icontains(body.current_thread.text, 'payment'),\n strings.icontains(body.current_thread.text, 'transaction'),\n strings.icontains(body.current_thread.text, 'subscription'),\n strings.icontains(body.current_thread.text, 'antivirus'),\n strings.icontains(body.current_thread.text, 'order'),\n strings.icontains(body.current_thread.text, 'support'),\n strings.icontains(body.current_thread.text, 'help line'),\n strings.icontains(body.current_thread.text, 'receipt'),\n strings.icontains(body.current_thread.text, 'invoice'),\n strings.icontains(body.current_thread.text, 'call'),\n strings.icontains(body.current_thread.text, 'cancel'),\n strings.icontains(body.current_thread.text, 'renew'),\n strings.icontains(body.current_thread.text, 'refund'),\n regex.icontains(body.current_thread.text, \"(?:reach|contact) us at\"),\n strings.icontains(body.current_thread.text, \"+1\"),\n strings.icontains(body.current_thread.text, \"amount\"),\n strings.icontains(body.current_thread.text, \"charged\"),\n strings.icontains(body.current_thread.text, \"crypto\"),\n strings.icontains(body.current_thread.text, \"wallet address\"),\n regex.icontains(body.current_thread.text, '\\$\\d{3}\\.\\d{2}\\b'),\n )"
and
not
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n 'wrote:[\\r\\n]'\n )"
not
regex.icount func_call "regex.icount(beta.ocr(file.message_screenshot()).text,\n '(?:from|to|sent|date|cc|subject):'\n ) > 3"
regex.icontains func_call "regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )"
macro "3 of (\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'subscription'\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n \"(?:reach|contact) us at\"\n ),\n strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),\n strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),\n strings.icontains(beta.ocr(file.message_screenshot()).text,\n 'wallet address'\n ),\n regex.icontains(beta.ocr(file.message_screenshot()).text,\n '\\$\\d{3}\\.\\d{2}\\b'\n ),\n )"
or
and
not
profile.by_sender func_call "profile.by_sender().any_messages_benign"
profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
not
profile.by_sender func_call "profile.by_sender().solicited"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
or
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'\n )"
macro "any(ml.logo_detect(file.message_screenshot()).brands,\n .name in (\"PayPal\", \"Norton\", \"GeekSquad\", \"Ebay\", \"McAfee\", \"AT&T\")\n )"
attachments length_compare "0"
body.current_thread.text length_compare "1750"
sender.email.domain.root_domain eq "eversign.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"eversign.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via Yammer comment
#Detects callback scams sent through Yammer infrastructure containing suspicious payment-related keywords and phone numbers. The rule identifies messages with callback scam language patterns or multiple financial transaction terms combined with phone number patterns in the message body or subject line.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
// message from Yammer sending infratructure
and sender.email.domain.root_domain == 'yammer.com'
and length(body.current_thread.text) < 2000
// Callback Phishing
and (
any(ml.nlu_classifier(body.current_thread.text).intents,
.name in ("callback_scam") and .confidence in ("medium", "high")
)
or 3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*')
)
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(.,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
// negate benign threads
and not any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "benign" and .confidence == "high"
)
Detection Logic
Scope: inbound message.
Detects callback scams sent through Yammer infrastructure containing suspicious payment-related keywords and phone numbers. The rule identifies messages with callback scam language patterns or multiple financial transaction terms combined with phone number patterns in the message body or subject line.
- inbound message
- sender.email.domain.root_domain is 'yammer.com'
- length(body.current_thread.text) < 2000
any of:
- any(ml.nlu_classifier(body.current_thread.text).intents, .name in ("callback_scam") and .confidence in ("medium", "high") )
at least 3 of 14: body.current_thread.text matches any of 14 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**help line**receipt**invoice**call**cancel**renew**refund*
- any([body.current_thread.text, subject.subject], regex.icontains(., '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ) )
not:
- any(ml.nlu_classifier(body.current_thread.text).intents, .name == "benign" and .confidence == "high" )
Inspects: body.current_thread.text, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, strings.ilike.
Indicators Matched (20)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | yammer.com |
ml.nlu_classifier(body.current_thread.text).intents[].name | member | callback_scam |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | member | medium |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | member | high |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
strings.ilike | substring | *help line* |
8 more
strings.ilike | substring | *receipt* |
strings.ilike | substring | *invoice* |
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
Stages and Predicates
Stage 1: mql_rule
and
or
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*')\n )"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name in (\"callback_scam\") and .confidence in (\"medium\", \"high\")\n )"
not
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name == \"benign\" and .confidence == \"high\"\n)"
body.current_thread.text length_compare "2000"
sender.email.domain.root_domain eq "yammer.com"
type.inbound eq "true"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(.,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )\n)"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"yammer.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via Zelle Service Abuse
#Callback phishing campaigns have been observed abusing Zelle services to send fraudulent payment requests with callback phishing contents.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | BEC/Fraud, Callback Phishing |
| Tactics and techniques | Evasion, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
and sender.email.domain.root_domain in ("zellepay.com")
and (
// only seeing payment requests abused
strings.ilike(body.html.display_text, "* requested*")
// phone number in subject
// the subject contains the seller's "name", attacks have been seen with the entire callback text in the seller's name
or (
regex.icontains(strings.replace_confusables(subject.subject),
'.*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*'
)
or regex.icontains(strings.replace_confusables(subject.subject),
'.*\+[ilo0-9]{1,3}[ilo0-9]{10}.*'
)
// +12028001238
or regex.icontains(strings.replace_confusables(subject.subject),
'.*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*'
)
// 202-800-1238
or regex.icontains(strings.replace_confusables(subject.subject),
'.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*'
)
// (202) 800-1238
or regex.icontains(strings.replace_confusables(subject.subject),
'.*\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*'
)
// (202)-800-1238
or regex.icontains(strings.replace_confusables(subject.subject),
'.*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*'
)
or ( // 8123456789
regex.icontains(strings.replace_confusables(subject.subject),
'.*8[ilo0-9]{9}.*'
)
and regex.icontains(strings.replace_confusables(subject.subject),
'\+[1li]'
)
)
)
)
and (
(
// icontains a phone number within the memo section (wrapped in quotes)
(
regex.icontains(strings.replace_confusables(body.current_thread.text),
'\".*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\"'
)
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'\".*\+[ilo0-9]{1,3}[ilo0-9]{10}.*\"'
)
// +12028001238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'\".*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\"'
)
// 202-800-1238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'\".*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\"'
)
// (202) 800-1238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'\".*\([ilo0-9]{3}\)\s[ilo0-9]{3}-[ilo0-9]{4}.*\"'
)
// (202)-800-1238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'\".*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\"'
)
or ( // 8123456789
regex.icontains(strings.replace_confusables(body.current_thread.text),
'\".*8[ilo0-9]{9}.*\"'
)
and regex.icontains(strings.replace_confusables(body.current_thread.text
),
'\".*\+[1li].*\"'
)
)
)
and (
(
4 of (
strings.ilike(body.html.inner_text, '*"*you did not*"*'),
strings.ilike(body.html.inner_text, '*"*is not for*"*'),
strings.ilike(body.html.inner_text, '*"*done by you*"*'),
regex.icontains(body.html.inner_text, "\".*didn\'t ma[kd]e this.*\""),
strings.ilike(body.html.inner_text, '*"*Fruad Alert*"*'),
strings.ilike(body.html.inner_text, '*"*Fraud Alert*"*'),
strings.ilike(body.html.inner_text, '*"*fraudulent*"*'),
strings.ilike(body.html.inner_text, '*"*Zelle*"*'),
strings.ilike(body.html.inner_text, '*"*subscription*"*'),
strings.ilike(body.html.inner_text, '*"*antivirus*"*'),
strings.ilike(body.html.inner_text, '*"*order*"*'),
strings.ilike(body.html.inner_text, '*"*support*"*'),
strings.ilike(body.html.inner_text, '*"*sincerely apologize*"*'),
strings.ilike(body.html.inner_text, '*"*receipt*"*'),
strings.ilike(body.html.inner_text, '*"*invoice*"*'),
strings.ilike(body.html.inner_text, '*"*Purchase*"*'),
strings.ilike(body.html.inner_text, '*"*transaction*"*'),
strings.ilike(body.html.inner_text, '*"*Market*Value*"*'),
strings.ilike(body.html.inner_text, '*"*BTC*"*'),
strings.ilike(body.html.inner_text, '*"*call*"*'),
strings.ilike(body.html.inner_text, '*"*get in touch with our*"*'),
strings.ilike(body.html.inner_text, '*"*quickly inform*"*'),
strings.ilike(body.html.inner_text, '*"*quickly reach*"*'),
strings.ilike(body.html.inner_text,
'*"*detected unusual transactions*'
),
strings.ilike(body.html.inner_text,
'*"*without your authorization*"*'
),
strings.ilike(body.html.inner_text, '*"*cancel*"*'),
strings.ilike(body.html.inner_text, '*"*renew*"*'),
strings.ilike(body.html.inner_text, '*"*refund*"*'),
strings.ilike(body.html.inner_text, '*"*+1*"*'),
regex.icontains(body.html.inner_text, '\"help.{0,3}desk'),
strings.ilike(body.html.inner_text, '*"* your funds*"*'),
strings.ilike(body.html.inner_text, '*"* your checking*"*'),
strings.ilike(body.html.inner_text, '*"* your saving*"*'),
strings.ilike(body.html.inner_text, '*"*transfer*"*'),
strings.ilike(body.html.inner_text, '*"*secure your account*"*'),
strings.ilike(body.html.inner_text, '*"*recover your *"*'),
)
)
or regex.icontains(body.current_thread.text,
'note from.{0,50}(?:call|reach|contact|paypal)'
)
or any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "callback_scam"
)
or (
// Unicode confusables words obfuscated in note
regex.icontains(body.html.inner_text,
'\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹'
)
)
or strings.ilike(body.html.inner_text, '*"*kindly*"*')
)
)
)
Detection Logic
Scope: inbound message.
Callback phishing campaigns have been observed abusing Zelle services to send fraudulent payment requests with callback phishing contents.
- inbound message
- length(attachments) == 0
- sender.email.domain.root_domain in ('zellepay.com')
any of:
- body.html.display_text matches '* requested*'
any of:
- regex.icontains(strings.replace_confusables(subject.subject), '.*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*' )
- regex.icontains(strings.replace_confusables(subject.subject), '.*\+[ilo0-9]{1,3}[ilo0-9]{10}.*' )
- regex.icontains(strings.replace_confusables(subject.subject), '.*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*' )
- regex.icontains(strings.replace_confusables(subject.subject), '.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*' )
- regex.icontains(strings.replace_confusables(subject.subject), '.*\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*' )
- regex.icontains(strings.replace_confusables(subject.subject), '.*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*' )
all of:
- regex.icontains(strings.replace_confusables(subject.subject), '.*8[ilo0-9]{9}.*' )
- regex.icontains(strings.replace_confusables(subject.subject), '\+[1li]' )
all of:
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '\".*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\"' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '\".*\+[ilo0-9]{1,3}[ilo0-9]{10}.*\"' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '\".*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\"' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '\".*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\"' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '\".*\([ilo0-9]{3}\)\s[ilo0-9]{3}-[ilo0-9]{4}.*\"' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '\".*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\"' )
all of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '\".*8[ilo0-9]{9}.*\"' )
- regex.icontains(strings.replace_confusables(body.current_thread.text ), '\".*\+[1li].*\"' )
any of:
at least 4 of 36: body.html.inner_text matches any of 36 patterns
*"*you did not*"**"*is not for*"**"*done by you*"*\".*didn\'t ma[kd]e this.*\"*"*Fruad Alert*"**"*Fraud Alert*"**"*fraudulent*"**"*Zelle*"**"*subscription*"**"*antivirus*"**"*order*"**"*support*"**"*sincerely apologize*"**"*receipt*"**"*invoice*"**"*Purchase*"**"*transaction*"**"*Market*Value*"**"*BTC*"**"*call*"**"*get in touch with our*"**"*quickly inform*"**"*quickly reach*"**"*detected unusual transactions**"*without your authorization*"**"*cancel*"**"*renew*"**"*refund*"**"*+1*"*\"help.{0,3}desk*"* your funds*"**"* your checking*"**"* your saving*"**"*transfer*"**"*secure your account*"**"*recover your *"*
- body.current_thread.text matches 'note from.{0,50}(?:call|reach|contact|paypal)'
- any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" )
- body.html.inner_text matches '\\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹'
- body.html.inner_text matches '*"*kindly*"*'
Inspects: body.current_thread.text, body.html.display_text, body.html.inner_text, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, strings.ilike, strings.replace_confusables.
Indicators Matched (58)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | member | zellepay.com |
strings.ilike | substring | * requested* |
regex.icontains | regex | .*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.* |
regex.icontains | regex | .*\+[ilo0-9]{1,3}[ilo0-9]{10}.* |
regex.icontains | regex | .*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.* |
regex.icontains | regex | .*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.* |
regex.icontains | regex | .*\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.* |
regex.icontains | regex | .*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.* |
regex.icontains | regex | .*8[ilo0-9]{9}.* |
regex.icontains | regex | \+[1li] |
regex.icontains | regex | \".*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\" |
regex.icontains | regex | \".*\+[ilo0-9]{1,3}[ilo0-9]{10}.*\" |
46 more
regex.icontains | regex | \".*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\" |
regex.icontains | regex | \".*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\" |
regex.icontains | regex | \".*\([ilo0-9]{3}\)\s[ilo0-9]{3}-[ilo0-9]{4}.*\" |
regex.icontains | regex | \".*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\" |
regex.icontains | regex | \".*8[ilo0-9]{9}.*\" |
regex.icontains | regex | \".*\+[1li].*\" |
strings.ilike | substring | *"*you did not*"* |
strings.ilike | substring | *"*is not for*"* |
strings.ilike | substring | *"*done by you*"* |
regex.icontains | regex | \".*didn\'t ma[kd]e this.*\" |
strings.ilike | substring | *"*Fruad Alert*"* |
strings.ilike | substring | *"*Fraud Alert*"* |
strings.ilike | substring | *"*fraudulent*"* |
strings.ilike | substring | *"*Zelle*"* |
strings.ilike | substring | *"*subscription*"* |
strings.ilike | substring | *"*antivirus*"* |
strings.ilike | substring | *"*order*"* |
strings.ilike | substring | *"*support*"* |
strings.ilike | substring | *"*sincerely apologize*"* |
strings.ilike | substring | *"*receipt*"* |
strings.ilike | substring | *"*invoice*"* |
strings.ilike | substring | *"*Purchase*"* |
strings.ilike | substring | *"*transaction*"* |
strings.ilike | substring | *"*Market*Value*"* |
strings.ilike | substring | *"*BTC*"* |
strings.ilike | substring | *"*call*"* |
strings.ilike | substring | *"*get in touch with our*"* |
strings.ilike | substring | *"*quickly inform*"* |
strings.ilike | substring | *"*quickly reach*"* |
strings.ilike | substring | *"*detected unusual transactions* |
strings.ilike | substring | *"*without your authorization*"* |
strings.ilike | substring | *"*cancel*"* |
strings.ilike | substring | *"*renew*"* |
strings.ilike | substring | *"*refund*"* |
strings.ilike | substring | *"*+1*"* |
regex.icontains | regex | \"help.{0,3}desk |
strings.ilike | substring | *"* your funds*"* |
strings.ilike | substring | *"* your checking*"* |
strings.ilike | substring | *"* your saving*"* |
strings.ilike | substring | *"*transfer*"* |
strings.ilike | substring | *"*secure your account*"* |
strings.ilike | substring | *"*recover your *"* |
regex.icontains | regex | note from.{0,50}(?:call|reach|contact|paypal) |
ml.nlu_classifier(body.current_thread.text).intents[].name | equals | callback_scam |
regex.icontains | regex | \+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹 |
strings.ilike | substring | *"*kindly*"* |
Stages and Predicates
Stage 1: mql_rule
and
or
and
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '\\\".*8[ilo0-9]{9}.*\\\"'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text\n ),\n '\\\".*\\+[1li].*\\\"'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '\\\".*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\\\"'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '\\\".*[ilo0-9]{3}\\.[ilo0-9]{3}\\.[ilo0-9]{4}.*\\\"'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '\\\".*\\([ilo0-9]{3}\\)-[ilo0-9]{3}-[ilo0-9]{4}.*\\\"'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '\\\".*\\([ilo0-9]{3}\\)\\s[ilo0-9]{3}-[ilo0-9]{4}.*\\\"'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '\\\".*\\+[ilo0-9]{1,3}[ilo0-9]{10}.*\\\"'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '\\\".*\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\\\"'\n )"
or
and
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '\\+[1li]'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '.*8[ilo0-9]{9}.*'\n )"
body.html.display_text match " requested"
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '.*[ilo0-9]{3}\\.[ilo0-9]{3}\\.[ilo0-9]{4}.*'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '.*\\([ilo0-9]{3}\\)-[ilo0-9]{3}-[ilo0-9]{4}.*'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '.*\\([ilo0-9]{3}\\)[\\s-]+[ilo0-9]{3}[\\s-]+[ilo0-9]{4}.*'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '.*\\+[ilo0-9]{1,3}[ilo0-9]{10}.*'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(subject.subject),\n '.*\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*'\n )"
or
body.current_thread.text regex_match "note from.{0,50}(?:call|reach|contact|paypal)"
body.html.inner_text regex_match "\\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹"
body.html.inner_text wildcard "*\"*kindly*\"*"
macro "4 of (\n strings.ilike(body.html.inner_text, '*\"*you did not*\"*'),\n strings.ilike(body.html.inner_text, '*\"*is not for*\"*'),\n strings.ilike(body.html.inner_text, '*\"*done by you*\"*'),\n regex.icontains(body.html.inner_text, \"\\\".*didn\\'t ma[kd]e this.*\\\"\"),\n strings.ilike(body.html.inner_text, '*\"*Fruad Alert*\"*'),\n strings.ilike(body.html.inner_text, '*\"*Fraud Alert*\"*'),\n strings.ilike(body.html.inner_text, '*\"*fraudulent*\"*'),\n strings.ilike(body.html.inner_text, '*\"*Zelle*\"*'),\n strings.ilike(body.html.inner_text, '*\"*subscription*\"*'),\n strings.ilike(body.html.inner_text, '*\"*antivirus*\"*'),\n strings.ilike(body.html.inner_text, '*\"*order*\"*'),\n strings.ilike(body.html.inner_text, '*\"*support*\"*'),\n strings.ilike(body.html.inner_text, '*\"*sincerely apologize*\"*'),\n strings.ilike(body.html.inner_text, '*\"*receipt*\"*'),\n strings.ilike(body.html.inner_text, '*\"*invoice*\"*'),\n strings.ilike(body.html.inner_text, '*\"*Purchase*\"*'),\n strings.ilike(body.html.inner_text, '*\"*transaction*\"*'),\n strings.ilike(body.html.inner_text, '*\"*Market*Value*\"*'),\n strings.ilike(body.html.inner_text, '*\"*BTC*\"*'),\n strings.ilike(body.html.inner_text, '*\"*call*\"*'),\n strings.ilike(body.html.inner_text, '*\"*get in touch with our*\"*'),\n strings.ilike(body.html.inner_text, '*\"*quickly inform*\"*'),\n strings.ilike(body.html.inner_text, '*\"*quickly reach*\"*'),\n strings.ilike(body.html.inner_text,\n '*\"*detected unusual transactions*'\n ),\n strings.ilike(body.html.inner_text,\n '*\"*without your authorization*\"*'\n ),\n strings.ilike(body.html.inner_text, '*\"*cancel*\"*'),\n strings.ilike(body.html.inner_text, '*\"*renew*\"*'),\n strings.ilike(body.html.inner_text, '*\"*refund*\"*'),\n strings.ilike(body.html.inner_text, '*\"*+1*\"*'),\n regex.icontains(body.html.inner_text, '\\\"help.{0,3}desk'),\n strings.ilike(body.html.inner_text, '*\"* your funds*\"*'),\n strings.ilike(body.html.inner_text, '*\"* your checking*\"*'),\n strings.ilike(body.html.inner_text, '*\"* your saving*\"*'),\n strings.ilike(body.html.inner_text, '*\"*transfer*\"*'),\n strings.ilike(body.html.inner_text, '*\"*secure your account*\"*'),\n strings.ilike(body.html.inner_text, '*\"*recover your *\"*'),\n )"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name == \"callback_scam\"\n )"
attachments length_compare "0"
sender.email.domain.root_domain eq "zellepay.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match value:"note from.{0,50}(?:call|reach|contact|paypal)" |
body.html.display_text | wildcard |
| field:"body.html.display_text" kind:wildcard value:"* requested*" |
body.html.inner_text | regex_match |
| field:"body.html.inner_text" kind:regex_match |
body.html.inner_text | wildcard |
| field:"body.html.inner_text" kind:wildcard |
sender.email.domain.root_domain | in |
| field:"sender.email.domain.root_domain" kind:in value:"zellepay.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing via Zoho service abuse
#Callback phishing campaigns have been observed abusing Zoho Invoice services to send fraudulent invoices with callback phishing contents.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Evasion, Free email provider, Impersonation: Brand, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
// Legitimate Zoho sending infratructure
and (
sender.email.domain.root_domain in ('zohoinvoice.com')
// check for SPF or DMARC passed
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
)
and (
// Callback Phishing in body (brand names required)
(
length(attachments) == 0
// brand names are required.
and regex.icontains(body.current_thread.text,
(
"mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock"
)
)
and 3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*')
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(., '\b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b')
)
)
// all attachments are PDFs with callback phishing indicators Brands Required
or (
length(attachments) < 3
and all(attachments, .file_extension == "pdf")
// the attachment is a pdf with 1 page, and at least 60 ocr chars
and any(attachments,
(
.file_extension == "pdf"
and any(file.explode(.), .scan.exiftool.page_count < 3)
and any(file.explode(.), length(.scan.ocr.raw) > 60)
// 4 of the following strings are found
and (
any(file.explode(.),
4 of (
strings.icontains(.scan.ocr.raw, "purchase"),
strings.icontains(.scan.ocr.raw, "payment"),
strings.icontains(.scan.ocr.raw, "transaction"),
strings.icontains(.scan.ocr.raw, "subscription"),
strings.icontains(.scan.ocr.raw, "antivirus"),
strings.icontains(.scan.ocr.raw, "order"),
strings.icontains(.scan.ocr.raw, "support"),
strings.icontains(.scan.ocr.raw, "help line"),
strings.icontains(.scan.ocr.raw, "receipt"),
strings.icontains(.scan.ocr.raw, "invoice"),
strings.icontains(.scan.ocr.raw, "call"),
strings.icontains(.scan.ocr.raw, "helpdesk"),
strings.icontains(.scan.ocr.raw, "cancel"),
strings.icontains(.scan.ocr.raw, "renew"),
strings.icontains(.scan.ocr.raw, "refund"),
strings.icontains(.scan.ocr.raw, "amount"),
strings.icontains(.scan.ocr.raw, "crypto"),
strings.icontains(.scan.ocr.raw, "wallet address"),
regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
regex.icontains(.scan.ocr.raw,
'(\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4})'
),
regex.icontains(.scan.ocr.raw,
'\+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4}'
)
)
// 1 of the following strings is found, representing common Callback brands
and (
1 of (
strings.icontains(.scan.ocr.raw, "geek squad"),
strings.icontains(.scan.ocr.raw, "lifelock"),
strings.icontains(.scan.ocr.raw, "best buy"),
strings.icontains(.scan.ocr.raw, "mcafee"),
strings.icontains(.scan.ocr.raw, "norton"),
strings.icontains(.scan.ocr.raw, "ebay"),
strings.icontains(.scan.ocr.raw, "paypal"),
)
// add additional logic for common language for paypal, which is a valid payment method
and not regex.icontains(.scan.ocr.raw,
"paypal[^\n]+accepted"
)
and not regex.icontains(.scan.ocr.raw,
"payment.{0,30}(via|by) paypal"
)
and not regex.icontains(.scan.ocr.raw,
'\d{2,4} norton'
) // an address, example: 1234 Norton Road
)
)
or any(ml.logo_detect(.).brands,
.name in ("PayPal", "Norton", "GeekSquad", "Ebay")
)
)
)
)
)
)
Detection Logic
Scope: inbound message.
Callback phishing campaigns have been observed abusing Zoho Invoice services to send fraudulent invoices with callback phishing contents.
- inbound message
all of:
- sender.email.domain.root_domain in ('zohoinvoice.com')
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
any of:
all of:
- length(attachments) == 0
- body.current_thread.text matches 'mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock'
at least 3 of 14: body.current_thread.text matches any of 14 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**help line**receipt**invoice**call**cancel**renew**refund*
- any([body.current_thread.text, subject.subject], regex.icontains(., '\b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b') )
all of:
- length(attachments) < 3
all of
attachmentswhere:- .file_extension is 'pdf'
any of
attachmentswhere all hold:- .file_extension is 'pdf'
- any(file.explode(.), .scan.exiftool.page_count < 3)
- any(file.explode(.), length(.scan.ocr.raw) > 60)
any of:
- any(file.explode(.), 4 of ( strings.icontains(.scan.ocr.raw, "purchase"), strings.icontains(.scan.ocr.raw, "payment"), strings.icontains(.scan.ocr.raw, "transaction"), strings.icontains(.scan.ocr.raw, "subscription"), strings.icontains(.scan.ocr.raw, "antivirus"), strings.icontains(.scan.ocr.raw, "order"), strings.icontains(.scan.ocr.raw, "support"), strings.icontains(.scan.ocr.raw, "help line"), strings.icontains(.scan.ocr.raw, "receipt"), strings.icontains(.scan.ocr.raw, "invoice"), strings.icontains(.scan.ocr.raw, "call"), strings.icontains(.scan.ocr.raw, "helpdesk"), strings.icontains(.scan.ocr.raw, "cancel"), strings.icontains(.scan.ocr.raw, "renew"), strings.icontains(.scan.ocr.raw, "refund"), strings.icontains(.scan.ocr.raw, "amount"), strings.icontains(.scan.ocr.raw, "crypto"), strings.icontains(.scan.ocr.raw, "wallet address"), regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'), regex.icontains(.scan.ocr.raw, '(\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4})' ), regex.icontains(.scan.ocr.raw, '\+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4}' ) ) // 1 of the following strings is found, representing common Callback brands and ( 1 of ( strings.icontains(.scan.ocr.raw, "geek squad"), strings.icontains(.scan.ocr.raw, "lifelock"), strings.icontains(.scan.ocr.raw, "best buy"), strings.icontains(.scan.ocr.raw, "mcafee"), strings.icontains(.scan.ocr.raw, "norton"), strings.icontains(.scan.ocr.raw, "ebay"), strings.icontains(.scan.ocr.raw, "paypal"), ) // add additional logic for common language for paypal, which is a valid payment method and not regex.icontains(.scan.ocr.raw, "paypal[^\n]+accepted" ) and not regex.icontains(.scan.ocr.raw, "payment.{0,30}(via|by) paypal" ) and not regex.icontains(.scan.ocr.raw, '\d{2,4} norton' ) // an address, example: 1234 Norton Road ) )
- any(ml.logo_detect(.).brands, .name in ("PayPal", "Norton", "GeekSquad", "Ebay") )
Inspects: attachments[].file_extension, body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, ml.logo_detect, regex.icontains, strings.icontains, strings.ilike.
Indicators Matched (50)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | member | zohoinvoice.com |
regex.icontains | regex | mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
strings.ilike | substring | *help line* |
strings.ilike | substring | *receipt* |
strings.ilike | substring | *invoice* |
38 more
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
regex.icontains | regex | \b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b |
attachments[].file_extension | equals | pdf |
strings.icontains | substring | purchase |
strings.icontains | substring | payment |
strings.icontains | substring | transaction |
strings.icontains | substring | subscription |
strings.icontains | substring | antivirus |
strings.icontains | substring | order |
strings.icontains | substring | support |
strings.icontains | substring | help line |
strings.icontains | substring | receipt |
strings.icontains | substring | invoice |
strings.icontains | substring | call |
strings.icontains | substring | helpdesk |
strings.icontains | substring | cancel |
strings.icontains | substring | renew |
strings.icontains | substring | refund |
strings.icontains | substring | amount |
strings.icontains | substring | crypto |
strings.icontains | substring | wallet address |
regex.icontains | regex | \$\d{3}\.\d{2}\b |
regex.icontains | regex | (\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4}) |
regex.icontains | regex | \+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4} |
strings.icontains | substring | geek squad |
strings.icontains | substring | lifelock |
strings.icontains | substring | best buy |
strings.icontains | substring | mcafee |
strings.icontains | substring | norton |
strings.icontains | substring | ebay |
strings.icontains | substring | paypal |
ml.logo_detect(attachments[]).brands[].name | member | PayPal |
ml.logo_detect(attachments[]).brands[].name | member | Norton |
ml.logo_detect(attachments[]).brands[].name | member | GeekSquad |
ml.logo_detect(attachments[]).brands[].name | member | Ebay |
Stages and Predicates
Stage 1: mql_rule
and
or
and
any(attachments)
and
or
macro "any(file.explode(.),\n 4 of (\n strings.icontains(.scan.ocr.raw, \"purchase\"),\n strings.icontains(.scan.ocr.raw, \"payment\"),\n strings.icontains(.scan.ocr.raw, \"transaction\"),\n strings.icontains(.scan.ocr.raw, \"subscription\"),\n strings.icontains(.scan.ocr.raw, \"antivirus\"),\n strings.icontains(.scan.ocr.raw, \"order\"),\n strings.icontains(.scan.ocr.raw, \"support\"),\n strings.icontains(.scan.ocr.raw, \"help line\"),\n strings.icontains(.scan.ocr.raw, \"receipt\"),\n strings.icontains(.scan.ocr.raw, \"invoice\"),\n strings.icontains(.scan.ocr.raw, \"call\"),\n strings.icontains(.scan.ocr.raw, \"helpdesk\"),\n strings.icontains(.scan.ocr.raw, \"cancel\"),\n strings.icontains(.scan.ocr.raw, \"renew\"),\n strings.icontains(.scan.ocr.raw, \"refund\"),\n strings.icontains(.scan.ocr.raw, \"amount\"),\n strings.icontains(.scan.ocr.raw, \"crypto\"),\n strings.icontains(.scan.ocr.raw, \"wallet address\"),\n regex.icontains(.scan.ocr.raw, '\\$\\d{3}\\.\\d{2}\\b'),\n regex.icontains(.scan.ocr.raw,\n '(\\+\\d|1.(\\()?\\d{3}(\\))?\\D\\d{3}\\D\\d{4})'\n ),\n regex.icontains(.scan.ocr.raw,\n '\\+?(\\d{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}\\d{3}[\\s\\.\\-⋅]{0,5}\\d{4}'\n )\n )\n\n // 1 of the following strings is found, representing common Callback brands \n and (\n 1 of (\n strings.icontains(.scan.ocr.raw, \"geek squad\"),\n strings.icontains(.scan.ocr.raw, \"lifelock\"),\n strings.icontains(.scan.ocr.raw, \"best buy\"),\n strings.icontains(.scan.ocr.raw, \"mcafee\"),\n strings.icontains(.scan.ocr.raw, \"norton\"),\n strings.icontains(.scan.ocr.raw, \"ebay\"),\n strings.icontains(.scan.ocr.raw, \"paypal\"),\n )\n // add additional logic for common language for paypal, which is a valid payment method\n and not regex.icontains(.scan.ocr.raw,\n \"paypal[^\\n]+accepted\"\n )\n and not regex.icontains(.scan.ocr.raw,\n \"payment.{0,30}(via|by) paypal\"\n )\n and not regex.icontains(.scan.ocr.raw,\n '\\d{2,4} norton'\n ) // an address, example: 1234 Norton Road\n )\n )"
macro "any(ml.logo_detect(.).brands,\n .name in (\"PayPal\", \"Norton\", \"GeekSquad\", \"Ebay\")\n )"
attachments.file_extension eq "pdf"
macro "any(file.explode(.), .scan.exiftool.page_count < 3)"
macro "any(file.explode(.), length(.scan.ocr.raw) > 60)"
attachments length_compare "3"
macro "all(attachments, .file_extension == \"pdf\")"
and
attachments length_compare "0"
body.current_thread.text regex_match "mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock"
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*')\n )"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(., '\\b\\+?(\\d{1}.)?\\(?\\d{3}?\\)?.\\d{3}.?\\d{4}\\b')\n )"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
sender.email.domain.root_domain eq "zohoinvoice.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
sender.email.domain.root_domain | in |
| field:"sender.email.domain.root_domain" kind:in value:"zohoinvoice.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback Phishing via Zoom comment
#Detects callback scams sent through legitimate Zoom infrastructure that impersonate well-known brands like McAfee, Norton, or PayPal. These messages contain purchase or support-related language along with phone numbers, attempting to trick recipients into calling fraudulent support lines.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Out of band pivot, Social engineering, Impersonation: Brand |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and length(attachments) == 0
// Legitimate Zoom sending infratructure
and sender.email.domain.root_domain == 'zoom.us'
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
// Zoom Logo
and any(ml.logo_detect(file.message_screenshot()).brands, .name == "Zoom")
// Callback Phishing
and regex.icontains(body.current_thread.text,
(
"mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck"
)
)
and (
3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*payment*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*invoice*'),
strings.ilike(body.current_thread.text, '*call*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*'),
strings.ilike(body.current_thread.text, '*host key*')
)
or any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "callback_scam" and .confidence != "low"
)
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(.,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
)
// negation for legitimate AI generated meeting summaries from Zoom
and not (
(
sender.display_name == "Meeting Summary with AI Companion"
and sender.email.email == "no-reply@zoom.us"
and headers.auth_summary.dmarc.pass
)
or (
strings.icontains(subject.subject, "Meeting assets")
and strings.icontains(body.current_thread.text, "Meeting summary")
and sender.email.email == "no-reply@zoom.us"
and headers.auth_summary.dmarc.pass
)
)
Detection Logic
Scope: inbound message.
Detects callback scams sent through legitimate Zoom infrastructure that impersonate well-known brands like McAfee, Norton, or PayPal. These messages contain purchase or support-related language along with phone numbers, attempting to trick recipients into calling fraudulent support lines.
- inbound message
- length(attachments) == 0
- sender.email.domain.root_domain is 'zoom.us'
any of:
- headers.auth_summary.spf.pass
- headers.auth_summary.dmarc.pass
- any(ml.logo_detect(file.message_screenshot()).brands, .name == "Zoom")
- body.current_thread.text matches 'mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck'
any of:
at least 3 of 15: body.current_thread.text matches any of 15 patterns
*purchase**payment**transaction**subscription**antivirus**order**support**help line**receipt**invoice**call**cancel**renew**refund**host key*
- any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" and .confidence != "low" )
- any([body.current_thread.text, subject.subject], regex.icontains(., '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ) )
none of:
all of:
- sender.display_name is 'Meeting Summary with AI Companion'
- sender.email.email is 'no-reply@zoom.us'
- headers.auth_summary.dmarc.pass
all of:
- subject.subject contains 'Meeting assets'
- body.current_thread.text contains 'Meeting summary'
- sender.email.email is 'no-reply@zoom.us'
- headers.auth_summary.dmarc.pass
Inspects: body.current_thread.text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.display_name, sender.email.domain.root_domain, sender.email.email, subject.subject, type.inbound. Sensors: file.message_screenshot, ml.logo_detect, ml.nlu_classifier, regex.icontains, strings.icontains, strings.ilike.
Indicators Matched (21)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | zoom.us |
ml.logo_detect(file.message_screenshot()).brands[].name | equals | Zoom |
regex.icontains | regex | mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *payment* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
strings.ilike | substring | *help line* |
strings.ilike | substring | *receipt* |
9 more
strings.ilike | substring | *invoice* |
strings.ilike | substring | *call* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
strings.ilike | substring | *host key* |
ml.nlu_classifier(body.current_thread.text).intents[].name | equals | callback_scam |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
Stages and Predicates
Stage 1: mql_rule
and
not
or
and
body.current_thread.text contains "Meeting summary"
headers.auth_summary.dmarc.pass eq "true"
sender.email.email eq "no-reply@zoom.us"
subject.subject contains "Meeting assets"
and
headers.auth_summary.dmarc.pass eq "true"
sender.display_name eq "Meeting Summary with AI Companion"
sender.email.email eq "no-reply@zoom.us"
or
headers.auth_summary.dmarc.pass eq "true"
headers.auth_summary.spf.pass eq "true"
or
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*payment*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*invoice*'),\n strings.ilike(body.current_thread.text, '*call*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*'),\n strings.ilike(body.current_thread.text, '*host key*')\n )"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name == \"callback_scam\" and .confidence != \"low\"\n )"
attachments length_compare "0"
body.current_thread.text regex_match "mcafee|n[o0]rt[o0]n|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifel[o0]ck"
sender.email.domain.root_domain eq "zoom.us"
type.inbound eq "true"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(.,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n )\n)"
macro "any(ml.logo_detect(file.message_screenshot()).brands, .name == \"Zoom\")"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
headers.auth_summary.dmarc.pass | eq |
| field:"headers.auth_summary.dmarc.pass" kind:eq value:"true" |
headers.auth_summary.spf.pass | eq |
| field:"headers.auth_summary.spf.pass" kind:eq value:"true" |
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"zoom.us" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
body.current_thread.text | contains | Meeting summary | excludes:body.current_thread.text field:"body.current_thread.text" value:"Meeting summary" |
headers.auth_summary.dmarc.pass | eq | true | excludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true" |
sender.email.email | eq | no-reply@zoom.us | excludes:sender.email.email field:"sender.email.email" value:"no-reply@zoom.us" |
subject.subject | contains | Meeting assets | excludes:subject.subject field:"subject.subject" value:"Meeting assets" |
sender.display_name | eq | Meeting Summary with AI Companion | excludes:sender.display_name field:"sender.display_name" value:"Meeting Summary with AI Companion" |
Callback phishing: AOL senders with suspicious HTML template or PDF attachment
#Detects a specific behavioral pattern from AOL senders using consistent HTML templates and PDF attachment characteristics. The pattern includes particular Yahoo-style formatting with specific font families, and standardized PDF metadata when attachments are present.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Free email provider, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
// sender is aol
and sender.email.domain.root_domain == "aol.com"
// there is a single recipient
and length(recipients.to) == 1
and length(recipients.cc) == 0
and length(recipients.bcc) == 0
// is not a reply
and headers.in_reply_to is null
// this is another way to limit replies but need to account for
// a behavior where Yahoo/Aol seems to include it's own message ID as a reference
and length(headers.references) == 1
// all message-id values end in mail.yahoo.com, some benign messages use @aol.com
and strings.iends_with(headers.message_id, '@mail.yahoo.com>')
// All are using the legit Yahoo X-Mailer
// this removes AOL sent from iphones and other non AOL client
and strings.ends_with(headers.mailer, 'AolMailNorrin')
// exclude common recipients which interact with aol addresses that are commonly (but not always) benign
// recipeint exclusions are suggested for other recipients
and (
// no attachment
(
length(attachments) == 0
// if there are no attachments focus on the HTML template being observed
and (
// yahoo div followed by <br>
// // verdana, helvetica, sans-serif;
strings.icontains(body.html.raw,
"<div class=\"yahoo-style-wrap\" style=\"font-family:verdana, helvetica, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><br>\r\n"
)
// // Helvetica Neue, Helvetica, Arial, sans-serif;
or strings.icontains(body.html.raw,
"<div class=\"yahoo-style-wrap\" style=\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><br>\r\n"
)
// yahoo div followed by doctype
// // verdana, helvetica, sans-serif;
or strings.icontains(body.html.raw,
"<div class=\"yahoo-style-wrap\" style=\"font-family:verdana, helvetica, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><!DOCTYPE html>"
)
// // Helvetica Neue, Helvetica, Arial, sans-serif;
or strings.icontains(body.html.raw,
"<div class=\"yahoo-style-wrap\" style=\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><!DOCTYPE html>"
)
)
)
or (
// if there is an attachment, there can be only one
length(attachments) == 1
and all(attachments,
// it's a PDF,
.file_type == "pdf"
and (
// static content_id value for the attachments
(
.content_id == '<@yahoo.com>' or .content_id == '@yahoo.com'
)
// created by observed static PDF details
or (
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
beta.parse_exif(.).creator == "wkhtmltopdf 0.12.6"
and beta.parse_exif(.).title is null
and beta.parse_exif(.).producer == 'Qt 4.8.7'
)
)
)
)
)
Detection Logic
Scope: inbound message.
Detects a specific behavioral pattern from AOL senders using consistent HTML templates and PDF attachment characteristics. The pattern includes particular Yahoo-style formatting with specific font families, and standardized PDF metadata when attachments are present.
- inbound message
- sender.email.domain.root_domain is 'aol.com'
- length(recipients.to) == 1
- length(recipients.cc) == 0
- length(recipients.bcc) == 0
- headers.in_reply_to is missing
- length(headers.references) == 1
- headers.message_id ends with '@mail.yahoo.com>'
- headers.mailer ends with 'AolMailNorrin'
any of:
all of:
- length(attachments) == 0
body.html.raw contains any of 4 patterns
<div class=\"yahoo-style-wrap\" style=\"font-family:verdana, helvetica, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><br>\r\n<div class=\"yahoo-style-wrap\" style=\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><br>\r\n<div class=\"yahoo-style-wrap\" style=\"font-family:verdana, helvetica, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><!DOCTYPE html><div class=\"yahoo-style-wrap\" style=\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><!DOCTYPE html>
all of:
- length(attachments) == 1
all of
attachmentswhere all hold:- .file_type is 'pdf'
any of:
any of:
- .content_id is '<@yahoo.com>'
- .content_id is '@yahoo.com'
all of:
- beta.parse_exif(.).creator == "wkhtmltopdf 0.12.6"
- beta.parse_exif(.).title is null
- beta.parse_exif(.).producer == 'Qt 4.8.7'
Inspects: attachments[].content_id, attachments[].file_type, body.html.raw, headers.in_reply_to, headers.mailer, headers.message_id, headers.references, recipients.bcc, recipients.cc, recipients.to, sender.email.domain.root_domain, type.inbound. Sensors: beta.parse_exif, strings.ends_with, strings.icontains, strings.iends_with.
Indicators Matched (10)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | equals | aol.com |
strings.iends_with | suffix | @mail.yahoo.com> |
strings.ends_with | suffix | AolMailNorrin |
strings.icontains | substring | <div class=\"yahoo-style-wrap\" style=\"font-family:verdana, helvetica, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><br>\r\n |
strings.icontains | substring | <div class=\"yahoo-style-wrap\" style=\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><br>\r\n |
strings.icontains | substring | <div class=\"yahoo-style-wrap\" style=\"font-family:verdana, helvetica, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><!DOCTYPE html> |
strings.icontains | substring | <div class=\"yahoo-style-wrap\" style=\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\">\r\n<div dir=\"ltr\" data-setdir=\"false\"><!DOCTYPE html> |
attachments[].file_type | equals | pdf |
attachments[].content_id | equals | <@yahoo.com> |
attachments[].content_id | equals | @yahoo.com |
Stages and Predicates
Stage 1: mql_rule
and
or
and
or
body.html.raw contains "<div class=\\\"yahoo-style-wrap\\\" style=\\\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\\\">\\r\\n<div dir=\\\"ltr\\\" data-setdir=\\\"false\\\"><!DOCTYPE html>"
body.html.raw contains "<div class=\\\"yahoo-style-wrap\\\" style=\\\"font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:18px;\\\">\\r\\n<div dir=\\\"ltr\\\" data-setdir=\\\"false\\\"><br>\\r\\n"
body.html.raw contains "<div class=\\\"yahoo-style-wrap\\\" style=\\\"font-family:verdana, helvetica, sans-serif;font-size:18px;\\\">\\r\\n<div dir=\\\"ltr\\\" data-setdir=\\\"false\\\"><!DOCTYPE html>"
body.html.raw contains "<div class=\\\"yahoo-style-wrap\\\" style=\\\"font-family:verdana, helvetica, sans-serif;font-size:18px;\\\">\\r\\n<div dir=\\\"ltr\\\" data-setdir=\\\"false\\\"><br>\\r\\n"
attachments length_compare "0"
and
attachments length_compare "1"
macro "all(attachments,\n // it's a PDF, \n .file_type == \"pdf\"\n and (\n // static content_id value for the attachments\n (\n .content_id == '<@yahoo.com>' or .content_id == '@yahoo.com'\n )\n // created by observed static PDF details\n or (\n\n // \n // This rule makes use of a beta feature and is subject to change without notice\n // using the beta feature in custom rules is not suggested until it has been formally released\n // \n beta.parse_exif(.).creator == \"wkhtmltopdf 0.12.6\"\n and beta.parse_exif(.).title is null\n and beta.parse_exif(.).producer == 'Qt 4.8.7'\n )\n )\n )"
headers.in_reply_to is_null
headers.mailer ends_with "AolMailNorrin"
headers.message_id ends_with "@mail.yahoo.com>"
headers.references length_compare "1"
recipients.bcc length_compare "0"
recipients.cc length_compare "0"
recipients.to length_compare "1"
sender.email.domain.root_domain eq "aol.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.html.raw | contains |
| field:"body.html.raw" kind:contains |
headers.in_reply_to | is_null | field:"headers.in_reply_to" kind:is_null | |
headers.mailer | ends_with |
| field:"headers.mailer" kind:ends_with value:"AolMailNorrin" |
headers.message_id | ends_with |
| field:"headers.message_id" kind:ends_with value:"@mail.yahoo.com>" |
sender.email.domain.root_domain | eq |
| field:"sender.email.domain.root_domain" kind:eq value:"aol.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing: Branded invoice from sender/reply-to domain less than 30 days old
#This rule checks for invoicing content from a sender, reply-to domain or return-path domain less than 30d old. It also checks the body or the OCR'd screenshot for key words commonly abused in fraudulent invoicing attacks.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
// reply to domain that's less than 30d old and doesn't match the sender
and (
(
length(headers.reply_to) > 0
and all(headers.reply_to,
network.whois(.email.domain).days_old <= 30
and .email.email != sender.email.email
)
)
// or the return path or sender domain is less than 30d old
or network.whois(headers.return_path.domain).days_old <= 30
or network.whois(sender.email.domain).days_old <= 30
)
// invoicing with high confidence
and any(ml.nlu_classifier(body.current_thread.text).tags,
.name == "invoice" and .confidence == "high"
)
// commonly abused brands in body
and (
strings.ilike(body.current_thread.text,
"*mcafee*",
"*norton*",
"*geek squad*",
"*paypal*",
"*ebay*",
"*symantec*",
"*best buy*",
"*lifelock*",
"*virus*"
)
// commonly abused brand logo
or any(ml.logo_detect(file.message_screenshot()).brands,
.name in ("PayPal", "Norton", "GeekSquad", "Ebay")
)
// check message screenshot ocr for commonly abused brands
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
or 1 of (
strings.icontains(beta.ocr(file.message_screenshot()).text, "geek squad"),
strings.icontains(beta.ocr(file.message_screenshot()).text, "lifelock"),
strings.icontains(beta.ocr(file.message_screenshot()).text, "best buy"),
strings.icontains(beta.ocr(file.message_screenshot()).text, "mcafee"),
strings.icontains(beta.ocr(file.message_screenshot()).text, "norton"),
strings.icontains(beta.ocr(file.message_screenshot()).text, "ebay"),
strings.icontains(beta.ocr(file.message_screenshot()).text, "paypal"),
strings.icontains(beta.ocr(file.message_screenshot()).text, "virus"),
)
)
// phone number regex
and regex.icontains(body.current_thread.text,
'\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}'
)
and not profile.by_sender().solicited
and not profile.by_sender().any_messages_benign
Detection Logic
Scope: inbound message.
This rule checks for invoicing content from a sender, reply-to domain or return-path domain less than 30d old. It also checks the body or the OCR'd screenshot for key words commonly abused in fraudulent invoicing attacks.
- inbound message
any of:
all of:
- length(headers.reply_to) > 0
all of
headers.reply_towhere all hold:- network.whois(.email.domain).days_old <= 30
- .email.email is not sender.email.email
- network.whois(headers.return_path.domain).days_old <= 30
- network.whois(sender.email.domain).days_old <= 30
- any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice" and .confidence == "high" )
any of:
body.current_thread.text matches any of 9 patterns
*mcafee**norton**geek squad**paypal**ebay**symantec**best buy**lifelock**virus*
- any(ml.logo_detect(file.message_screenshot()).brands, .name in ("PayPal", "Norton", "GeekSquad", "Ebay") )
at least 1 of:
- strings.icontains(beta.ocr(file.message_screenshot()).text, "geek squad")
- strings.icontains(beta.ocr(file.message_screenshot()).text, "lifelock")
- strings.icontains(beta.ocr(file.message_screenshot()).text, "best buy")
- strings.icontains(beta.ocr(file.message_screenshot()).text, "mcafee")
- strings.icontains(beta.ocr(file.message_screenshot()).text, "norton")
- strings.icontains(beta.ocr(file.message_screenshot()).text, "ebay")
- strings.icontains(beta.ocr(file.message_screenshot()).text, "paypal")
- strings.icontains(beta.ocr(file.message_screenshot()).text, "virus")
- body.current_thread.text matches '\\+?(\\d{1}.)?\\(?\\d{3}?\\)?.\\d{3}.?\\d{4}'
not:
- profile.by_sender().solicited
not:
- profile.by_sender().any_messages_benign
Inspects: body.current_thread.text, headers.reply_to, headers.reply_to[].email.domain, headers.reply_to[].email.email, headers.return_path.domain, sender.email.domain, sender.email.email, type.inbound. Sensors: beta.ocr, file.message_screenshot, ml.logo_detect, ml.nlu_classifier, network.whois, profile.by_sender, regex.icontains, strings.icontains, strings.ilike.
Indicators Matched (24)
| Field | Match | Value |
|---|---|---|
ml.nlu_classifier(body.current_thread.text).tags[].name | equals | invoice |
ml.nlu_classifier(body.current_thread.text).tags[].confidence | equals | high |
strings.ilike | substring | *mcafee* |
strings.ilike | substring | *norton* |
strings.ilike | substring | *geek squad* |
strings.ilike | substring | *paypal* |
strings.ilike | substring | *ebay* |
strings.ilike | substring | *symantec* |
strings.ilike | substring | *best buy* |
strings.ilike | substring | *lifelock* |
strings.ilike | substring | *virus* |
ml.logo_detect(file.message_screenshot()).brands[].name | member | PayPal |
12 more
ml.logo_detect(file.message_screenshot()).brands[].name | member | Norton |
ml.logo_detect(file.message_screenshot()).brands[].name | member | GeekSquad |
ml.logo_detect(file.message_screenshot()).brands[].name | member | Ebay |
strings.icontains | substring | geek squad |
strings.icontains | substring | lifelock |
strings.icontains | substring | best buy |
strings.icontains | substring | mcafee |
strings.icontains | substring | norton |
strings.icontains | substring | ebay |
strings.icontains | substring | paypal |
strings.icontains | substring | virus |
regex.icontains | regex | \+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4} |
Stages and Predicates
Stage 1: mql_rule
and
or
and
headers.reply_to length_compare "0"
macro "all(headers.reply_to,\n network.whois(.email.domain).days_old <= 30\n and .email.email != sender.email.email\n )"
network.whois func_call "network.whois(headers.return_path.domain).days_old <= 30"
network.whois func_call "network.whois(sender.email.domain).days_old <= 30"
or
body.current_thread.text match "best buy"
body.current_thread.text match "ebay"
body.current_thread.text match "geek squad"
body.current_thread.text match "lifelock"
body.current_thread.text match "mcafee"
body.current_thread.text match "norton"
body.current_thread.text match "paypal"
body.current_thread.text match "symantec"
body.current_thread.text match "virus"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"best buy\")"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"ebay\")"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"geek squad\")"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"lifelock\")"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"mcafee\")"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"norton\")"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"paypal\")"
strings.icontains func_call "strings.icontains(beta.ocr(file.message_screenshot()).text, \"virus\")"
macro "any(ml.logo_detect(file.message_screenshot()).brands,\n .name in (\"PayPal\", \"Norton\", \"GeekSquad\", \"Ebay\")\n )"
not
profile.by_sender func_call "profile.by_sender().any_messages_benign"
not
profile.by_sender func_call "profile.by_sender().solicited"
body.current_thread.text regex_match "\\+?(\\d{1}.)?\\(?\\d{3}?\\)?.\\d{3}.?\\d{4}"
type.inbound eq "true"
macro "any(ml.nlu_classifier(body.current_thread.text).tags,\n .name == \"invoice\" and .confidence == \"high\"\n)"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match value:"+?(\d{1}.)?(?\d{3}?)?.\d{3}.?\d{4}" |
body.current_thread.text | wildcard |
| field:"body.current_thread.text" kind:wildcard |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing: SumUp infrastructure abuse
#A fraudulent invoice/receipt found in the body of the message sent by exploiting SumUp's receipt email service.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | BEC/Fraud, Callback Phishing |
| Tactics and techniques | Evasion, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and sender.email.domain.root_domain in ("sumup.com")
and (
strings.ilike(body.html.display_text, "*delivery note*")
or strings.ilike(body.html.display_text, "*made with sumup*")
)
// keep in sync with https://github.com/sublime-security/sublime-rules/blob/main/detection-rules/paypal_invoice_abuse.yml
and (
(
// icontains a phone number
(
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\n'
)
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\+[ilo0-9]{1,3}[ilo0-9]{10}.*\n'
)
// +12028001238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\n'
)
// 202-800-1238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\n'
)
// (202) 800-1238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*\n'
)
// (202)-800-1238
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\n'
)
or ( // 8123456789
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*8[ilo0-9]{9}.*\n'
)
and regex.icontains(strings.replace_confusables(body.current_thread.text
),
'\+[1l]'
)
)
)
and (
(
4 of (
strings.ilike(body.html.inner_text, '*you did not*'),
strings.ilike(body.html.inner_text, '*is not for*'),
strings.ilike(body.html.inner_text, '*done by you*'),
regex.icontains(body.html.inner_text, "didn\'t ma[kd]e this"),
strings.ilike(body.html.inner_text, '*Fruad Alert*'),
strings.ilike(body.html.inner_text, '*Fraud Alert*'),
strings.ilike(body.html.inner_text, '*fraudulent*'),
strings.ilike(body.html.inner_text, '*using your PayPal*'),
strings.ilike(body.html.inner_text, '*subscription*'),
strings.ilike(body.html.inner_text, '*antivirus*'),
strings.ilike(body.html.inner_text, '*order*'),
strings.ilike(body.html.inner_text, '*support*'),
strings.ilike(body.html.inner_text, '*sincerely apologize*'),
strings.ilike(body.html.inner_text, '*receipt*'),
strings.ilike(body.html.inner_text, '*invoice*'),
strings.ilike(body.html.inner_text, '*Purchase*'),
strings.ilike(body.html.inner_text, '*transaction*'),
strings.ilike(body.html.inner_text, '*Market*Value*'),
strings.ilike(body.html.inner_text, '*BTC*'),
strings.ilike(body.html.inner_text, '*call*'),
strings.ilike(body.html.inner_text, '*get in touch with our*'),
strings.ilike(body.html.inner_text, '*quickly inform*'),
strings.ilike(body.html.inner_text, '*quickly reach *'),
strings.ilike(body.html.inner_text, '*detected unusual transactions*'),
strings.ilike(body.html.inner_text, '*without your authorization*'),
strings.ilike(body.html.inner_text, '*cancel*'),
strings.ilike(body.html.inner_text, '*renew*'),
strings.ilike(body.html.inner_text, '*refund*'),
strings.ilike(body.html.inner_text, '*+1*'),
regex.icontains(body.html.inner_text, 'help.{0,3}desk'),
strings.ilike(body.html.inner_text, '* your funds*'),
strings.ilike(body.html.inner_text, '* your checking*'),
strings.ilike(body.html.inner_text, '* your saving*'),
strings.ilike(body.html.inner_text, '*transfer*'),
strings.ilike(body.html.inner_text, '*secure your account*'),
strings.ilike(body.html.inner_text, '*recover your*'),
strings.ilike(body.html.inner_text, '*unusual activity*'),
strings.ilike(body.html.inner_text, '*suspicious transaction*'),
strings.ilike(body.html.inner_text, '*transaction history*'),
strings.ilike(body.html.inner_text, '*please ignore this*'),
strings.ilike(body.html.inner_text, '*report activity*'),
)
)
or regex.icontains(body.current_thread.text,
'note from.{0,50}(?:call|reach|contact|paypal)'
)
or any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "callback_scam"
)
or (
// Unicode confusables words obfuscated in note
regex.icontains(body.html.inner_text,
'\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹'
)
)
or strings.ilike(body.html.inner_text, '*kindly*')
)
)
)
Detection Logic
Scope: inbound message.
A fraudulent invoice/receipt found in the body of the message sent by exploiting SumUp's receipt email service.
- inbound message
- sender.email.domain.root_domain in ('sumup.com')
any of:
- body.html.display_text matches '*delivery note*'
- body.html.display_text matches '*made with sumup*'
all of:
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '.*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '.*\+[ilo0-9]{1,3}[ilo0-9]{10}.*\n' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '.*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '.*\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*\n' )
- regex.icontains(strings.replace_confusables(body.current_thread.text), '.*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\n' )
all of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), '.*8[ilo0-9]{9}.*\n' )
- regex.icontains(strings.replace_confusables(body.current_thread.text ), '\+[1l]' )
any of:
at least 4 of 41: body.html.inner_text matches any of 41 patterns
*you did not**is not for**done by you*didn\'t ma[kd]e this*Fruad Alert**Fraud Alert**fraudulent**using your PayPal**subscription**antivirus**order**support**sincerely apologize**receipt**invoice**Purchase**transaction**Market*Value**BTC**call**get in touch with our**quickly inform**quickly reach **detected unusual transactions**without your authorization**cancel**renew**refund**+1*help.{0,3}desk* your funds** your checking** your saving**transfer**secure your account**recover your**unusual activity**suspicious transaction**transaction history**please ignore this**report activity*
- body.current_thread.text matches 'note from.{0,50}(?:call|reach|contact|paypal)'
- any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" )
- body.html.inner_text matches '\\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹'
- body.html.inner_text matches '*kindly*'
Inspects: body.current_thread.text, body.html.display_text, body.html.inner_text, sender.email.domain.root_domain, type.inbound. Sensors: ml.nlu_classifier, regex.icontains, strings.ilike, strings.replace_confusables.
Indicators Matched (56)
| Field | Match | Value |
|---|---|---|
sender.email.domain.root_domain | member | sumup.com |
strings.ilike | substring | *delivery note* |
strings.ilike | substring | *made with sumup* |
regex.icontains | regex | .*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\n |
regex.icontains | regex | .*\+[ilo0-9]{1,3}[ilo0-9]{10}.*\n |
regex.icontains | regex | .*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\n |
regex.icontains | regex | .*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\n |
regex.icontains | regex | .*\([ilo0-9]{3}\)[\s-]+[ilo0-9]{3}[\s-]+[ilo0-9]{4}.*\n |
regex.icontains | regex | .*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\n |
regex.icontains | regex | .*8[ilo0-9]{9}.*\n |
regex.icontains | regex | \+[1l] |
strings.ilike | substring | *you did not* |
44 more
strings.ilike | substring | *is not for* |
strings.ilike | substring | *done by you* |
regex.icontains | regex | didn\'t ma[kd]e this |
strings.ilike | substring | *Fruad Alert* |
strings.ilike | substring | *Fraud Alert* |
strings.ilike | substring | *fraudulent* |
strings.ilike | substring | *using your PayPal* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
strings.ilike | substring | *sincerely apologize* |
strings.ilike | substring | *receipt* |
strings.ilike | substring | *invoice* |
strings.ilike | substring | *Purchase* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *Market*Value* |
strings.ilike | substring | *BTC* |
strings.ilike | substring | *call* |
strings.ilike | substring | *get in touch with our* |
strings.ilike | substring | *quickly inform* |
strings.ilike | substring | *quickly reach * |
strings.ilike | substring | *detected unusual transactions* |
strings.ilike | substring | *without your authorization* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
strings.ilike | substring | *+1* |
regex.icontains | regex | help.{0,3}desk |
strings.ilike | substring | * your funds* |
strings.ilike | substring | * your checking* |
strings.ilike | substring | * your saving* |
strings.ilike | substring | *transfer* |
strings.ilike | substring | *secure your account* |
strings.ilike | substring | *recover your* |
strings.ilike | substring | *unusual activity* |
strings.ilike | substring | *suspicious transaction* |
strings.ilike | substring | *transaction history* |
strings.ilike | substring | *please ignore this* |
strings.ilike | substring | *report activity* |
regex.icontains | regex | note from.{0,50}(?:call|reach|contact|paypal) |
ml.nlu_classifier(body.current_thread.text).intents[].name | equals | callback_scam |
regex.icontains | regex | \+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹 |
strings.ilike | substring | *kindly* |
Stages and Predicates
Stage 1: mql_rule
and
or
and
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '.*8[ilo0-9]{9}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text\n ),\n '\\+[1l]'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '.*[ilo0-9]{3}\\.[ilo0-9]{3}\\.[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '.*\\([ilo0-9]{3}\\)-[ilo0-9]{3}-[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '.*\\([ilo0-9]{3}\\)[\\s-]+[ilo0-9]{3}[\\s-]+[ilo0-9]{4}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '.*\\+[ilo0-9]{1,3}[ilo0-9]{10}.*\\n'\n )"
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n '.*\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\\n'\n )"
or
body.current_thread.text regex_match "note from.{0,50}(?:call|reach|contact|paypal)"
body.html.inner_text match "kindly"
body.html.inner_text regex_match "\\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹"
macro "4 of (\n strings.ilike(body.html.inner_text, '*you did not*'),\n strings.ilike(body.html.inner_text, '*is not for*'),\n strings.ilike(body.html.inner_text, '*done by you*'),\n regex.icontains(body.html.inner_text, \"didn\\'t ma[kd]e this\"),\n strings.ilike(body.html.inner_text, '*Fruad Alert*'),\n strings.ilike(body.html.inner_text, '*Fraud Alert*'),\n strings.ilike(body.html.inner_text, '*fraudulent*'),\n strings.ilike(body.html.inner_text, '*using your PayPal*'),\n strings.ilike(body.html.inner_text, '*subscription*'),\n strings.ilike(body.html.inner_text, '*antivirus*'),\n strings.ilike(body.html.inner_text, '*order*'),\n strings.ilike(body.html.inner_text, '*support*'),\n strings.ilike(body.html.inner_text, '*sincerely apologize*'),\n strings.ilike(body.html.inner_text, '*receipt*'),\n strings.ilike(body.html.inner_text, '*invoice*'),\n strings.ilike(body.html.inner_text, '*Purchase*'),\n strings.ilike(body.html.inner_text, '*transaction*'),\n strings.ilike(body.html.inner_text, '*Market*Value*'),\n strings.ilike(body.html.inner_text, '*BTC*'),\n strings.ilike(body.html.inner_text, '*call*'),\n strings.ilike(body.html.inner_text, '*get in touch with our*'),\n strings.ilike(body.html.inner_text, '*quickly inform*'),\n strings.ilike(body.html.inner_text, '*quickly reach *'),\n strings.ilike(body.html.inner_text, '*detected unusual transactions*'),\n strings.ilike(body.html.inner_text, '*without your authorization*'),\n strings.ilike(body.html.inner_text, '*cancel*'),\n strings.ilike(body.html.inner_text, '*renew*'),\n strings.ilike(body.html.inner_text, '*refund*'),\n strings.ilike(body.html.inner_text, '*+1*'),\n regex.icontains(body.html.inner_text, 'help.{0,3}desk'),\n strings.ilike(body.html.inner_text, '* your funds*'),\n strings.ilike(body.html.inner_text, '* your checking*'),\n strings.ilike(body.html.inner_text, '* your saving*'),\n strings.ilike(body.html.inner_text, '*transfer*'),\n strings.ilike(body.html.inner_text, '*secure your account*'),\n strings.ilike(body.html.inner_text, '*recover your*'),\n strings.ilike(body.html.inner_text, '*unusual activity*'),\n strings.ilike(body.html.inner_text, '*suspicious transaction*'),\n strings.ilike(body.html.inner_text, '*transaction history*'),\n strings.ilike(body.html.inner_text, '*please ignore this*'),\n strings.ilike(body.html.inner_text, '*report activity*'),\n )"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name == \"callback_scam\"\n )"
or
body.html.display_text match "delivery note"
body.html.display_text match "made with sumup"
sender.email.domain.root_domain eq "sumup.com"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match value:"note from.{0,50}(?:call|reach|contact|paypal)" |
body.html.display_text | wildcard |
| field:"body.html.display_text" kind:wildcard |
body.html.inner_text | regex_match |
| field:"body.html.inner_text" kind:regex_match |
body.html.inner_text | wildcard |
| field:"body.html.inner_text" kind:wildcard value:"*kindly*" |
sender.email.domain.root_domain | in |
| field:"sender.email.domain.root_domain" kind:in value:"sumup.com" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback phishing: Zero-width character obfuscation from freemail sender
#Detects inbound messages sent from free email providers that contain a high volume of zero-width no-break space characters inserted before closing HTML tags, a technique used to break up and obfuscate text from content scanners. The rule also requires the presence of a phone number pattern in the message thread, consistent with callback phishing lures that rely on victims dialing a number rather than clicking a link.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Free email provider, Evasion, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and sender.email.domain.root_domain in $free_email_providers
and regex.icount(body.html.raw, '\x{FEFF}+</[^>]*>[a-z0-9]') >= 20
and regex.icontains(body.current_thread.text,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
'\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
)
Detection Logic
Scope: inbound message.
Detects inbound messages sent from free email providers that contain a high volume of zero-width no-break space characters inserted before closing HTML tags, a technique used to break up and obfuscate text from content scanners. The rule also requires the presence of a phone number pattern in the message thread, consistent with callback phishing lures that rely on victims dialing a number rather than clicking a link.
- inbound message
- sender.email.domain.root_domain in $free_email_providers
- regex.icount(body.html.raw, '\x{FEFF}+</[^>]*>[a-z0-9]') >= 20
body.current_thread.text matches any of 2 patterns
\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
Inspects: body.current_thread.text, body.html.raw, sender.email.domain.root_domain, type.inbound. Sensors: regex.icontains, regex.icount. Reference lists: $free_email_providers.
Indicators Matched (3)
| Field | Match | Value |
|---|---|---|
regex.icount | regex | \x{FEFF}+</[^>]*>[a-z0-9] |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
regex.icontains | regex | \+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4} |
Stages and Predicates
Stage 1: mql_rule
and
or
body.current_thread.text regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
body.current_thread.text regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
regex.icount func_call "regex.icount(body.html.raw, '\\x{FEFF}+</[^>]*>[a-z0-9]') >= 20"
sender.email.domain.root_domain macro "sender.email.domain.root_domain in free_email_providers"
type.inbound eq "true"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
body.current_thread.text | regex_match |
| field:"body.current_thread.text" kind:regex_match |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Callback Scam: Outlook groups
#Detects inbound messages sent to Outlook group distribution lists (groups.outlook.com) where the body text is classified with high confidence as callback scam intent by an NLU model, while excluding cases where recipient lists are empty or entirely invalid.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and all(recipients.to, .email.domain.domain == "groups.outlook.com")
and any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "callback_scam" and .confidence == "high"
)
and not (
length(recipients.to) == 0 or all(recipients.to, .email.domain.valid == false)
)
Detection Logic
Scope: inbound message.
Detects inbound messages sent to Outlook group distribution lists (groups.outlook.com) where the body text is classified with high confidence as callback scam intent by an NLU model, while excluding cases where recipient lists are empty or entirely invalid.
- inbound message
all of
recipients.towhere:- .email.domain.domain is 'groups.outlook.com'
- any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" and .confidence == "high" )
none of:
- length(recipients.to) == 0
all of
recipients.towhere:- .email.domain.valid is False
Inspects: body.current_thread.text, recipients.to, recipients.to[].email.domain.domain, recipients.to[].email.domain.valid, type.inbound. Sensors: ml.nlu_classifier.
Indicators Matched (3)
| Field | Match | Value |
|---|---|---|
recipients.to[].email.domain.domain | equals | groups.outlook.com |
ml.nlu_classifier(body.current_thread.text).intents[].name | equals | callback_scam |
ml.nlu_classifier(body.current_thread.text).intents[].confidence | equals | high |
Stages and Predicates
Stage 1: mql_rule
and
not
or
recipients.to length_compare "0"
macro "all(recipients.to, .email.domain.valid == false)"
type.inbound eq "true"
macro "all(recipients.to, .email.domain.domain == \"groups.outlook.com\")"
macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n .name == \"callback_scam\" and .confidence == \"high\"\n)"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
recipients.to | length_compare | 0 | excludes:recipients.to field:"recipients.to" value:"0" |
Service abuse: Callback phishing via Microsoft Teams invite
#Detects abuse of legitimate Microsoft Teams invites containing callback scam content, including brand references and financial transaction language with phone numbers.
Threat Classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Callback Phishing |
| Tactics and techniques | Impersonation: Brand, Out of band pivot, Social engineering |
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Sublime | Inbound email message |
Message Attributes
Rule Body
type.inbound
and sender.email.domain.domain == "teams.mail.microsoft"
// MS Teams invite indicators
and (
any(body.links,
.display_text == "Open Microsoft Teams"
and (
.href_url.domain.domain == "login.microsoftonline.com"
or strings.iends_with(.href_url.query_params,
"login.microsoftonline.com"
)
)
)
)
and (
(
regex.icontains(strings.replace_confusables(body.current_thread.text),
(
"mcafee|norton|geek.{0,5}squad|pay.?pal|ebay|symantec|best buy|lifelock|(ms|microsoft|teams).{0,10}premium"
)
)
or 3 of (
strings.ilike(body.current_thread.text, '*purchase*'),
strings.ilike(body.current_thread.text, '*p?ym?nt*'),
strings.ilike(body.current_thread.text, '*transaction*'),
strings.ilike(body.current_thread.text, '*subscription*'),
strings.ilike(body.current_thread.text, '*antivirus*'),
strings.ilike(body.current_thread.text, '*order*'),
strings.ilike(body.current_thread.text, '*support*'),
strings.ilike(body.current_thread.text, '*help line*'),
strings.ilike(body.current_thread.text, '*receipt*'),
strings.ilike(body.current_thread.text, '*c?ntact*'),
strings.ilike(body.current_thread.text, '*cancel*'),
strings.ilike(body.current_thread.text, '*renew*'),
strings.ilike(body.current_thread.text, '*refund*'),
strings.ilike(body.current_thread.text, '*billing*'),
regex.icontains(body.current_thread.text, '[li]nv.[li]ce')
)
)
// phone number regex
and any([body.current_thread.text, subject.subject],
regex.icontains(.,
'\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}'
)
)
)
Detection Logic
Scope: inbound message.
Detects abuse of legitimate Microsoft Teams invites containing callback scam content, including brand references and financial transaction language with phone numbers.
- inbound message
- sender.email.domain.domain is 'teams.mail.microsoft'
any of
body.linkswhere all hold:- .display_text is 'Open Microsoft Teams'
any of:
- .href_url.domain.domain is 'login.microsoftonline.com'
- .href_url.query_params ends with 'login.microsoftonline.com'
all of:
any of:
- regex.icontains(strings.replace_confusables(body.current_thread.text), ( "mcafee|norton|geek.{0,5}squad|pay.?pal|ebay|symantec|best buy|lifelock|(ms|microsoft|teams).{0,10}premium" ) )
at least 3 of 15: body.current_thread.text matches any of 15 patterns
*purchase**p?ym?nt**transaction**subscription**antivirus**order**support**help line**receipt**c?ntact**cancel**renew**refund**billing*[li]nv.[li]ce
- any([body.current_thread.text, subject.subject], regex.icontains(., '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}' ) )
Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.domain, body.links[].href_url.query_params, sender.email.domain.domain, subject.subject, type.inbound. Sensors: regex.icontains, strings.iends_with, strings.ilike, strings.replace_confusables.
Indicators Matched (21)
| Field | Match | Value |
|---|---|---|
sender.email.domain.domain | equals | teams.mail.microsoft |
body.links[].display_text | equals | Open Microsoft Teams |
body.links[].href_url.domain.domain | equals | login.microsoftonline.com |
strings.iends_with | suffix | login.microsoftonline.com |
regex.icontains | regex | mcafee|norton|geek.{0,5}squad|pay.?pal|ebay|symantec|best buy|lifelock|(ms|microsoft|teams).{0,10}premium |
strings.ilike | substring | *purchase* |
strings.ilike | substring | *p?ym?nt* |
strings.ilike | substring | *transaction* |
strings.ilike | substring | *subscription* |
strings.ilike | substring | *antivirus* |
strings.ilike | substring | *order* |
strings.ilike | substring | *support* |
9 more
strings.ilike | substring | *help line* |
strings.ilike | substring | *receipt* |
strings.ilike | substring | *c?ntact* |
strings.ilike | substring | *cancel* |
strings.ilike | substring | *renew* |
strings.ilike | substring | *refund* |
strings.ilike | substring | *billing* |
regex.icontains | regex | [li]nv.[li]ce |
regex.icontains | regex | \+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4} |
Stages and Predicates
Stage 1: mql_rule
and
any(body.links)
and
or
body.links.href_url.domain.domain eq "login.microsoftonline.com"
body.links.href_url.query_params ends_with "login.microsoftonline.com"
body.links.display_text eq "Open Microsoft Teams"
or
regex.icontains func_call "regex.icontains(strings.replace_confusables(body.current_thread.text),\n (\n \"mcafee|norton|geek.{0,5}squad|pay.?pal|ebay|symantec|best buy|lifelock|(ms|microsoft|teams).{0,10}premium\"\n )\n )"
macro "3 of (\n strings.ilike(body.current_thread.text, '*purchase*'),\n strings.ilike(body.current_thread.text, '*p?ym?nt*'),\n strings.ilike(body.current_thread.text, '*transaction*'),\n strings.ilike(body.current_thread.text, '*subscription*'),\n strings.ilike(body.current_thread.text, '*antivirus*'),\n strings.ilike(body.current_thread.text, '*order*'),\n strings.ilike(body.current_thread.text, '*support*'),\n strings.ilike(body.current_thread.text, '*help line*'),\n strings.ilike(body.current_thread.text, '*receipt*'),\n strings.ilike(body.current_thread.text, '*c?ntact*'),\n strings.ilike(body.current_thread.text, '*cancel*'),\n strings.ilike(body.current_thread.text, '*renew*'),\n strings.ilike(body.current_thread.text, '*refund*'),\n strings.ilike(body.current_thread.text, '*billing*'),\n regex.icontains(body.current_thread.text, '[li]nv.[li]ce')\n )"
sender.email.domain.domain eq "teams.mail.microsoft"
type.inbound eq "true"
macro "any([body.current_thread.text, subject.subject],\n regex.icontains(.,\n '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}'\n )\n )"Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
sender.email.domain.domain | eq |
| field:"sender.email.domain.domain" kind:eq value:"teams.mail.microsoft" |
type.inbound | eq |
| field:"type.inbound" kind:eq value:"true" |