Extortion / sextortion (untrusted sender)

Detects extortion and sextortion attempts by analyzing the email body text from an untrusted sender.

Sublime rule (View on GitHub)

  1name: "Extortion / sextortion (untrusted sender)"
  2description: |
  3    Detects extortion and sextortion attempts by analyzing the email body text from an untrusted sender.
  4references:
  5  - "https://krebsonsecurity.com/2018/07/sextortion-scam-uses-recipients-hacked-passwords/"
  6type: "rule"
  7severity: "low"
  8source: |
  9  type.inbound
 10  and length(filter(body.links, .display_text is not null)) < 10
 11  and not (
 12    ml.nlu_classifier(body.current_thread.text).language == "english"
 13    and any(ml.nlu_classifier(body.html.display_text).topics,
 14            .name in (
 15              "News and Current Events",
 16              "Newsletters and Digests",
 17              "Advertising and Promotions"
 18            )
 19            and .confidence in ("high", "medium")
 20    )
 21  )
 22  and (
 23    (
 24      any(ml.nlu_classifier(strings.replace_confusables(body.current_thread.text)).intents,
 25          (.name == "extortion" and .confidence == "high")
 26      )
 27      and (
 28        any(ml.nlu_classifier(strings.replace_confusables(body.current_thread.text
 29                              )
 30            ).entities,
 31            .name == "financial"
 32            or (
 33              .name is not null
 34              and regex.icontains(.text,
 35                                  "cybḛ[rŗřṙȑȓɍʀɼɽг]c[rŗřṙȑȓɍʀɼɽг]imina[lĺļľḷḹḽłƖʟḻ]s"
 36              )
 37            )
 38        )
 39        or any(ml.nlu_classifier(strings.replace_confusables(body.current_thread.text
 40                                 )
 41               ).topics,
 42               .name == "Financial Communications" and .confidence != "low"
 43        )
 44      )
 45    )
 46    // catches extortion content delivered as inline base64 images
 47    or (
 48      (body.current_thread.text is null or length(body.current_thread.text) < 10)
 49      and any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents,
 50              .name == "extortion" and .confidence == "high"
 51      )
 52      and (
 53        any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).entities,
 54            .name == "financial"
 55        )
 56        or any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).topics,
 57               .name == "Financial Communications" and .confidence != "low"
 58        )
 59      )
 60    )
 61    // manual indicators failsafe
 62    or 3 of (
 63      // malware terms
 64      regex.icontains(strings.replace_confusables(body.current_thread.text),
 65                      "(?:(?:spy|[mṁ][aȁḁ]l)[wŵ][aȁḁ][rŗ]e|[tŢ][rŗȓ][oốởộ]j[aǻä][nņ]|[rȓ]emote (?:entry|cont[rř]o[lĺ])|infiltrat(?:ed|ion)|backdoor|vi[rṙ]us|intruder|(?:your|the).{0,15}(?:device|system|computer|phone).{0,10}(?:became|was|got|is).{0,5}comprom[ḯiïíįī]sed|prov[ḯiïíįī]d[ḯiïíįī]ng.{0,20}full [aảǡą]ccess)"
 66      ),
 67      // actions recorded
 68      regex.icontains(strings.replace_confusables(body.current_thread.text),
 69                      "(?:p[oộ][rŗ]n|a[dȡ]ult (?:web)?site|webcam|mastu[rŗ]bating|je[rŗ]king off|pleasu[rŗȑ]i[nŋ]g you[rŗṛ]self|getting off|expli[cƈ]it|cl[ḯiïíįī]ps.{0,20}screenshots|NSFW|gr[aǻẳ]phic c[oỡở]ntent)"
 70      ),
 71      regex.icontains(strings.replace_confusables(body.current_thread.text),
 72                      "(?:pe[rŗ]ve[rŗ]t|pe[rŗ]ve[rŗ]sion|mastu[rŗ]bat)"
 73      ),
 74      // a timeframe to pay
 75      regex.icontains(strings.replace_confusables(body.current_thread.text),
 76                      '[ilo0-9]{2} (?:hou[rŗṝ][sṣ]|uu[rŗ])',
 77                      '(?:one|tw[oờȍ]|2|th[rŗ]ee|\d) [dḍ][aảǡą]y[sṣ]?',
 78                      'set a timer'
 79      ),
 80      // a promise from the actor
 81      regex.icontains(strings.replace_confusables(body.current_thread.text),
 82                      '(?:pe[rŗ]manently|will|I''ll) delete|([rŗ]emove|destroy) (?:[\p{L}\p{M}\p{N}]+\s*){0,4} (?:data|ev[ḯiïįīí]dence|v[ḯiïíįī]deos?)'
 83      ),
 84      // a threat from the actor
 85      regex.icontains(strings.replace_confusables(body.current_thread.text),
 86                      '(?:\bsen[dt]|forward|expose|share)\s*(?:[\p{L}\p{N}]+\s*){0,5}\s*to\s*(?:[\p{L}\p{N}]+\s*){0,5}(?:contacts|media|family|f[rŗ]iends|coworkers|co-workers|associates|kin\b)'
 87      ),
 88      // bitcoin language (excluding newsletters)
 89      (
 90        regex.icontains(strings.replace_confusables(body.current_thread.text),
 91                        '[bḆḂ]it[cĉƈ][oöة]i[nņɲ]|\bbtc\b|blockchain'
 92        )
 93        // negate cryptocurrency newsletters
 94        and not (
 95          any(body.links,
 96              strings.icontains(.display_text, "unsubscribe")
 97              and (
 98                strings.icontains(.href_url.path, "unsubscribe")
 99                // handle mimecast URL rewrites
100                or (
101                  .href_url.domain.root_domain == 'mimecastprotect.com'
102                  and strings.icontains(.href_url.query_params,
103                                        sender.email.domain.root_domain
104                  )
105                )
106              )
107          )
108        )
109      ),
110      (
111        regex.icontains(strings.replace_confusables(body.current_thread.text),
112                        '(?:contact the police|(?:bitcoin|\bbtc\b).{0,20}(?:wallet|address))'
113        )
114        and regex.icontains(strings.replace_confusables(body.current_thread.text),
115                            '(?:\b[13][a-km-zA-HJ-NP-Z0-9]{24,34}\b)|\bX[1-9A-HJ-NP-Za-km-z]{33}\b|\b(?:0x[a-fA-F0-9]{40})\b|\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\b|\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\b'
116        )
117      ),
118      regex.icontains(strings.replace_confusables(body.current_thread.text),
119                      'bc1q.{0,50}\b'
120      ),
121      (
122        regex.count(body.current_thread.text,
123                    '[\x{0300}-\x{036F}\x{1AB0}-\x{1AFF}\x{1DC0}-\x{1DFF}\x{0100}-\x{024F}\x{1E00}-\x{1EFF}]'
124        ) > 20
125        and length(body.current_thread.links) == 0
126      )
127    )
128  )
129  and (
130    not profile.by_sender().solicited
131    or (
132      profile.by_sender().any_messages_malicious_or_spam
133      and not profile.by_sender().any_messages_benign
134    )
135    or any(headers.hops, any(.fields, .name == "X-Google-Group-Id"))
136  
137    // many extortion emails spoof sender domains and fail sender authentication
138    or (
139      not headers.auth_summary.dmarc.pass
140      or headers.auth_summary.dmarc.pass is null
141      or not headers.auth_summary.spf.pass
142    )
143  )
144  // negate legit bounce backs
145  and not any(ml.nlu_classifier(body.current_thread.text).topics,
146              .name in ("Bounce Back and Delivery Failure Notifications")
147  )
148  // negate legit forwards and replies
149  and not (
150    (subject.is_reply or subject.is_forward)
151    and length(body.previous_threads) > 0
152    and (length(headers.references) > 0 or headers.in_reply_to is not null)
153  )
154  // negate benign newsletters that mention cyber extortion
155  and not (
156    any(body.links,
157        strings.icontains(.display_text, "unsubscribe")
158        and strings.icontains(.href_url.path, "unsubscribe")
159    )
160    // newsletters are typically longer than the average extortion script
161    and length(body.current_thread.text) > 2000
162  )
163  and length(body.current_thread.text) < 8000
164  // negate highly trusted sender domains unless they fail DMARC authentication
165  and (
166    (
167      sender.email.domain.root_domain in $high_trust_sender_root_domains
168      and not headers.auth_summary.dmarc.pass
169    )
170    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
171  )  
172
173attack_types:
174  - "Extortion"
175tactics_and_techniques:
176  - "Social engineering"
177  - "Spoofing"
178detection_methods:
179  - "Content analysis"
180  - "Header analysis"
181  - "Natural Language Understanding"
182  - "Sender analysis"
183id: "265913eb-2ccd-5f77-9a09-f6d8539fd2f6"
to-top