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