
Exploit de preuve de concept pour CVE-2023-36664, une vulnérabilité d'injection de commandes Ghostscript. Comprend un environnement de laboratoire Docker, une analyse détaillée du contournement de validation des pipes et un guide de reproduction étape par étape.
CVE ID: CVE-2023-36664
Produit: Ghostscript (< 10.01.2)
Type de vulnérabilité: Remote Code Execution (RCE)
Cette vulnérabilité (CVE-2023-36664) est une vulnérabilité d'exécution de code arbitraire (RCE) résultant d'une validation insuffisante des autorisations de chemin pour les périphériques de type pipe (préfixe %pipe% ou |) dans Ghostscript.
Lorsqu'un système analyse ou traite un fichier de document malveillamment conçu (PS/EPS) par un attaquant, des commandes système arbitraires peuvent être exécutées sans autorisation de l'utilisateur.
Rôle principal : Il lit essentiellement un code de coordonnées graphiques textuel (par exemple, 'tracer une ligne à la position 100 200') et le convertit en une image visible sur un écran d'ordinateur ou un fichier image destiné à une sortie imprimante.
Un pipe est une fonctionnalité qui permet de connecter la sortie d'une application à l'entrée d'une autre, permettant ainsi aux logiciels de communiquer entre eux. Dans les commandes, il est représenté par le symbole |.
Exemple : cat /etc/hosts | grep localhost
Ghostscript vérifie strictement les chemins de fichiers lorsque le mode sécurisé (-dSAFER) est activé par défaut, empêchant ainsi l'accès aux fichiers sensibles du système ou l'exécution de commandes externes non autorisées.
Problème : Lorsqu'un attaquant insère, à la place d'un nom de fichier normal, un préfixe de périphérique pipe (%pipe% ou |) soigneusement manipulé, la logique de validation des autorisations de Ghostscript ne reconnaît pas correctement ce préfixe et le considère à tort comme un « chemin sûr » ou « ne nécessitant pas de validation », le laissant passer.
Résultat : Les commandes dangereuses qui auraient dû être filtrées contournent facilement la boucle de validation.
En examinant le code corrigé, on constate que deux fichiers .c ont été modifiés :
base/gpmisc.cbase/gslibctx.cIci, en observant gpmisc.c, on peut comprendre la vulnérabilité.

Le cœur de cette vulnérabilité est que des chemins spéciaux comme %pipe% ne sont pas correctement distingués des chemins de fichiers normaux et sont reconnus comme des chemins normaux.
gp_file_name_reducePour le vérifier, il est nécessaire d'examiner la fonction qui nettoie les chemins. Dans gpmisc.c, la fonction chargée de nettoyer les chemins est gp_file_name_reduce(...), et elle appelle en interne gp_file_name_combine() dont elle retourne le résultat.
gp_file_name_reduce(const char *fname, uint flen, char *buffer, uint *blen) {
return gp_file_name_combine(fname, flen, fname + flen, 0, false, buffer, blen);
}
gp_file_name_combine(), comme son nom l'indique, est une fonction qui supprime les expressions de chemin relatif inutiles telles que ./, // du chemin de fichier reçu.
Le problème se situe ici. Si cette fonction reçoit, au lieu d'un chemin de fichier normal, une chaîne spéciale destinée à exécuter une commande comme %pipe%, elle ne la reconnaît pas comme un modèle de chemin valide et retourne la chaîne originale sans aucun traitement.
gp_validate_path_len
gp_validate_path_len(...) est une fonction qui valide un chemin en appelant en interne gp_file_name_reduce(), mais dans ce processus, il n'existe aucune logique de validation distincte permettant de déterminer si l'entrée est un chemin de fichier normal ou une syntaxe d'exécution de commande comme %pipe%.
Par conséquent, une chaîne contenant %pipe% passe sans aucun filtrage, ce qui est la cause fondamentale de cette vulnérabilité.
Ainsi, si une chaîne comme %pipe%touch /tmp/pwned est transmise comme chemin de fichier, l'utilisateur pensait simplement vouloir afficher un fichier image, mais en réalité, la commande touch /tmp/pwned est exécutée, créant le fichier /tmp/pwned.
┌─────────────────────────────────┐
│ Docker Container │
│ (Ubuntu 22.04 + Ghostscript) │
│ │
│ /home/test/ ← Working directory
│ ├── poc.py ← Script de génération du PoC
│ | |
│ └── /var/www/html/config.php ← Fichier d'informations sensibles
│ │
│ User: test (non root) │
│ Ghostscript: 10.01.1 (vulnérable) │
└─────────────────────────────────┘
La raison pour laquelle un compte normal et non root a été choisi ici est que, dans les serveurs de production réels, il est courant de ne pas utiliser directement un compte root pour des raisons de sécurité. Par conséquent, afin de reproduire aussi fidèlement que possible le scénario d'une attaque réelle sur un serveur, l'environnement a été configuré sur la base d'un compte normal.
version: '3.8'
services:
gs-lab:
build: .
container_name: cve_lab
network_mode: "host"
environment:
- DISPLAY=${DISPLAY}
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix:ro
- ./poc.py:/home/test/poc.py
stdin_open: true
tty: true
DISPLAY=${DISPLAY} : Transmet la variable d'environnement pour permettre aux applications GUI du conteneur d'accéder au serveur d'affichage X11 de l'hôte./tmp/.X11-unix:/tmp/.X11-unix:ro : Monte le socket Unix pour la communication entre le serveur d'affichage X11 de l'hôte et le conteneur.
./poc.py:/home/test/poc.py : Monte le script PoC local de l'hôte dans l'environnement d'exécution du conteneur.
FROM ubuntu:22.04
RUN apt update && \
apt install -y \
wget \
build-essential \
gedit \
python3 \
sudo && \
rm -rf /var/lib/apt/lists/*
RUN wget https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10011/ghostscript-10.01.1.tar.gz && \
tar -xzf ghostscript-10.01.1.tar.gz
WORKDIR /ghostscript-10.01.1
RUN ./configure && \
make && \
make install
RUN mkdir -p /var/www/html && \
echo "DB_PASSWORD=SuperSecret1234!!!" > /var/www/html/config.php
RUN useradd -m -s /bin/bash test
WORKDIR /home/test
USER test
CMD ["/bin/bash"]