Euro Office - Path Traversal in ZIP Extraction (ZipSlip) - Arbitrary File Write
Severity: CRITICAL
CVSS Estimate: 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Description
Euro-Office is vulnerable to a path traversal vulnerability (ZipSlip) in its ZIP archive extraction logic, allowing arbitrary file write when processing OOXML and other ZIP-based document formats.
In OfficeUtils/src/ZipUtilsCP.cpp, the function do_extract_currentfile() constructs the output path by directly concatenating the user-controlled ZIP entry filename with the target extraction directory:
std::wstring output = std::wstring(unzip_dir) + FILE_SEPARATOR_STR + filenameW;
The only sanitization performed is replacing / with \ (on Windows) or \ with / (on Unix). There is no validation to prevent path traversal sequences such as ../ or ..\. As a result, a malicious ZIP entry name (e.g., ../../../../var/www/html/webshell.php) can cause files to be written outside the intended extraction directory.
This code path is reached when X2tConverter processes any ZIP-based document format via zip2dir() → ExtractToDirectory(). Affected formats include .docx, .xlsx, .pptx, .vsdx, .odt, .ods, .odp, and any other format that triggers ZIP extraction during conversion.
An attacker can exploit this vulnerability by uploading or submitting a specially crafted malicious document. Successful exploitation allows arbitrary file write on the server, which can lead to remote code execution (e.g., writing a webshell, overwriting binaries, or modifying configuration files).
Component
OfficeUtils/src/ZipUtilsCP.cpp
Vulnerable Location
Function: do_extract_currentfile() at line 268
Vulnerable Code
std::wstring filenameW = /* ZIP entry name from minizip */;
// Line 249-257: Only replaces '/' with '\' (Windows) or '\' with '/' (non-Windows)
std::wstring output = std::wstring(unzip_dir) + FILE_SEPARATOR_STR + filenameW;
Root Cause
Every OOXML format file (.docx, .xlsx, .pptx, .vsdx) is a ZIP archive. When processed by X2tConverter, the file is extracted via zip2dir() → ExtractToDirectory() → do_extract_currentfile(). The ZIP entry filename (filenameW) is directly concatenated to the output directory path without any path traversal sanitization.
The only "normalization" performed is:
- Windows: replacing
/ with \
- Unix: replacing
\ with /
There is no check for ../ path traversal sequences.
Exploit Path
- Attacker creates a malicious .docx file (which is a ZIP archive)
- Within the ZIP, a file entry is named
../../../../var/www/html/webshell.php
- Attacker uploads/sends this .docx for conversion
- X2tConverter calls
zip2dir() → do_extract_currentfile()
- The file is written to
/var/www/html/webshell.php instead of staying within the temp directory
- Attacker accesses the webshell via HTTP
Call Chain
X2tConverter (main.cpp)
→ fromInputParams() [ASCConverters.cpp]
→ zip2dir() [OfficeUtils]
→ ExtractToDirectory() [ZipUtilsCP.cpp]
→ do_extract_currentfile()
→ output = unzip_dir + FILE_SEPARATOR + filenameW ← NO SANITIZATION
Impact
- Remote Code Execution: Write webshell, overwrite server executables, overwrite cron jobs
- Arbitrary File Overwrite: Overwrite configuration files, SSH authorized_keys
- Full Server Compromise: On DocumentServer, can overwrite Node.js modules or JavaScript files that get executed on next request
Affected Formats
All ZIP-based formats are vulnerable:
- .docx (Word)
- .xlsx (Excel)
- .pptx (PowerPoint)
- .vsdx (Visio)
- .odt/.ods/.odp (OpenDocument) - also ZIP-based
- Any other format that triggers ZIP extraction
Remediation
- Validate each ZIP entry name before extraction:
if (filenameW.find(L"..") != std::wstring::npos)
continue; // skip this entry
- Resolve the canonical path and verify it starts with
unzip_dir
- Use a ZIP library that provides this protection natively
- Strip all directory components and extract files to a flat directory
References
Euro Office - Path Traversal in ZIP Extraction (ZipSlip) - Arbitrary File Write
Affected product: https://github.com/Euro-Office/core
Severity: CRITICAL
CVSS Estimate: 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Description
Euro-Office is vulnerable to a path traversal vulnerability (ZipSlip) in its ZIP archive extraction logic, allowing arbitrary file write when processing OOXML and other ZIP-based document formats.
In
OfficeUtils/src/ZipUtilsCP.cpp, the functiondo_extract_currentfile()constructs the output path by directly concatenating the user-controlled ZIP entry filename with the target extraction directory:std::wstring output = std::wstring(unzip_dir) + FILE_SEPARATOR_STR + filenameW;The only sanitization performed is replacing
/with\(on Windows) or\with/(on Unix). There is no validation to prevent path traversal sequences such as../or..\. As a result, a malicious ZIP entry name (e.g.,../../../../var/www/html/webshell.php) can cause files to be written outside the intended extraction directory.This code path is reached when
X2tConverterprocesses any ZIP-based document format viazip2dir()→ExtractToDirectory(). Affected formats include.docx,.xlsx,.pptx,.vsdx,.odt,.ods,.odp, and any other format that triggers ZIP extraction during conversion.An attacker can exploit this vulnerability by uploading or submitting a specially crafted malicious document. Successful exploitation allows arbitrary file write on the server, which can lead to remote code execution (e.g., writing a webshell, overwriting binaries, or modifying configuration files).
Component
OfficeUtils/src/ZipUtilsCP.cppVulnerable Location
Function:
do_extract_currentfile()at line 268Vulnerable Code
Root Cause
Every OOXML format file (.docx, .xlsx, .pptx, .vsdx) is a ZIP archive. When processed by X2tConverter, the file is extracted via
zip2dir()→ExtractToDirectory()→do_extract_currentfile(). The ZIP entry filename (filenameW) is directly concatenated to the output directory path without any path traversal sanitization.The only "normalization" performed is:
/with\\with/There is no check for
../path traversal sequences.Exploit Path
../../../../var/www/html/webshell.phpzip2dir()→do_extract_currentfile()/var/www/html/webshell.phpinstead of staying within the temp directoryCall Chain
Impact
Affected Formats
All ZIP-based formats are vulnerable:
Remediation
unzip_dirReferences