Skip to content

Commit f603937

Browse files
[Shared Samples] [PR #4702] added rule: PR# 4702 - Spam: Photo/image lure
1 parent c2b9c8b commit f603937

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
name: "PR# 4702 - Spam: Photo/image lure"
2+
description: '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.'
3+
type: "rule"
4+
severity: "low"
5+
source: |
6+
type.inbound
7+
and length(attachments) == 0
8+
and (
9+
(
10+
(
11+
(
12+
(length(body.plain.raw) < 500 and length(body.current_thread.text) == 0)
13+
or (
14+
length(body.html.display_text) < 500
15+
and length(body.current_thread.text) == 0
16+
)
17+
or length(body.current_thread.text) < 500
18+
or any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,
19+
.name == "disclaimer"
20+
),
21+
.text
22+
),
23+
(length(body.current_thread.text) - length(.)) < 500
24+
)
25+
)
26+
and strings.ilike(subject.subject,
27+
"*picture*",
28+
"*photo*",
29+
"*image*",
30+
"*sad news*",
31+
"*sad announcement*",
32+
"*sad update*",
33+
"*new pics*",
34+
"*Reunion*",
35+
"*planing*"
36+
)
37+
)
38+
or (
39+
(
40+
(
41+
length(body.html.display_text) < 500
42+
and length(body.current_thread.text) == 0
43+
)
44+
and strings.ilike(body.html.display_text,
45+
"*picture*",
46+
"*photo*",
47+
"*image*",
48+
"*sad news*",
49+
"*sad announcement*",
50+
"*sad update*",
51+
"*new pics*"
52+
)
53+
)
54+
or (
55+
(length(body.plain.raw) < 500 and length(body.current_thread.text) == 0)
56+
and strings.ilike(body.plain.raw,
57+
"*picture*",
58+
"*photo*",
59+
"*image*",
60+
"*sad news*",
61+
"*sad announcement*",
62+
"*sad update*",
63+
"*new pics*"
64+
)
65+
and not strings.icontains(body.plain.raw, "[cid:image")
66+
)
67+
or (
68+
length(body.current_thread.text) < 500
69+
and (
70+
strings.ilike(body.current_thread.text,
71+
"*picture*",
72+
"*photo*",
73+
"*image*",
74+
"*sad news*",
75+
"*sad announcement*",
76+
"*sad update*",
77+
"*new pics*"
78+
)
79+
or regex.icontains(body.current_thread.text,
80+
'\b(photo|pics?|picture)\b'
81+
)
82+
)
83+
)
84+
)
85+
or (
86+
body.plain.raw is not null
87+
and body.html.display_text is null
88+
and (
89+
length(body.current_thread.text) == 0
90+
or (
91+
length(body.current_thread.text) < 500
92+
// fake forward indicator in the plain text body
93+
and (
94+
regex.contains(body.plain.raw,
95+
'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
96+
)
97+
or strings.icontains(body.plain.raw, 'Original Message')
98+
)
99+
and not regex.contains(body.current_thread.text,
100+
'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
101+
)
102+
and not strings.icontains(body.current_thread.text,
103+
'Original Message'
104+
)
105+
and not any(headers.hops, any(.fields, .name == "Resent-From"))
106+
)
107+
)
108+
and strings.ilike(body.plain.raw,
109+
"*picture*",
110+
"*photo*",
111+
"*image*",
112+
"*sad news*",
113+
"*sad announcement*",
114+
"*sad update*",
115+
"*pics*"
116+
)
117+
and not strings.istarts_with(body.plain.raw, "[cid:image")
118+
and strings.icontains(subject.subject, sender.display_name)
119+
)
120+
or (
121+
strings.icontains(subject.subject, sender.display_name)
122+
and sender.email.domain.root_domain in $free_email_providers
123+
and length(body.links) == 2
124+
and length(filter(body.links, .display_text == "h")) == 1
125+
and length(filter(body.links, .display_url.scheme == "ttp")) == 1
126+
)
127+
)
128+
and length(body.links) < 5
129+
and any(body.links,
130+
(
131+
(
132+
network.whois(.href_url.domain).days_old < 30
133+
or not network.whois(.href_url.domain).found
134+
or network.whois(.href_url.domain).found is null
135+
)
136+
and .href_url.domain.root_domain != sender.email.domain.root_domain
137+
)
138+
or (
139+
length(.display_text) == 1
140+
and .href_url.domain.root_domain in ("facebook.com", "youtube.com")
141+
)
142+
or (
143+
// random 5-character subdomain
144+
regex.icontains(.href_url.domain.domain,
145+
'^[a-z]{5}\.[a-z]{5,}\.[a-z]+'
146+
)
147+
// subdomain contains 3+ consecutive consonants
148+
and regex.icontains(.href_url.domain.domain,
149+
'^[a-z]*[b-df-hj-np-tv-z]{3,}[a-z]*\.'
150+
)
151+
and network.whois(.href_url.domain).days_old < 365
152+
)
153+
)
154+
)
155+
and (
156+
(
157+
(length(headers.references) > 0 or headers.in_reply_to is null)
158+
and not (
159+
(
160+
strings.istarts_with(subject.subject, "RE:")
161+
or strings.istarts_with(subject.subject, "R:")
162+
or strings.istarts_with(subject.subject, "ODG:")
163+
or strings.istarts_with(subject.subject, "答复:")
164+
or strings.istarts_with(subject.subject, "AW:")
165+
or strings.istarts_with(subject.subject, "TR:")
166+
or strings.istarts_with(subject.subject, "FWD:")
167+
or regex.imatch(subject.subject, '(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:')
168+
)
169+
)
170+
)
171+
or length(headers.references) == 0
172+
)
173+
// negate highly trusted sender domains unless they fail DMARC authentication
174+
and (
175+
(
176+
sender.email.domain.root_domain in $high_trust_sender_root_domains
177+
and not headers.auth_summary.dmarc.pass
178+
)
179+
or sender.email.domain.root_domain not in $high_trust_sender_root_domains
180+
)
181+
attack_types:
182+
- "Spam"
183+
tactics_and_techniques:
184+
- "Evasion"
185+
- "Social engineering"
186+
detection_methods:
187+
- "Content analysis"
188+
- "Sender analysis"
189+
- "URL analysis"
190+
- "Whois"
191+
id: "52b43a73-9783-5ae6-a52b-b785a9ed83ad"
192+
tags:
193+
- created_from_open_prs
194+
- rule_status_renamed
195+
- pr_author_cybher0808
196+
references:
197+
- https://github.com/sublime-security/sublime-rules/pull/4702

0 commit comments

Comments
 (0)