Callback phishing via SignFree e-signature request

This rule inspects messages originating from legitimate SignFree infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.

Sublime rule (View on GitHub)

  1name: "Callback phishing via SignFree e-signature request"
  2description: "This rule inspects messages originating from legitimate SignFree infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number."
  3type: "rule"
  4severity: "high"
  5source: |
  6  type.inbound
  7  and length(attachments) == 0
  8  and (
  9    not beta.profile.by_reply_to().solicited
 10    or (
 11      beta.profile.by_reply_to().any_messages_malicious_or_spam
 12      and not beta.profile.by_reply_to().any_messages_benign
 13    )
 14  )
 15  // Legitimate SignFree sending infratructure
 16  and sender.email.domain.root_domain == 'signfree.io'
 17  and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
 18  and (
 19    // this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
 20    regex.icontains(strings.replace_confusables(body.current_thread.text),
 21                    '(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)'
 22    )
 23    or any(ml.logo_detect(file.message_screenshot()).brands,
 24           .name in (
 25             "PayPal",
 26             "Norton",
 27             "GeekSquad",
 28             "Ebay",
 29             "McAfee",
 30             "AT&T",
 31             "Microsoft"
 32           )
 33    )
 34  )
 35  and (
 36    (
 37      // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
 38      // however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
 39      // caused by messages which mention cancelling or otherwise managing a subscription
 40      // it is also synced and below for message_screenshot OCR output
 41      3 of (
 42        strings.icontains(body.current_thread.text, 'purchase'),
 43        strings.icontains(body.current_thread.text, 'payment'),
 44        strings.icontains(body.current_thread.text, 'transaction'),
 45        strings.icontains(body.current_thread.text, 'subscription'),
 46        strings.icontains(body.current_thread.text, 'antivirus'),
 47        strings.icontains(body.current_thread.text, 'order'),
 48        strings.icontains(body.current_thread.text, 'support'),
 49        strings.icontains(body.current_thread.text, 'help line'),
 50        strings.icontains(body.current_thread.text, 'receipt'),
 51        strings.icontains(body.current_thread.text, 'invoice'),
 52        strings.icontains(body.current_thread.text, 'call'),
 53        strings.icontains(body.current_thread.text, 'cancel'),
 54        strings.icontains(body.current_thread.text, 'renew'),
 55        strings.icontains(body.current_thread.text, 'refund'),
 56        regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
 57        strings.icontains(body.current_thread.text, "+1"),
 58        strings.icontains(body.current_thread.text, "amount"),
 59        strings.icontains(body.current_thread.text, "charged"),
 60        strings.icontains(body.current_thread.text, "crypto"),
 61        strings.icontains(body.current_thread.text, "wallet address"),
 62        regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
 63      )
 64      // phone number regex
 65      and regex.icontains(body.current_thread.text,
 66                          '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
 67                          '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
 68      )
 69    )
 70    or (
 71      // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
 72      // and above for current_thread.text
 73      //
 74      // This rule makes use of a beta feature and is subject to change without notice
 75      // using the beta feature in custom rules is not suggested until it has been formally released
 76      //
 77      3 of (
 78        strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
 79        strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
 80        strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
 81        strings.icontains(beta.ocr(file.message_screenshot()).text,
 82                          'subscription'
 83        ),
 84        strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
 85        strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
 86        strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
 87        strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
 88        strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
 89        strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
 90        strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
 91        strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
 92        strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
 93        strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
 94        strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
 95        regex.icontains(beta.ocr(file.message_screenshot()).text,
 96                        "(?:reach|contact) us at"
 97        ),
 98        strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
 99        strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
100        strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
101        strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
102        strings.icontains(beta.ocr(file.message_screenshot()).text,
103                          'wallet address'
104        ),
105        regex.icontains(beta.ocr(file.message_screenshot()).text,
106                        '\$\d{3}\.\d{2}\b'
107        ),
108      )
109      // phone number regex
110      and regex.icontains(beta.ocr(file.message_screenshot()).text,
111                          '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
112                          '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
113      )
114  
115      // negate messages with previous threads.  While callback phishing with thread hijacking or with current_thread 
116      // padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
117      and not regex.icount(beta.ocr(file.message_screenshot()).text,
118                           '(?:from|to|sent|date|cc|subject):'
119      ) > 3
120      // this notation of previous threads often only occurs once
121      and not regex.icontains(beta.ocr(file.message_screenshot()).text,
122                              'wrote:[\r\n]'
123      )
124    )
125  )  
126attack_types:
127  - "Callback Phishing"
128tactics_and_techniques:
129  - "Exploit"
130  - "Impersonation: Brand"
131  - "Out of band pivot"
132  - "Social engineering"
133detection_methods:
134  - "Computer Vision"
135  - "Content analysis"
136  - "Header analysis"
137  - "Sender analysis"
138  - "URL analysis"
139id: "21381c37-ecc7-5c3c-b7ab-87e936f4b048"
to-top