Skip to content

Euro Office - Path Traversal in ZIP Extraction (ZipSlip) - Arbitrary File Write #18

Description

@CVE-Hunter-Leo

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 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

  1. Attacker creates a malicious .docx file (which is a ZIP archive)
  2. Within the ZIP, a file entry is named ../../../../var/www/html/webshell.php
  3. Attacker uploads/sends this .docx for conversion
  4. X2tConverter calls zip2dir()do_extract_currentfile()
  5. The file is written to /var/www/html/webshell.php instead of staying within the temp directory
  6. 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

  1. Validate each ZIP entry name before extraction:
    if (filenameW.find(L"..") != std::wstring::npos)
        continue; // skip this entry
  2. Resolve the canonical path and verify it starts with unzip_dir
  3. Use a ZIP library that provides this protection natively
  4. Strip all directory components and extract files to a flat directory

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions