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 .scan.qr.url.domain.root_domain in $social_landing_hosts
77 and (
78 not (
79 any(ml.nlu_classifier(body.current_thread.text).intents,
80 .name == "benign"
81 )
82 or any(ml.nlu_classifier(body.current_thread.text).entities,
83 .name == "disclaimer"
84 )
85 )
86 or not any(attachments,
87 any(file.explode(.),
88 any(ml.nlu_classifier(.scan.ocr.raw).intents,
89 .name == "benign"
90 )
91 )
92 )
93 // the QR code contains the email address of a recipient
94 or (
95 any(filter(recipients.to, .email.domain.valid),
96 strings.icontains(..scan.qr.url.url, .email.email)
97 )
98 )
99 )
100
101 // exclude google maps
102 and not strings.starts_with(.scan.qr.url.url,
103 'https://goo.gl/maps'
104 )
105 and not strings.starts_with(.scan.qr.url.url,
106 'https://maps.app.goo.gl'
107 )
108 )
109
110 // the QR code url is a bing open redirect
111 or (
112 .scan.qr.url.domain.root_domain == 'bing.com'
113 and .scan.qr.url.path =~ '/ck/a'
114 )
115 // QR code contains non ascii chars
116 or regex.contains(.scan.qr.url.url, '[^\x00-\x7F]')
117 or (
118
119 // usap-dc open redirect
120 .scan.qr.url.domain.root_domain == "usap-dc.org"
121 and .scan.qr.url.path =~ "/tracker"
122 and strings.starts_with(.scan.qr.url.query_params,
123 "type=dataset&url=http"
124 )
125 // the QR code contains the email address of a recipient
126 // allowing for base64 encoded variants
127 or (
128 any(filter(recipients.to, .email.domain.valid),
129 strings.icontains(..scan.qr.url.url, .email.email)
130 or any(beta.scan_base64(..scan.qr.url.url,
131 ignore_padding=true
132 ),
133 strings.icontains(., ..email.email)
134 )
135 or any(beta.scan_base64(..scan.qr.url.fragment,
136 ignore_padding=true
137 ),
138 strings.icontains(., ..email.email)
139 )
140 )
141 )
142 )
143 )
144 )
145 )
146 )
147 and (
148 (
149 profile.by_sender_email().prevalence in ("new", "outlier")
150 and not profile.by_sender_email().solicited
151 )
152 or (
153 profile.by_sender_email().any_messages_malicious_or_spam
154 and not profile.by_sender_email().any_messages_benign
155 )
156 or (
157 sender.email.domain.domain in $org_domains
158 and not coalesce(headers.auth_summary.dmarc.pass, false)
159 )
160 )
161
162 // negate highly trusted sender domains unless they fail DMARC authentication
163 and (
164 (
165 sender.email.domain.root_domain in $high_trust_sender_root_domains
166 and not headers.auth_summary.dmarc.pass
167 )
168 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
169 )
170attack_types:
171 - "Credential Phishing"
172tactics_and_techniques:
173 - "QR code"
174 - "Social engineering"
175detection_methods:
176 - "Computer Vision"
177 - "Header analysis"
178 - "Natural Language Understanding"
179 - "QR code analysis"
180 - "Sender analysis"
181 - "URL analysis"
182 - "URL screenshot"
183id: "9f1681e1-8c15-5edd-9aaa-eb5af1729322"