Callback phishing solicitation in message body

A fraudulent invoice/receipt found in the body of the message. Callback phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.

Sublime rule (View on GitHub)

  1name: "Callback phishing solicitation in message body"
  2description: |
  3  A fraudulent invoice/receipt found in the body of the message.
  4  Callback phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. 
  5  The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.  
  6type: "rule"
  7severity: "medium"
  8source: |
  9  type.inbound
 10  and length(attachments) == 0
 11  and (
 12    not profile.by_sender().solicited
 13    or (
 14      profile.by_sender().any_messages_malicious_or_spam
 15      and not profile.by_sender().any_messages_benign
 16    )
 17  )
 18  and (
 19    sender.email.domain.root_domain in $free_email_providers
 20    or sender.email.domain.tld in $suspicious_tlds
 21    or network.whois(sender.email.domain).found == false
 22    or headers.mailer in~ ("Microsoft CDO for Windows 2000")
 23    or (
 24      length(recipients.to) == 1
 25      and all(recipients.to, .email.domain.domain not in $org_domains)
 26    )
 27  )
 28  and (
 29    // this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
 30    regex.icontains(body.current_thread.text,
 31                    '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
 32    )
 33    or any(ml.logo_detect(file.message_screenshot()).brands,
 34           .name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T")
 35    )
 36    //
 37    // This rule makes use of a beta feature and is subject to change without notice
 38    // using the beta feature in custom rules is not suggested until it has been formally released
 39    //
 40    or regex.icontains(beta.ocr(file.message_screenshot()).text,
 41                       '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
 42    )
 43  )
 44  and length(body.current_thread.text) < 1750
 45  and (
 46    (
 47      // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
 48      // however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
 49      // caused by messages which mention cancelling or otherwise managing a subscription
 50      // it is also synced and below for message_screenshot OCR output
 51      3 of (
 52        strings.icontains(body.current_thread.text, 'purchase'),
 53        strings.icontains(body.current_thread.text, 'payment'),
 54        strings.icontains(body.current_thread.text, 'transaction'),
 55        strings.icontains(body.current_thread.text, 'subscription'),
 56        strings.icontains(body.current_thread.text, 'antivirus'),
 57        strings.icontains(body.current_thread.text, 'order'),
 58        strings.icontains(body.current_thread.text, 'support'),
 59        strings.icontains(body.current_thread.text, 'help line'),
 60        strings.icontains(body.current_thread.text, 'receipt'),
 61        strings.icontains(body.current_thread.text, 'invoice'),
 62        strings.icontains(body.current_thread.text, 'call'),
 63        strings.icontains(body.current_thread.text, 'cancel'),
 64        strings.icontains(body.current_thread.text, 'renew'),
 65        strings.icontains(body.current_thread.text, 'refund'),
 66        regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
 67        strings.icontains(body.current_thread.text, "+1"),
 68        strings.icontains(body.current_thread.text, "amount"),
 69        strings.icontains(body.current_thread.text, "charged"),
 70        strings.icontains(body.current_thread.text, "crypto"),
 71        strings.icontains(body.current_thread.text, "wallet address"),
 72        regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
 73      )
 74      // phone number regex
 75      and regex.icontains(body.current_thread.text,
 76                          '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
 77                          '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
 78      )
 79    )
 80    or (
 81      any(file.explode(file.message_screenshot()),
 82          // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
 83          // and above for current_thread.text
 84          3 of (
 85            strings.icontains(.scan.ocr.raw, 'purchase'),
 86            strings.icontains(.scan.ocr.raw, 'payment'),
 87            strings.icontains(.scan.ocr.raw, 'transaction'),
 88            strings.icontains(.scan.ocr.raw, 'subscription'),
 89            strings.icontains(.scan.ocr.raw, 'antivirus'),
 90            strings.icontains(.scan.ocr.raw, 'order'),
 91            strings.icontains(.scan.ocr.raw, 'support'),
 92            strings.icontains(.scan.ocr.raw, 'help line'),
 93            strings.icontains(.scan.ocr.raw, 'receipt'),
 94            strings.icontains(.scan.ocr.raw, 'invoice'),
 95            strings.icontains(.scan.ocr.raw, 'call'),
 96            strings.icontains(.scan.ocr.raw, 'helpdesk'),
 97            strings.icontains(.scan.ocr.raw, 'cancel'),
 98            strings.icontains(.scan.ocr.raw, 'renew'),
 99            strings.icontains(.scan.ocr.raw, 'refund'),
100            regex.icontains(.scan.ocr.raw, "(?:reach|contact) us at"),
101            strings.icontains(.scan.ocr.raw, '+1'),
102            strings.icontains(.scan.ocr.raw, 'amount'),
103            strings.icontains(.scan.ocr.raw, 'charged'),
104            strings.icontains(.scan.ocr.raw, 'crypto'),
105            strings.icontains(.scan.ocr.raw, 'wallet address'),
106            regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
107          )
108          // phone number regex
109          and regex.icontains(.scan.ocr.raw,
110                              '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
111                              '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
112          )
113  
114          // negate messages with previous threads.  While callback phishing with thread hijacking or with current_thread 
115          // padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
116          and not regex.icount(.scan.ocr.raw, '(?:from|to|sent|date|cc|subject):') > 3
117          // this notation of previous threads often only occurs once
118          and not regex.icontains(.scan.ocr.raw, 'wrote:[\r\n]')
119      )
120    )
121  )
122  // not high trust sender domains
123  and (
124    (
125      sender.email.domain.root_domain in $high_trust_sender_root_domains
126      and not headers.auth_summary.dmarc.pass
127    )
128    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
129  )
130  and not strings.ends_with(headers.message_id, "@shopify.com>")  
131attack_types:
132  - "Callback Phishing"
133tactics_and_techniques:
134  - "Free email provider"
135  - "Impersonation: Brand"
136  - "Out of band pivot"
137  - "Social engineering"
138detection_methods:
139  - "File analysis"
140  - "Sender analysis"
141id: "10a3a446-c70f-5843-a4e4-4d815d33fcb1"
to-top