Detection rules › Sublime MQL
Spam: Fake photo share
Message contains pretexting language about sharing photos ("found these photos and thought you'd like them", "remember these photos?") and a link with a newly registered domain. Fake threads and plain text bodies have been seen in the wild, indicating active evasion techniques.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Spam |
| Tactics and techniques | Evasion, Social engineering |
Event coverage
Rule body MQL
type.inbound
and length(attachments) == 0
and (
(
(
(
(length(body.plain.raw) < 500 and length(body.current_thread.text) == 0)
or (
length(body.html.display_text) < 500
and length(body.current_thread.text) == 0
)
or length(body.current_thread.text) < 500
or any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,
.name == "disclaimer"
),
.text
),
(length(body.current_thread.text) - length(.)) < 500
)
)
and strings.ilike(subject.subject,
"*picture*",
"*photo*",
"*image*",
"*sad news*",
"*sad announcement*",
"*sad update*",
"*new pics*",
"*Reunion*",
"*planing*"
)
)
or (
(
(
length(body.html.display_text) < 500
and length(body.current_thread.text) == 0
)
and strings.ilike(body.html.display_text,
"*picture*",
"*photo*",
"*image*",
"*sad news*",
"*sad announcement*",
"*sad update*",
"*new pics*"
)
)
or (
(length(body.plain.raw) < 500 and length(body.current_thread.text) == 0)
and strings.ilike(body.plain.raw,
"*picture*",
"*photo*",
"*image*",
"*sad news*",
"*sad announcement*",
"*sad update*",
"*new pics*"
)
and not strings.icontains(body.plain.raw, "[cid:image")
)
or (
length(body.current_thread.text) < 500
and strings.ilike(body.current_thread.text,
"*picture*",
"*photo*",
"*image*",
"*sad news*",
"*sad announcement*",
"*sad update*",
"*new pics*"
)
)
)
or (
body.plain.raw is not null
and body.html.display_text is null
and (
length(body.current_thread.text) == 0
or (
length(body.current_thread.text) < 500
// fake forward indicator in the plain text body
and (
regex.contains(body.plain.raw,
'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
)
or strings.icontains(body.plain.raw, 'Original Message')
)
and not regex.contains(body.current_thread.text,
'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
)
and not strings.icontains(body.current_thread.text,
'Original Message'
)
and not any(headers.hops, any(.fields, .name == "Resent-From"))
)
)
and strings.ilike(body.plain.raw,
"*picture*",
"*photo*",
"*image*",
"*sad news*",
"*sad announcement*",
"*sad update*",
"*pics*"
)
and not strings.istarts_with(body.plain.raw, "[cid:image")
and strings.icontains(subject.subject, sender.display_name)
)
or (
strings.icontains(subject.subject, sender.display_name)
and sender.email.domain.root_domain in $free_email_providers
and length(body.links) == 2
and length(filter(body.links, .display_text == "h")) == 1
and length(filter(body.links, .display_url.scheme == "ttp")) == 1
)
)
and length(body.links) < 5
and any(body.links,
(
(
network.whois(.href_url.domain).days_old < 30
or not network.whois(.href_url.domain).found
or network.whois(.href_url.domain).found is null
)
and .href_url.domain.root_domain != sender.email.domain.root_domain
)
or (
length(.display_text) == 1
and .href_url.domain.root_domain in ("facebook.com", "youtube.com")
)
or (
// random 5-character subdomain
regex.icontains(.href_url.domain.domain,
'^[a-z]{5}\.[a-z]{5,}\.[a-z]+'
)
// subdomain contains 3+ consecutive consonants
and regex.icontains(.href_url.domain.domain,
'^[a-z]*[b-df-hj-np-tv-z]{3,}[a-z]*\.'
)
and network.whois(.href_url.domain).days_old < 365
)
)
)
and (
(
(length(headers.references) > 0 or headers.in_reply_to is null)
and not (
(
strings.istarts_with(subject.subject, "RE:")
or strings.istarts_with(subject.subject, "R:")
or strings.istarts_with(subject.subject, "ODG:")
or strings.istarts_with(subject.subject, "答复:")
or strings.istarts_with(subject.subject, "AW:")
or strings.istarts_with(subject.subject, "TR:")
or strings.istarts_with(subject.subject, "FWD:")
or regex.imatch(subject.subject, '(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:')
)
)
)
or length(headers.references) == 0
)
// 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.
Message contains pretexting language about sharing photos ("found these photos and thought you'd like them", "remember these photos?") and a link with a newly registered domain. Fake threads and plain text bodies have been seen in the wild, indicating active evasion techniques.
- inbound message
- length(attachments) is 0
all of:
any of:
all of:
any of:
all of:
- length(body.plain.raw) < 500
- length(body.current_thread.text) is 0
all of:
- length(body.html.display_text) < 500
- length(body.current_thread.text) is 0
- length(body.current_thread.text) < 500
any of
map(...)where:- length(body.current_thread.text) - length(.) < 500
subject.subject matches any of 9 patterns
*picture**photo**image**sad news**sad announcement**sad update**new pics**Reunion**planing*
any of:
all of:
all of:
- length(body.html.display_text) < 500
- length(body.current_thread.text) is 0
body.html.display_text matches any of 7 patterns
*picture**photo**image**sad news**sad announcement**sad update**new pics*
all of:
all of:
- length(body.plain.raw) < 500
- length(body.current_thread.text) is 0
body.plain.raw matches any of 7 patterns
*picture**photo**image**sad news**sad announcement**sad update**new pics*
not:
- body.plain.raw contains '[cid:image'
all of:
- length(body.current_thread.text) < 500
body.current_thread.text matches any of 7 patterns
*picture**photo**image**sad news**sad announcement**sad update**new pics*
all of:
- body.plain.raw is set
- body.html.display_text is missing
any of:
- length(body.current_thread.text) is 0
all of:
- length(body.current_thread.text) < 500
any of:
- body.plain.raw matches 'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
- body.plain.raw contains 'Original Message'
not:
- body.current_thread.text matches 'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
not:
- body.current_thread.text contains 'Original Message'
not:
any of
headers.hopswhere:any of
.fieldswhere:- .name is 'Resent-From'
body.plain.raw matches any of 7 patterns
*picture**photo**image**sad news**sad announcement**sad update**pics*
not:
- body.plain.raw starts with '[cid:image'
- strings.icontains(subject.subject)
all of:
- strings.icontains(subject.subject)
- sender.email.domain.root_domain in $free_email_providers
- length(body.links) is 2
- length(filter(body.links, .display_text == 'h')) is 1
- length(filter(body.links, .display_url.scheme == 'ttp')) is 1
- length(body.links) < 5
any of
body.linkswhere any holds:all of:
any of:
- network.whois(.href_url.domain).days_old < 30
not:
- network.whois(.href_url.domain).found
- network.whois(.href_url.domain).found is missing
- .href_url.domain.root_domain is not sender.email.domain.root_domain
all of:
- length(.display_text) is 1
- .href_url.domain.root_domain in ('facebook.com', 'youtube.com')
all of:
- .href_url.domain.domain matches '^[a-z]{5}\\.[a-z]{5,}\\.[a-z]+'
- .href_url.domain.domain matches '^[a-z]*[b-df-hj-np-tv-z]{3,}[a-z]*\\.'
- network.whois(.href_url.domain).days_old < 365
any of:
all of:
any of:
- length(headers.references) > 0
- headers.in_reply_to is missing
none of:
- subject.subject starts with 'RE:'
- subject.subject starts with 'R:'
- subject.subject starts with 'ODG:'
- subject.subject starts with '答复:'
- subject.subject starts with 'AW:'
- subject.subject starts with 'TR:'
- subject.subject starts with 'FWD:'
- subject.subject matches '(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?)\\s?:'
- length(headers.references) is 0
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: body.current_thread.text, body.html.display_text, body.links, body.links[].display_text, body.links[].display_url.scheme, body.links[].href_url.domain, body.links[].href_url.domain.domain, body.links[].href_url.domain.root_domain, body.plain.raw, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, headers.in_reply_to, headers.references, sender.display_name, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: ml.nlu_classifier, network.whois, regex.contains, regex.icontains, regex.imatch, strings.icontains, strings.ilike, strings.istarts_with. Reference lists: $free_email_providers, $high_trust_sender_root_domains.
Indicators matched (30)
| Field | Match | Value |
|---|---|---|
ml.nlu_classifier(body.current_thread.text).entities[].name | equals | disclaimer |
strings.ilike | substring | *picture* |
strings.ilike | substring | *photo* |
strings.ilike | substring | *image* |
strings.ilike | substring | *sad news* |
strings.ilike | substring | *sad announcement* |
strings.ilike | substring | *sad update* |
strings.ilike | substring | *new pics* |
strings.ilike | substring | *Reunion* |
strings.ilike | substring | *planing* |
strings.icontains | substring | [cid:image |
regex.contains | regex | On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote |
18 more
strings.icontains | substring | Original Message |
headers.hops[].fields[].name | equals | Resent-From |
strings.ilike | substring | *pics* |
strings.istarts_with | prefix | [cid:image |
body.links[].display_text | equals | h |
body.links[].display_url.scheme | equals | ttp |
body.links[].href_url.domain.root_domain | member | facebook.com |
body.links[].href_url.domain.root_domain | member | youtube.com |
regex.icontains | regex | ^[a-z]{5}\.[a-z]{5,}\.[a-z]+ |
regex.icontains | regex | ^[a-z]*[b-df-hj-np-tv-z]{3,}[a-z]*\. |
strings.istarts_with | prefix | RE: |
strings.istarts_with | prefix | R: |
strings.istarts_with | prefix | ODG: |
strings.istarts_with | prefix | 答复: |
strings.istarts_with | prefix | AW: |
strings.istarts_with | prefix | TR: |
strings.istarts_with | prefix | FWD: |
regex.imatch | regex | (\[[^\]]+\]\s?){0,3}(re|fwd?)\s?: |