Callback Phishing via Signable E-Signature Request
This rule inspects messages originating from legitimate Signable 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 Signable E-Signature Request"
2description: "This rule inspects messages originating from legitimate Signable 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 Signable sending infratructure
16 and sender.email.domain.root_domain == 'signable.app'
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 length(body.current_thread.text) < 1750
36 and (
37 (
38 // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
39 // however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
40 // caused by messages which mention cancelling or otherwise managing a subscription
41 // it is also synced and below for message_screenshot OCR output
42 3 of (
43 strings.icontains(body.current_thread.text, 'purchase'),
44 strings.icontains(body.current_thread.text, 'payment'),
45 strings.icontains(body.current_thread.text, 'transaction'),
46 strings.icontains(body.current_thread.text, 'subscription'),
47 strings.icontains(body.current_thread.text, 'antivirus'),
48 strings.icontains(body.current_thread.text, 'order'),
49 strings.icontains(body.current_thread.text, 'support'),
50 strings.icontains(body.current_thread.text, 'help line'),
51 strings.icontains(body.current_thread.text, 'receipt'),
52 strings.icontains(body.current_thread.text, 'invoice'),
53 strings.icontains(body.current_thread.text, 'call'),
54 strings.icontains(body.current_thread.text, 'cancel'),
55 strings.icontains(body.current_thread.text, 'renew'),
56 strings.icontains(body.current_thread.text, 'refund'),
57 regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
58 strings.icontains(body.current_thread.text, "+1"),
59 strings.icontains(body.current_thread.text, "amount"),
60 strings.icontains(body.current_thread.text, "charged"),
61 strings.icontains(body.current_thread.text, "crypto"),
62 strings.icontains(body.current_thread.text, "wallet address"),
63 regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
64 )
65 // phone number regex
66 and regex.icontains(body.current_thread.text,
67 '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
68 '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
69 )
70 )
71 or (
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 //
75 // This rule makes use of a beta feature and is subject to change without notice
76 // using the beta feature in custom rules is not suggested until it has been formally released
77 //
78 3 of (
79 strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
80 strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
81 strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
82 strings.icontains(beta.ocr(file.message_screenshot()).text, 'subscription'),
83 strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
84 strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
85 strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
86 strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
87 strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
88 strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
89 strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
90 strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
91 strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
92 strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
93 strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
94 regex.icontains(beta.ocr(file.message_screenshot()).text, "(?:reach|contact) us at"),
95 strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
96 strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
97 strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
98 strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
99 strings.icontains(beta.ocr(file.message_screenshot()).text, 'wallet address'),
100 regex.icontains(beta.ocr(file.message_screenshot()).text, '\$\d{3}\.\d{2}\b'),
101 )
102 // phone number regex
103 and regex.icontains(beta.ocr(file.message_screenshot()).text,
104 '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
105 '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
106 )
107
108 // negate messages with previous threads. While callback phishing with thread hijacking or with current_thread
109 // padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
110 and not regex.icount(beta.ocr(file.message_screenshot()).text, '(?:from|to|sent|date|cc|subject):') > 3
111 // this notation of previous threads often only occurs once
112 and not regex.icontains(beta.ocr(file.message_screenshot()).text, 'wrote:[\r\n]')
113 )
114 )
115attack_types:
116 - "Callback Phishing"
117tactics_and_techniques:
118 - "Exploit"
119 - "Impersonation: Brand"
120 - "Out of band pivot"
121 - "Social engineering"
122detection_methods:
123 - "Computer Vision"
124 - "Content analysis"
125 - "Header analysis"
126 - "Sender analysis"
127 - "URL analysis"
128id: "4599575d-6dd7-5785-bad9-4902eeff4e1b"