Detection rules › Sublime MQL

Extortion / sextortion in attachment from untrusted sender

Severity
low
Type
rule
Source
github.com/sublime-security/sublime-rules

Detects extortion and sextortion attempts by analyzing attachment text from an untrusted sender.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesExtortion
Tactics and techniquesSocial engineering, Spoofing

Event coverage

Rule body MQL

type.inbound
and length(attachments) < 2
and (
  length(body.current_thread.text) < 500
  or (
    length(ml.nlu_classifier(body.current_thread.text).intents) > 0
    and any(ml.nlu_classifier(body.current_thread.text).intents,
            .name != "benign"
    )
  )
)
and any(attachments,
        // use ocr output from file.explode on pdfs/images
        (
          (.file_type in $file_types_images or .file_type == "pdf")
          and any(filter(file.explode(.), .scan.ocr.raw is not null),
                  (
                    any(ml.nlu_classifier(.scan.ocr.raw).intents,
                        .name == "extortion" and .confidence == "high"
                    )
                    and any(ml.nlu_classifier(.scan.ocr.raw).entities,
                            .name == "financial"
                    )
                  )
                  or 3 of (
                    // malware terms
                    regex.icontains(.scan.ocr.raw,
                                    "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))"
                    ),
                    // actions recorded
                    regex.icontains(.scan.ocr.raw,
                                    "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off"
                    ),
                    regex.icontains(.scan.ocr.raw,
                                    "pervert|perversion|masturbat"
                    ),
                    // a timeframe to pay
                    regex.icontains(.scan.ocr.raw,
                                    '\d\d hours',
                                    '(?:one|two|three) days?'
                    ),
                    // a promise from the actor
                    regex.icontains(.scan.ocr.raw,
                                    'permanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)'
                    ),
                    // a threat from the actor
                    regex.icontains(.scan.ocr.raw,
                                    'sen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)'
                    ),
                    // bitcoin
                    (
                      regex.icontains(.scan.ocr.raw,
                                      'bitcoin|\bbtc\b|blockchain'
                      )
                      // negate cryptocurrency newsletters
                      and not (
                        any(body.links,
                            strings.icontains(.display_text, "unsubscribe")
                            and (
                              strings.icontains(.href_url.path, "unsubscribe")
                              // handle mimecast URL rewrites
                              or (
                                .href_url.domain.root_domain == 'mimecastprotect.com'
                                and strings.icontains(.href_url.query_params,
                                                      sender.email.domain.root_domain
                                )
                              )
                            )
                        )
                      )
                    ),
                    // bitcoin wallet address + threat
                    (
                      strings.icontains(.scan.ocr.raw, "contact the police")
                      and regex.icontains(.scan.ocr.raw,
                                          '(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\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'
                      )
                    ),
                    regex.icontains(.scan.ocr.raw, 'bc1q.{0,50}\b')
                  )
          )
        )
        or 
        // use beta.parse_text on plain text files
        (
          (
            .file_extension in ("txt")
            and (
              (
                any(ml.nlu_classifier(file.parse_text(.).text).intents,
                    .name == "extortion" and .confidence == "high"
                )
                and any(ml.nlu_classifier(file.parse_text(.).text).entities,
                        .name == "financial"
                )
              )
              or 3 of (
                // malware terms
                regex.icontains(beta.parse_text(.).text,
                                "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))"
                ),
                // actions recorded
                regex.icontains(beta.parse_text(.).text,
                                "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off"
                ),
                regex.icontains(beta.parse_text(.).text,
                                "pervert|perversion|masturbat"
                ),
                // a timeframe to pay
                regex.icontains(beta.parse_text(.).text,
                                '\d\d hours',
                                '(?:one|two|three) days?'
                ),
                // a promise from the actor
                regex.icontains(beta.parse_text(.).text,
                                'permanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)'
                ),
                // a threat from the actor
                regex.icontains(beta.parse_text(.).text,
                                'sen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)'
                ),
                // bitcoin
                (
                  regex.icontains(beta.parse_text(.).text,
                                  'bitcoin|\bbtc\b|blockchain'
                  )
                  // negate cryptocurrency newsletters
                  and not (
                    any(body.links,
                        strings.icontains(.display_text, "unsubscribe")
                        and (
                          strings.icontains(.href_url.path, "unsubscribe")
                          // handle mimecast URL rewrites
                          or (
                            .href_url.domain.root_domain == 'mimecastprotect.com'
                            and strings.icontains(.href_url.query_params,
                                                  sender.email.domain.root_domain
                            )
                          )
                        )
                    )
                  )
                ),
                // bitcoin wallet address + threat
                (
                  strings.icontains(beta.parse_text(.).text,
                                    "contact the police"
                  )
                  and regex.icontains(beta.parse_text(.).text,
                                      '(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\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'
                  )
                ),
                regex.icontains(beta.parse_text(.).text, 'bc1q.{0,50}\b')
              )
            )
          )
        )
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
  or any(headers.hops, any(.fields, .name == "X-Google-Group-Id"))

  // many extortion emails spoof sender domains and fail sender authentication
  or any(headers.hops,
         .authentication_results.dmarc == "fail"
         or .authentication_results.compauth.verdict not in ("pass", "softpass")
  )
)

Detection logic

Scope: inbound message.

Detects extortion and sextortion attempts by analyzing attachment text from an untrusted sender.

  1. inbound message
  2. length(attachments) < 2
  3. any of:
    • length(body.current_thread.text) < 500
    • all of:
      • length(ml.nlu_classifier(body.current_thread.text).intents) > 0
      • any of ml.nlu_classifier(body.current_thread.text).intents where:
        • .name is not 'benign'
  4. any of attachments where any holds:
    • all of:
      • any of:
        • .file_type in $file_types_images
        • .file_type is 'pdf'
      • any of filter(...) where any holds:
        • all of:
          • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
            • .name is 'extortion'
            • .confidence is 'high'
          • any of ml.nlu_classifier(.scan.ocr.raw).entities where:
            • .name is 'financial'
        • at least 3 of:
          • .scan.ocr.raw matches '((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))'
          • .scan.ocr.raw matches 'porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off'
          • .scan.ocr.raw matches 'pervert|perversion|masturbat'
          • .scan.ocr.raw matches any of 2 patterns
            • \d\d hours
            • (?:one|two|three) days?
          • .scan.ocr.raw matches 'permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)'
          • .scan.ocr.raw matches 'sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)'
          • all of:
            • .scan.ocr.raw matches 'bitcoin|\\bbtc\\b|blockchain'
            • not:
              • any of body.links where all hold:
                • .display_text contains 'unsubscribe'
                • any of:
                  • .href_url.path contains 'unsubscribe'
                  • all of:
                    • .href_url.domain.root_domain is 'mimecastprotect.com'
                    • strings.icontains(.href_url.query_params)
          • all of:
            • .scan.ocr.raw contains 'contact the police'
            • .scan.ocr.raw matches '(\\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\\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'
          • .scan.ocr.raw matches 'bc1q.{0,50}\\b'
    • all of:
      • .file_extension in ('txt')
      • any of:
        • all of:
          • any of ml.nlu_classifier(file.parse_text(.).text).intents where all hold:
            • .name is 'extortion'
            • .confidence is 'high'
          • any of ml.nlu_classifier(file.parse_text(.).text).entities where:
            • .name is 'financial'
        • at least 3 of:
          • beta.parse_text(.).text matches '((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))'
          • beta.parse_text(.).text matches 'porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off'
          • beta.parse_text(.).text matches 'pervert|perversion|masturbat'
          • beta.parse_text(.).text matches any of 2 patterns
            • \d\d hours
            • (?:one|two|three) days?
          • beta.parse_text(.).text matches 'permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)'
          • beta.parse_text(.).text matches 'sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)'
          • all of:
            • beta.parse_text(.).text matches 'bitcoin|\\bbtc\\b|blockchain'
            • not:
              • any of body.links where all hold:
                • .display_text contains 'unsubscribe'
                • any of:
                  • .href_url.path contains 'unsubscribe'
                  • all of:
                    • .href_url.domain.root_domain is 'mimecastprotect.com'
                    • strings.icontains(.href_url.query_params)
          • all of:
            • beta.parse_text(.).text contains 'contact the police'
            • beta.parse_text(.).text matches '(\\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\\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'
          • beta.parse_text(.).text matches 'bc1q.{0,50}\\b'
  5. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
    • any of headers.hops where:
      • any of .fields where:
        • .name is 'X-Google-Group-Id'
    • any of headers.hops where any holds:
      • .authentication_results.dmarc is 'fail'
      • .authentication_results.compauth.verdict not in ('pass', 'softpass')

Inspects: attachments[].file_extension, attachments[].file_type, body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.root_domain, body.links[].href_url.path, body.links[].href_url.query_params, headers.hops, headers.hops[].authentication_results.compauth.verdict, headers.hops[].authentication_results.dmarc, headers.hops[].fields, headers.hops[].fields[].name, sender.email.domain.root_domain, type.inbound. Sensors: beta.parse_text, file.explode, file.parse_text, ml.nlu_classifier, profile.by_sender, regex.icontains, strings.icontains. Reference lists: $file_types_images.

Indicators matched (25)

FieldMatchValue
attachments[].file_typeequalspdf
ml.nlu_classifier(filter(...)[].scan.ocr.raw).intents[].nameequalsextortion
ml.nlu_classifier(filter(...)[].scan.ocr.raw).intents[].confidenceequalshigh
ml.nlu_classifier(filter(...)[].scan.ocr.raw).entities[].nameequalsfinancial
regex.icontainsregex((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))
regex.icontainsregexporn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off
regex.icontainsregexpervert|perversion|masturbat
regex.icontainsregex\d\d hours
regex.icontainsregex(?:one|two|three) days?
regex.icontainsregexpermanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)
regex.icontainsregexsen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)
regex.icontainsregexbitcoin|\bbtc\b|blockchain
13 more
strings.icontainssubstringunsubscribe
body.links[].href_url.domain.root_domainequalsmimecastprotect.com
strings.icontainssubstringcontact the police
regex.icontainsregex(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\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
regex.icontainsregexbc1q.{0,50}\b
attachments[].file_extensionmembertxt
ml.nlu_classifier(file.parse_text(attachments[]).text).intents[].nameequalsextortion
ml.nlu_classifier(file.parse_text(attachments[]).text).intents[].confidenceequalshigh
ml.nlu_classifier(file.parse_text(attachments[]).text).entities[].nameequalsfinancial
headers.hops[].fields[].nameequalsX-Google-Group-Id
headers.hops[].authentication_results.dmarcequalsfail
headers.hops[].authentication_results.compauth.verdictmemberpass
headers.hops[].authentication_results.compauth.verdictmembersoftpass