Sploitus

Exploit for pdfcpu_poc

githubexploit Β· 2026-08-13

Exploit Code

README69 lines
## https://sploitus.com/exploit?id=7542FDA4-413F-5316-932F-00D80A315372
# pdfcpu β€” Path Traversal β†’ Arbitrary File Write in font extraction (PoC)

**Zip-Slip–style path traversal** in [`pdfcpu`](https://github.com/pdfcpu/pdfcpu).
The font-extraction feature builds the output filename from a PDF font's
`/BaseFont` value (or the `/Name` value for Type3 fonts) **without any
sanitization**. A crafted PDF whose `/BaseFont` contains `../` sequences makes
`os.Create()` write the embedded font file **outside** the caller-specified
output directory β€” arbitrary file write with attacker-controlled contents.

> Not a ZIP archive, but the mechanism is identical to Zip-Slip: embedded content
> is extracted to disk under an attacker-controlled member name that escapes the
> target directory. The root cause is a classic path traversal (CWE-22).

- **Vulnerability class:** CWE-22 β€” Improper Limitation of a Pathname to a
  Restricted Directory ('Path Traversal') β†’ arbitrary file write
- **Affected:** `github.com/pdfcpu/pdfcpu` **≀ v0.12.1**
- **Fixed in:** **v0.13.0** β€” commit
  [`21f8b3b`](https://github.com/pdfcpu/pdfcpu/commit/21f8b3bd585923e38316efa16e0cd7b26b79e79f)
  introduced `pkg/pdfcpu/sanitize`; all filename parts now pass through
  `sanitize.Path`, which strips path separators and `.`/`..` segments.
- **Sink:** `writeFonts()` in `pkg/api/extract.go`
- **Trigger (CLI):** `pdfcpu extract -mode fonts attacker.pdf ./out/`
- **Trigger (API):** `api.ExtractFontsFile` / `api.ExtractFonts`

## Taint chain
```
/BaseFont value in the PDF
  β†’ font.Name()            pkg/pdfcpu/font/fontDict.go   (only strips the "ABC+" subset prefix)
  β†’ FontObject.FontName    pkg/pdfcpu/optimize.go        (optimizeFontResourcesDict)
  β†’ Font.Name              pkg/pdfcpu/extract.go         (ExtractFont)
  β†’ writeFonts()           pkg/api/extract.go:
        outFile := filepath.Join(outDir,
            fmt.Sprintf("%s_%s.%s", fileName, f.Name, f.Type))   // f.Name is unsanitized
        os.Create(outFile)                                       //  writes /tmp/pdfcpu_zipslip_pwned.ttf (OUTSIDE ./out)
cd exploit && go run . malicious.pdf ./out

# 3. patched version    -> writes ./out/malicious_tmp_pdfcpu_zipslip_pwned.ttf (contained)
cd ../patched && go run . ../exploit/malicious.pdf ./out
```

### Observed
```
v0.12.1:  [+] CONFIRMED  -> /tmp/pdfcpu_zipslip_pwned.ttf   (139 bytes, attacker content)
v0.15.0:  [-] no escape  -> out/malicious_tmp_pdfcpu_zipslip_pwned.ttf
```

## Impact
Arbitrary file write with attacker-controlled contents at an attacker-chosen path
(bounded by the process's permissions). Depending on the victim's environment
this can overwrite config/scripts or drop files into autostart/`cron`/web-root
locations, and may lead to code execution. Any service that extracts fonts from
user-supplied PDFs on an affected version is exposed.

## Remediation
Upgrade to **β‰₯ v0.13.0**. If pinned to an older release, sanitize every untrusted
filename component before joining: reject/rewrite path separators and `..`, and
verify the final cleaned path stays within the intended output directory, e.g.
`strings.HasPrefix(filepath.Clean(outFile), outDir+string(os.PathSeparator))`.

> Note: even on patched versions the low-level `pdfcpu.ExtractPageFonts` /
> `ExtractFont` still return the raw, unsanitized `Font.Name`. Callers that build
> their own paths must sanitize it themselves.

## Disclosure
The issue was previously surfaced in a public security audit
([pdfcpu#1350](https://github.com/pdfcpu/pdfcpu/issues/1350), finding #6) and
silently fixed in v0.13.0. This repository provides a reproducible PoC and a
side-by-side vulnerable/patched comparison.