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