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(beta.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      any(file.explode(beta.message_screenshot()),
 72          // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
 73          // and above for current_thread.text
 74          3 of (
 75            strings.icontains(.scan.ocr.raw, 'purchase'),
 76            strings.icontains(.scan.ocr.raw, 'payment'),
 77            strings.icontains(.scan.ocr.raw, 'transaction'),
 78            strings.icontains(.scan.ocr.raw, 'subscription'),
 79            strings.icontains(.scan.ocr.raw, 'antivirus'),
 80            strings.icontains(.scan.ocr.raw, 'order'),
 81            strings.icontains(.scan.ocr.raw, 'support'),
 82            strings.icontains(.scan.ocr.raw, 'help line'),
 83            strings.icontains(.scan.ocr.raw, 'receipt'),
 84            strings.icontains(.scan.ocr.raw, 'invoice'),
 85            strings.icontains(.scan.ocr.raw, 'call'),
 86            strings.icontains(.scan.ocr.raw, 'helpdesk'),
 87            strings.icontains(.scan.ocr.raw, 'cancel'),
 88            strings.icontains(.scan.ocr.raw, 'renew'),
 89            strings.icontains(.scan.ocr.raw, 'refund'),
 90            regex.icontains(.scan.ocr.raw, "(?:reach|contact) us at"),
 91            strings.icontains(.scan.ocr.raw, '+1'),
 92            strings.icontains(.scan.ocr.raw, 'amount'),
 93            strings.icontains(.scan.ocr.raw, 'charged'),
 94            strings.icontains(.scan.ocr.raw, 'crypto'),
 95            strings.icontains(.scan.ocr.raw, 'wallet address'),
 96            regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
 97          )
 98          // phone number regex
 99          and regex.icontains(.scan.ocr.raw,
100                              '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
101                              '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
102          )
103  
104          // negate messages with previous threads.  While callback phishing with thread hijacking or with current_thread 
105          // padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
106          and not regex.icount(.scan.ocr.raw, '(?:from|to|sent|date|cc|subject):') > 3
107          // this notation of previous threads often only occurs once
108          and not regex.icontains(.scan.ocr.raw, 'wrote:[\r\n]')
109      )
110    )
111  )  
112
113attack_types:
114  - "Callback Phishing"
115tactics_and_techniques:
116  - "Exploit"
117  - "Impersonation: Brand"
118  - "Out of band pivot"
119  - "Social engineering"
120detection_methods:
121  - "Computer Vision"
122  - "Content analysis"
123  - "Header analysis"
124  - "Sender analysis"
125  - "URL analysis"
126id: "21381c37-ecc7-5c3c-b7ab-87e936f4b048"
to-top