Attachment: QR code with credential phishing indicators
Detects messages with between 1-3 attachments containing a QR code with suspicious credential theft indicators, such as: LinkAnalysis credential phishing conclusion, decoded QR code url traverses suspicious infrastructure, the final destination is in URLhaus, decoded URL downloads a zip or executable, leverages URL shorteners, known QR abused openredirects, and more.
Sublime rule (View on GitHub)
1name: "Attachment: QR code with credential phishing indicators"
2description: |
3 Detects messages with between 1-3 attachments containing a QR code with suspicious credential theft indicators, such as: LinkAnalysis credential phishing conclusion, decoded QR code url traverses suspicious infrastructure, the final destination is in URLhaus, decoded URL downloads a zip or executable, leverages URL shorteners, known QR abused openredirects, and more.
4type: "rule"
5severity: "medium"
6source: |
7 type.inbound
8 and (
9 1 <= length(attachments) < 3
10 or (
11 // if there are more than three attachments
12 3 <= length(attachments) < 20
13 // there are only pngs and pdf/docx
14 and length(distinct(map(attachments, .file_extension))) == 2
15 and all(distinct(map(attachments, .file_extension)),
16 . in ('png', 'pdf', 'docx')
17 )
18 and (
19 // multiple attachments mention common brands or other common common filenames
20 (
21 length(filter(attachments,
22 strings.icontains(.file_name, 'adobe')
23 or strings.icontains(.file_name, 'office')
24 or strings.icontains(.file_name, 'appstore')
25 or strings.icontains(.file_name, 'google')
26 or strings.icontains(.file_name, 'padlock')
27 or regex.icontains(.file_name, '\bdoc\b')
28 )
29 ) > 3
30 )
31 // the attachment name contains the SLD of a recipient
32 or any(filter(attachments, .file_extension in ('pdf', 'docx')),
33 any(filter(recipients.to, .email.domain.valid),
34 strings.icontains(..file_name, .email.domain.sld)
35 )
36 )
37 )
38 )
39 )
40
41 // Inspects image attachments for QR codes
42 and any(attachments,
43 (
44 .file_type in $file_types_images
45 or .file_type == "pdf"
46 or .file_extension in $file_extensions_macros
47 )
48 and (
49 any(file.explode(.),
50 .scan.qr.type == "url"
51 and not .scan.qr.url.domain.domain == "geico.app.link"
52 and (
53 // pass the QR URL to LinkAnalysis
54 any([ml.link_analysis(.scan.qr.url)],
55 .credphish.disposition == "phishing"
56
57 // any routing traverses via $suspicious_tld list
58 or any(.redirect_history, .domain.tld in $suspicious_tlds)
59
60 // effective destination in $suspicious_tld list
61 or .effective_url.domain.tld in $suspicious_tlds
62
63 // or the effective destination domain is in $abuse_ch_urlhaus_domains_trusted_reporters
64 or .effective_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters
65
66 // or any files downloaded are zips or executables
67 or any(.files_downloaded,
68 .file_extension in $file_extensions_common_archives
69 or .file_extension in $file_extensions_executables
70 )
71 )
72 or (
73
74 // or the QR code's root domain is a url_shortener
75 .scan.qr.url.domain.root_domain in $url_shorteners
76 or (
77 .scan.qr.url.domain.root_domain in $social_landing_hosts
78 and (
79 not (
80 any(ml.nlu_classifier(body.current_thread.text).intents,
81 .name == "benign"
82 )
83 or any(ml.nlu_classifier(body.current_thread.text).entities,
84 .name == "disclaimer"
85 )
86 )
87 or not any(attachments,
88 any(file.explode(.),
89 any(ml.nlu_classifier(.scan.ocr.raw).intents,
90 .name == "benign"
91 )
92 )
93 )
94 // the QR code contains the email address of a recipient
95 or (
96 any(filter(recipients.to, .email.domain.valid),
97 strings.icontains(..scan.qr.url.url, .email.email)
98 )
99 )
100 )
101
102 // exclude google maps
103 and not strings.starts_with(.scan.qr.url.url,
104 'https://goo.gl/maps'
105 )
106 and not strings.starts_with(.scan.qr.url.url,
107 'https://maps.app.goo.gl'
108 )
109 )
110 )
111
112 // the QR code url is a bing open redirect
113 or (
114 .scan.qr.url.domain.root_domain == 'bing.com'
115 and .scan.qr.url.path =~ '/ck/a'
116 )
117 // QR code contains non ascii chars
118 or regex.contains(.scan.qr.url.url, '[^\x00-\x7F]')
119 or (
120 (
121 // usap-dc open redirect
122 .scan.qr.url.domain.root_domain == "usap-dc.org"
123 and .scan.qr.url.path =~ "/tracker"
124 and strings.starts_with(.scan.qr.url.query_params,
125 "type=dataset&url=http"
126 )
127 )
128 // the QR code contains the email address of a recipient
129 // allowing for base64 encoded variants
130 or (
131 any(filter(recipients.to, .email.domain.valid),
132 strings.icontains(..scan.qr.url.url, .email.email)
133 or any(strings.scan_base64(..scan.qr.url.url,
134 ignore_padding=true
135 ),
136 strings.icontains(., ..email.email)
137 )
138 or any(strings.scan_base64(..scan.qr.url.fragment,
139 ignore_padding=true
140 ),
141 strings.icontains(., ..email.email)
142 )
143 )
144 )
145 )
146 )
147 )
148 )
149 )
150 and (
151 (
152 profile.by_sender_email().prevalence in ("new", "outlier")
153 and not profile.by_sender_email().solicited
154 )
155 or (
156 profile.by_sender_email().any_messages_malicious_or_spam
157 and not profile.by_sender_email().any_messages_benign
158 )
159 or (
160 sender.email.domain.domain in $org_domains
161 and not coalesce(headers.auth_summary.dmarc.pass, false)
162 )
163 )
164
165 // negate highly trusted sender domains unless they fail DMARC authentication
166 and (
167 (
168 sender.email.domain.root_domain in $high_trust_sender_root_domains
169 and not headers.auth_summary.dmarc.pass
170 )
171 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
172 )
173attack_types:
174 - "Credential Phishing"
175tactics_and_techniques:
176 - "QR code"
177 - "Social engineering"
178detection_methods:
179 - "Computer Vision"
180 - "Header analysis"
181 - "Natural Language Understanding"
182 - "QR code analysis"
183 - "Sender analysis"
184 - "URL analysis"
185 - "URL screenshot"
186id: "9f1681e1-8c15-5edd-9aaa-eb5af1729322"