
phpMyAdmin 5.2.3 - Élevé - À distance - SQLi - ImportLdi TERMINATED BY résiduel
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-importldi
Classe : SQLi Portée : Distante
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
ImportLdi.php construit LOAD DATA avec FIELDS/LINES TERMINATED BY à partir des POST ldi_terminated et ldi_new_line. Ces deux chaînes sont concaténées dans du SQL entre guillemets simples. ldi_enclosed et ldi_escaped passent par escapeString. phpMyAdmin active PMA_ENABLE_LDI sur /import, donc MYSQLI_OPT_LOCAL_INFILE est activé.
Un utilisateur connecté envoie en POST format=ldi avec un guillemet dans ldi_terminated. Le LOAD DATA émis contient le POST brut à l'intérieur de TERMINATED BY. Injection SQL dans la connexion de l'utilisateur, pas dans le control user.
| ID | pas encore de CVE |
| Classe | SQLi |
| Portée | Distante (connexion authentifiée par cookie ; import de table, format ldi) |
| CWE | CWE-89 |
| CVSS | Moyen : 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Produit | phpMyAdmin |
| Affecté | 5.2.3 tag RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Auth | connexion authentifiée par cookie. Import de table, format ldi |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Un utilisateur phpMyAdmin connecté qui peut ouvrir l'import de table peut injecter du SQL dans LOAD DATA ... TERMINATED BY sur sa connexion MySQL.
| Privilège | Méthode / sink | Recon / intégrité / disponibilité | Prouvé en lab ou déduit |
|---|---|---|---|
Casser le littéral FIELDS TERMINATED BY | POST index.php?route=/import format=ldi ldi_terminated avec un guillemet | Intégrité de la requête construite par PMA | Prouvé en lab. Boîte SQL HTML : TERMINATED BY '',PMA-IMPORTLDI-WITNESS' |
Garder ENCLOSED BY in-band | Même POST, guillemet dans ldi_enclosed | Contrôle négatif | Prouvé en lab. ENCLOSED BY est échappé |
| SQL supplémentaire sur la connexion utilisateur (INTO OUTFILE / stacked si autorisé) | Même sink une fois la chaîne fermée | Intégrité de la connexion utilisateur | Déduit. Le lab s'arrête au délimiteur cassé. Par défaut mysqli::query est mono-requête |
| Lecture/écriture de fichiers côté MySQL | Même LOAD DATA si le compte dispose de FILE ou LOCAL INFILE vers le serveur web | Intégrité des fichiers que mysqld peut toucher | Déduit. Non accordé ici. Non revendiqué |
Écarté sur ce lab : accès non authentifié, control-user / pmadb, LFI via include OS, et lecture/écriture conditionnée par FILE. L'utilisateur connecté dispose déjà d'une boîte SQL ; ce reliquat est le délimiteur non échappé à l'intérieur d'une requête que PMA construit pour lui.
Même pin : WebAuthn CustomServer leftover.
J'ai épinglé phpMyAdmin RELEASE_5_2_3. Les plugins d'import qui construisent LOAD DATA à la main sont un audit de quoting. Deux des quatre champs de délimiteur étaient échappés. Deux ne l'étaient pas :
$sql .= ' FIELDS TERMINATED BY \'' . $ldi_terminated . '\'';
...
$sql .= ' LINES TERMINATED BY \'' . $ldi_new_line . '\'';
ldi_enclosed / ldi_escaped appellent $dbi->escapeString. Common.php active PMA_ENABLE_LDI sur /import + format=ldi. Routes GET|POST /import et GET|POST /table/import.
Fausses pistes déjà consignées : revendiquer un LFI sans octroi FILE ; traiter la boîte SQL comme la découverte (le reliquat est le délimiteur non échappé que PMA concatène) ; revendiquer control-user / pmadb ; un reverse shell. Du théâtre.
python3 phpmyadmin-importldi-Abraxas-Labs.py
# or: cd lab && ./run.sh
Cible uniquement http://127.0.0.1:19290. Images phpmyadmin:5.2.3 et mysql:8.0. Projet Compose phpmyadmin-importldi. La stack est démontée après l'exécution.
Connexion par cookie. POST /import avec format=ldi et un guillemet dans ldi_terminated. LOAD DATA LOCAL INFILE ... INTO TABLE \ldi_target` FIELDS TERMINATED BY '',PMA-IMPORTLDI-WITNESS'émis. Le même guillemet dansldi_enclosedstocké commeENCLOSED BYéchappé. Le code source épinglé sur l'image 5.2.3 contient toujours'.$ldi_terminated.'et$dbi->escapeString($ldi_enclosed)`.
SUCCESS phpmyadmin-importldi pin=RELEASE_5_2_3 how=live TERMINATED-BY-raw ENCLOSED-escaped PMA-IMPORTLDI-WITNESS
escapeString sur ldi_terminated et ldi_new_line, comme pour enclosed et escaped. Cast en int de skip_queries.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/Plugins/Import/ImportLdi.phpGNU Affero GPL v3.0. Voir LICENSE. Lab en loopback uniquement. Aucune garantie.