wkhtmltopdf aujourd’hui · Sécurité
wkhtmltopdf CVE-2022-35583 : que faire
CVE-2022-35583, notée 9,8 (critique) par le NVD le 22 août 2022 : wkhtmltopdf 0.12.6 laisse le HTML qu’il rend joindre des adresses internes, par exemple par une iframe. Une falsification de requête côté serveur (SSRF) qu’aucune version ne corrigera : wkhtmltopdf est archivé.
Qui est exposé
Tout serveur qui convertit du HTML contenant un texte qu’il ne maîtrise pas : le nom d’un client, une adresse, un commentaire. Non échappé, ce texte peut porter une <iframe> ou une <img> vers http://169.254.169.254/ (les métadonnées du cloud) ou vers un service sur localhost. La conversion envoie alors la requête depuis l’intérieur du réseau.
Ce que fait pdfkiln
- Par défaut, ce que fait wkhtmltopdf 0.12.6, le contrat de compatibilité : une page charge ce qu’elle veut sur le réseau, et ne lit aucun fichier local à part elle-même, sauf si
--enable-local-file-accessou--allowl’autorise ; ni..ni un lien symbolique ne contournent--allow. --kiln-block-private-networkrefuse les adresses de boucle locale, privées et de lien local, métadonnées du cloud comprises, après la résolution DNS : un nom qui se résout en127.0.0.1est refusé aussi. Vérifié sous Debian 13 avec pdfkiln 1.0.3 : une image servie sur127.0.0.1est imprimée sans l’option, laissée de côté avec elle.- La sandbox de Chromium est active, et
--kiln-timeoutarrête une conversion après 120 s par défaut.
La faille précédente, CVE-2020-21365 (notée 7,5 : lecture de fichiers locaux dans wkhtmltopdf 0.12.5 et avant), a été fermée par le réglage par défaut de la 0.12.6, que pdfkiln garde.
Activer l’option
En ligne de commande :
wkhtmltopdf --kiln-block-private-network page.html page.pdf
Avec pdfkit (Python), dans les options :
pdfkit.from_string(html, 'out.pdf', options={'kiln-block-private-network': ''})
knp-snappy, et les bibliothèques qui refusent les options qu’elles ne connaissent pas, reçoivent un script qui l’ajoute, à la place du programme :
printf '#!/bin/sh\nexec /usr/bin/wkhtmltopdf --kiln-block-private-network "$@"\n' \
| sudo tee /usr/local/bin/wkhtmltopdf-safe > /dev/null
sudo chmod +x /usr/local/bin/wkhtmltopdf-safe
$pdf = new Knp\Snappy\Pdf('/usr/local/bin/wkhtmltopdf-safe');
Le script transmet tout le reste : wkhtmltopdf-safe --version répond comme wkhtmltopdf.
Et dans les modèles
La cause reste dans le modèle : le texte qui vient des utilisateurs doit y être échappé, comme le font par défaut la plupart des moteurs de gabarits des frameworks web. L’option est le filet de sécurité.