Attachment: Suspicious PDF created with headless browser
Detects PDF documents containing a table of contents that were generated using HeadlessChrome, Chromium with Skia/PDF, or QT with empty metadata fields - common characteristics of automated malicious document creation.
Sublime rule (View on GitHub)
1name: "Attachment: Suspicious PDF created with headless browser"
2description: "Detects PDF documents containing a table of contents that were generated using HeadlessChrome, Chromium with Skia/PDF, or QT with empty metadata fields - common characteristics of automated malicious document creation."
3type: "rule"
4severity: "high"
5source: |
6 type.inbound
7 and (
8 // directly attached PDF
9 any(filter(attachments, .file_type == "pdf"),
10 (
11 // table of contents detection
12 (
13 any(file.explode(.),
14 strings.contains(.scan.ocr.raw, 'TABLE OF CONTEN')
15 )
16 // the Table of contents can be on another page
17 and any(file.explode(.),
18 regex.icontains(.scan.ocr.raw,
19 '(?:[\r\n]|^)+(?:\s*1\s*(?:\.|:))?\s*Introduction'
20 )
21 or strings.icontains(.scan.ocr.raw, 'marked in red')
22 )
23 )
24 // heading of sections within observed documents
25 or (
26 any(file.explode(.),
27 any(.scan.strings.strings,
28 any([
29 'Employee Acknowledgement',
30 'Document Summary',
31 'appraisal overview',
32 'accessing full appraisal',
33 ],
34 .. =~ .
35 )
36 )
37 )
38 )
39 )
40 and (
41 (
42 (
43 strings.icontains(beta.parse_exif(.).creator, 'HeadlessChrome')
44 or strings.icontains(beta.parse_exif(.).creator, 'Chromium')
45 )
46 and strings.icontains(beta.parse_exif(.).producer, 'Skia/PDF')
47 )
48 or (
49 any(beta.parse_exif(.).fields,
50 .key == "Creator"
51 and (.value == "" or strings.istarts_with(.value, 'wkhtmltopdf'))
52 )
53 and any(beta.parse_exif(.).fields,
54 .key == "Title"
55 and (
56 .value == ""
57 // company handbook
58 or .value in ('Company HandBook')
59 // appraisal themes
60 or strings.icontains(.value,
61 'Employee Performance Appraisal'
62 )
63 )
64 )
65 and strings.istarts_with(beta.parse_exif(.).producer, 'QT ')
66 )
67 )
68 )
69 // or within an attached EML
70 or any(filter(attachments,
71 .content_type == "message/rfc822" or .file_extension == "eml"
72 ),
73 any(filter(file.parse_eml(.).attachments, .file_type == "pdf"),
74 (
75 // table of contents detection
76 (
77 any(file.explode(.),
78 strings.contains(.scan.ocr.raw, 'TABLE OF CONTEN')
79 )
80 // the Table of contents can be on another page
81 and any(file.explode(.),
82 regex.icontains(.scan.ocr.raw,
83 '(?:[\r\n]|^)+(?:\s*1\s*(?:\.|:))?\s*Introduction'
84 )
85 or strings.icontains(.scan.ocr.raw, 'marked in red')
86 )
87 )
88 // heading of sections within observed documents
89 or (
90 any(file.explode(.),
91 any(.scan.strings.strings,
92 any([
93 'Employee Acknowledgement',
94 'Document Summary',
95 'appraisal overview',
96 'accessing full appraisal',
97 ],
98 .. =~ .
99 )
100 )
101 )
102 )
103 )
104 and (
105 (
106 (
107 strings.icontains(beta.parse_exif(.).creator,
108 'HeadlessChrome'
109 )
110 or strings.icontains(beta.parse_exif(.).creator, 'Chromium')
111 )
112 and strings.icontains(beta.parse_exif(.).producer, 'Skia/PDF')
113 )
114 or (
115 any(beta.parse_exif(.).fields,
116 .key == "Creator"
117 and (
118 .value == ""
119 or strings.istarts_with(.value, 'wkhtmltopdf')
120 )
121 )
122 and any(beta.parse_exif(.).fields,
123 .key == "Title"
124 and (
125 .value == ""
126 // company handbook
127 or .value in ('Company HandBook')
128 // appraisal themes
129 or strings.icontains(.value,
130 'Employee Performance Appraisal'
131 )
132 )
133 )
134 and strings.istarts_with(beta.parse_exif(.).producer, 'QT ')
135 )
136 )
137 )
138 )
139 )
140
141attack_types:
142 - "Credential Phishing"
143tactics_and_techniques:
144 - "Evasion"
145 - "PDF"
146detection_methods:
147 - "Content analysis"
148 - "Exif analysis"
149 - "File analysis"
150 - "Optical Character Recognition"
151id: "8f3108d7-e224-5bb0-81f4-e4f8506cfed3"