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.

Sublime rule (View on GitHub)

  1name: "Spam: Fake photo share"
  2description: '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.'
  3type: "rule"
  4severity: "low"
  5source: |
  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 strings.ilike(body.current_thread.text,
 70                            "*picture*",
 71                            "*photo*",
 72                            "*image*",
 73                            "*sad news*",
 74                            "*sad announcement*",
 75                            "*sad update*",
 76                            "*new pics*"
 77          )
 78        )
 79      )
 80      or (
 81        body.plain.raw is not null
 82        and body.html.display_text is null
 83        and (
 84          length(body.current_thread.text) == 0
 85          or (
 86            length(body.current_thread.text) < 500
 87            // fake forward indicator in the plain text body
 88            and (
 89              regex.contains(body.plain.raw,
 90                             'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
 91              )
 92              or strings.icontains(body.plain.raw, 'Original Message')
 93            )
 94            and not regex.contains(body.current_thread.text,
 95                                   'On (Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday).{0,50} wrote'
 96            )
 97            and not strings.icontains(body.current_thread.text,
 98                                      'Original Message'
 99            )
100            and not any(headers.hops, any(.fields, .name == "Resent-From"))
101          )
102        )
103        and strings.ilike(body.plain.raw,
104                          "*picture*",
105                          "*photo*",
106                          "*image*",
107                          "*sad news*",
108                          "*sad announcement*",
109                          "*sad update*",
110                          "*pics*"
111        )
112        and not strings.istarts_with(body.plain.raw, "[cid:image")
113        and strings.icontains(subject.subject, sender.display_name)
114      )
115      or (
116        strings.icontains(subject.subject, sender.display_name)
117        and sender.email.domain.root_domain in $free_email_providers
118        and length(body.links) == 2
119        and length(filter(body.links, .display_text == "h")) == 1
120        and length(filter(body.links, .display_url.scheme == "ttp")) == 1
121      )
122    )
123    and length(body.links) < 5
124    and any(body.links,
125            (
126              (
127                network.whois(.href_url.domain).days_old < 30
128                or not network.whois(.href_url.domain).found
129                or network.whois(.href_url.domain).found is null
130              )
131              and .href_url.domain.root_domain != sender.email.domain.root_domain
132            )
133            or (
134              length(.display_text) == 1
135              and .href_url.domain.root_domain in ("facebook.com", "youtube.com")
136            )
137            or (
138              // random 5-character subdomain
139              regex.icontains(.href_url.domain.domain,
140                              '^[a-z]{5}\.[a-z]{5,}\.[a-z]+'
141              )
142              // subdomain contains 3+ consecutive consonants
143              and regex.icontains(.href_url.domain.domain,
144                                  '^[a-z]*[b-df-hj-np-tv-z]{3,}[a-z]*\.'
145              )
146              and network.whois(.href_url.domain).days_old < 365
147            )
148    )
149  )
150  and (
151    (
152      (length(headers.references) > 0 or headers.in_reply_to is null)
153      and not (
154        (
155          strings.istarts_with(subject.subject, "RE:")
156          or strings.istarts_with(subject.subject, "R:")
157          or strings.istarts_with(subject.subject, "ODG:")
158          or strings.istarts_with(subject.subject, "答复:")
159          or strings.istarts_with(subject.subject, "AW:")
160          or strings.istarts_with(subject.subject, "TR:")
161          or strings.istarts_with(subject.subject, "FWD:")
162          or regex.imatch(subject.subject, '(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:')
163        )
164      )
165    )
166    or length(headers.references) == 0
167  )
168  // negate highly trusted sender domains unless they fail DMARC authentication
169  and (
170    (
171      sender.email.domain.root_domain in $high_trust_sender_root_domains
172      and not headers.auth_summary.dmarc.pass
173    )
174    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
175  )  
176attack_types:
177  - "Spam"
178tactics_and_techniques:
179  - "Evasion"
180  - "Social engineering"
181detection_methods:
182  - "Content analysis"
183  - "Sender analysis"
184  - "URL analysis"
185  - "Whois"
186id: "eb086f7d-3ad7-52cd-8e16-3ce08726b9ea"
to-top