Skip to content

Commit afb2903

Browse files
EmlParser - sanitize attachment filenames
1 parent 2760870 commit afb2903

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

analyzers/EmlParser/parse.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def artifacts(self, raw):
168168
tags=["body:attachment", "autoImport:true"] + h["tag"],
169169
)
170170
)
171-
filepath = os.path.join(self.job_directory, "output", h.get("filename"))
171+
filepath = os.path.join(self.job_directory, "output", os.path.basename(h.get("filename", "")))
172172
file_key = ("file", filepath)
173173
if file_key not in seen:
174174
seen.add(file_key)
@@ -193,6 +193,15 @@ def _add_ioc(ioc_list, data, tags):
193193
ioc_list.append({"data": data, "tag": list(tags)})
194194

195195

196+
def _safe_attachment_filename(raw_name):
197+
if not raw_name or "\x00" in raw_name:
198+
raise ValueError("invalid attachment filename")
199+
base = os.path.basename(raw_name)
200+
if not base or base in (".", "..") or os.path.isabs(base) or re.match(r"^[A-Za-z]:", base):
201+
raise ValueError("invalid attachment filename")
202+
return base
203+
204+
196205
def parseEml(filepath, job_directory, wkhtmltoimage, sanitized_rendering):
197206
ep = eml_parser.EmlParser(include_raw_body=True, include_attachment_data=True)
198207
with open(filepath, "rb") as f:
@@ -322,16 +331,15 @@ def parseEml(filepath, job_directory, wkhtmltoimage, sanitized_rendering):
322331
for a in decoded_email.get("attachment"):
323332
a["mime"] = magic.from_buffer(binascii.a2b_base64(a.get("raw")))
324333
if isinstance(a.get("raw"), bytes):
325-
path, filename = os.path.split(a.get("filename", ""))
326-
if path != "":
327-
os.umask(0)
328-
os.makedirs(
329-
f"{job_directory}/output/{path}", exist_ok=True, mode=0o777
330-
)
331-
filepath = os.path.join(job_directory, "output", path, filename)
334+
filename = _safe_attachment_filename(a.get("filename", ""))
335+
out_dir = os.path.join(job_directory, "output")
336+
filepath = os.path.join(out_dir, filename)
337+
if not os.path.realpath(filepath).startswith(
338+
os.path.realpath(out_dir) + os.sep
339+
):
340+
raise ValueError("attachment path escapes sandbox")
332341
with open(filepath, "wb") as f:
333342
f.write(base64.b64decode(a["raw"]))
334-
f.close()
335343
a["raw"] = a.get("raw").decode("ascii")
336344
result["attachments"].append(a)
337345
iocs["hash"].append(

0 commit comments

Comments
 (0)