Callback phishing via Xodo Sign comment
This rule inspects messages originating from legitimate Xodo Sign 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 Xodo Sign comment"
2description: "This rule inspects messages originating from legitimate Xodo Sign 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 profile.by_sender().solicited
10 or (
11 profile.by_sender().any_messages_malicious_or_spam
12 and not profile.by_sender().any_messages_benign
13 )
14 )
15 // Legitimate Xodo Sign/Eversign sending infratructure
16 and sender.email.domain.root_domain == 'eversign.com'
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 ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T")
25 )
26 )
27 and length(body.current_thread.text) < 1750
28 and (
29 (
30 // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
31 // however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
32 // caused by messages which mention cancelling or otherwise managing a subscription
33 // it is also synced and below for message_screenshot OCR output
34 3 of (
35 strings.icontains(body.current_thread.text, 'purchase'),
36 strings.icontains(body.current_thread.text, 'payment'),
37 strings.icontains(body.current_thread.text, 'transaction'),
38 strings.icontains(body.current_thread.text, 'subscription'),
39 strings.icontains(body.current_thread.text, 'antivirus'),
40 strings.icontains(body.current_thread.text, 'order'),
41 strings.icontains(body.current_thread.text, 'support'),
42 strings.icontains(body.current_thread.text, 'help line'),
43 strings.icontains(body.current_thread.text, 'receipt'),
44 strings.icontains(body.current_thread.text, 'invoice'),
45 strings.icontains(body.current_thread.text, 'call'),
46 strings.icontains(body.current_thread.text, 'cancel'),
47 strings.icontains(body.current_thread.text, 'renew'),
48 strings.icontains(body.current_thread.text, 'refund'),
49 regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
50 strings.icontains(body.current_thread.text, "+1"),
51 strings.icontains(body.current_thread.text, "amount"),
52 strings.icontains(body.current_thread.text, "charged"),
53 strings.icontains(body.current_thread.text, "crypto"),
54 strings.icontains(body.current_thread.text, "wallet address"),
55 regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
56 )
57 // phone number regex
58 and regex.icontains(body.current_thread.text,
59 '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
60 '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
61 )
62 )
63 or (
64 // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
65 // and above for current_thread.text
66 //
67 // This rule makes use of a beta feature and is subject to change without notice
68 // using the beta feature in custom rules is not suggested until it has been formally released
69 //
70 3 of (
71 strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
72 strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
73 strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
74 strings.icontains(beta.ocr(file.message_screenshot()).text,
75 'subscription'
76 ),
77 strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
78 strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
79 strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
80 strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
81 strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
82 strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
83 strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
84 strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
85 strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
86 strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
87 strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
88 regex.icontains(beta.ocr(file.message_screenshot()).text,
89 "(?:reach|contact) us at"
90 ),
91 strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
92 strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
93 strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
94 strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
95 strings.icontains(beta.ocr(file.message_screenshot()).text,
96 'wallet address'
97 ),
98 regex.icontains(beta.ocr(file.message_screenshot()).text,
99 '\$\d{3}\.\d{2}\b'
100 ),
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,
111 '(?:from|to|sent|date|cc|subject):'
112 ) > 3
113 // this notation of previous threads often only occurs once
114 and not regex.icontains(beta.ocr(file.message_screenshot()).text,
115 'wrote:[\r\n]'
116 )
117 )
118 )
119attack_types:
120 - "Callback Phishing"
121tactics_and_techniques:
122 - "Exploit"
123 - "Impersonation: Brand"
124 - "Out of band pivot"
125 - "Social engineering"
126detection_methods:
127 - "Computer Vision"
128 - "Content analysis"
129 - "Header analysis"
130 - "Sender analysis"
131 - "URL analysis"
132id: "6f722c5d-ea4b-5fc4-9903-45a6310335e0"