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 or any(filter(attachments, .file_extension in ('pdf', 'docx')),
32 any(recipients.to,
33 strings.icontains(..file_name, .email.domain.sld)
34 )
35 )
36 )
37 )
38 )
39
40 // Inspects image attachments for QR codes
41 and any(attachments,
42 (
43 .file_type in $file_types_images
44 or .file_type == "pdf"
45 or .file_extension in $file_extensions_macros
46 )
47 and (
48 any(file.explode(.),
49 .scan.qr.type == "url"
50 and not .scan.qr.url.domain.domain == "geico.app.link"
51 and (
52 // pass the QR URL to LinkAnalysis
53 any([ml.link_analysis(.scan.qr.url)],
54 .credphish.disposition == "phishing"
55
56 // any routing traverses via $suspicious_tld list
57 or any(.redirect_history, .domain.tld in $suspicious_tlds)
58
59 // effective destination in $suspicious_tld list
60 or .effective_url.domain.tld in $suspicious_tlds
61
62 // or the effective destination domain is in $abuse_ch_urlhaus_domains_trusted_reporters
63 or .effective_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters
64
65 // or any files downloaded are zips or executables
66 or any(.files_downloaded,
67 .file_extension in $file_extensions_common_archives
68 or .file_extension in $file_extensions_executables
69 )
70 )
71 or (
72
73 // or the QR code's root domain is a url_shortener
74 .scan.qr.url.domain.root_domain in $url_shorteners
75 or .scan.qr.url.domain.root_domain in $social_landing_hosts
76 and (
77 not (
78 any(ml.nlu_classifier(body.current_thread.text).intents,
79 .name == "benign"
80 )
81 or any(ml.nlu_classifier(body.current_thread.text).entities,
82 .name == "disclaimer"
83 )
84 )
85 or not any(attachments,
86 any(file.explode(.),
87 any(ml.nlu_classifier(.scan.ocr.raw).intents,
88 .name == "benign"
89 )
90 )
91 )
92 or (
93 any(recipients.to,
94 strings.icontains(..scan.qr.url.url, .email.email)
95 )
96 )
97 )
98
99 // exclude google maps
100 and not strings.starts_with(.scan.qr.url.url,
101 'https://goo.gl/maps'
102 )
103 and not strings.starts_with(.scan.qr.url.url,
104 'https://maps.app.goo.gl'
105 )
106 )
107
108 // the QR code url is a bing open redirect
109 or (
110 .scan.qr.url.domain.root_domain == 'bing.com'
111 and .scan.qr.url.path =~ '/ck/a'
112 )
113 // QR code contains non ascii chars
114 or regex.contains(.scan.qr.url.url, '[^\x00-\x7F]')
115 or (
116
117 // usap-dc open redirect
118 .scan.qr.url.domain.root_domain == "usap-dc.org"
119 and .scan.qr.url.path =~ "/tracker"
120 and strings.starts_with(.scan.qr.url.query_params,
121 "type=dataset&url=http"
122 )
123 or (
124 any(recipients.to,
125 strings.icontains(..scan.qr.url.url, .email.email)
126 or any(beta.scan_base64(..scan.qr.url.url,
127 ignore_padding=true
128 ),
129 strings.icontains(., ..email.email)
130 )
131 or any(beta.scan_base64(..scan.qr.url.fragment,
132 ignore_padding=true
133 ),
134 strings.icontains(., ..email.email)
135 )
136 )
137 )
138 )
139 )
140 )
141 )
142 )
143 and (
144 (
145 profile.by_sender_email().prevalence in ("new", "outlier")
146 and not profile.by_sender_email().solicited
147 )
148 or (
149 profile.by_sender_email().any_messages_malicious_or_spam
150 and not profile.by_sender_email().any_messages_benign
151 )
152 or (
153 sender.email.domain.domain in $org_domains
154 and not coalesce(headers.auth_summary.dmarc.pass, false)
155 )
156 )
157
158 // negate highly trusted sender domains unless they fail DMARC authentication
159 and (
160 (
161 sender.email.domain.root_domain in $high_trust_sender_root_domains
162 and not headers.auth_summary.dmarc.pass
163 )
164 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
165 )
166attack_types:
167 - "Credential Phishing"
168tactics_and_techniques:
169 - "QR code"
170 - "Social engineering"
171detection_methods:
172 - "Computer Vision"
173 - "Header analysis"
174 - "Natural Language Understanding"
175 - "QR code analysis"
176 - "Sender analysis"
177 - "URL analysis"
178 - "URL screenshot"
179id: "9f1681e1-8c15-5edd-9aaa-eb5af1729322"