Translated ['mobile-pentesting/android-app-pentesting/README.md', 'netwo

This commit is contained in:
Translator 2023-07-17 13:20:20 +00:00
parent 11af30ebab
commit 33be177503
2 changed files with 345 additions and 191 deletions

View file

@ -46,7 +46,7 @@ Echa un vistazo a la siguiente lista de [**Comandos de ADB**](adb-commands.md) p
## Smali
A veces es interesante **modificar el código de la aplicación** para acceder a **información oculta** (quizás contraseñas bien ofuscadas o banderas). Luego, podría ser interesante descompilar el apk, modificar el código y volver a compilarlo.\
A veces es interesante **modificar el código de la aplicación** para acceder a **información oculta** (quizás contraseñas bien ofuscadas o banderas). Luego, puede ser interesante descompilar el apk, modificar el código y volver a compilarlo.\
[**En este tutorial** puedes **aprender cómo descompilar un APK, modificar el código Smali y volver a compilar el APK** con la nueva funcionalidad](smali-changes.md). Esto podría ser muy útil como una **alternativa para varias pruebas durante el análisis dinámico** que se presentarán. Entonces, **siempre ten en cuenta esta posibilidad**.
## Otros trucos interesantes
@ -87,7 +87,7 @@ Por favor, [**lee aquí para encontrar información sobre los diferentes descomp
### Buscando información interesante
Solo echando un vistazo a las **cadenas de texto** del APK, puedes buscar **contraseñas**, **URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)), claves de **API**, **encriptación**, **UUIDs de Bluetooth**, **tokens** y cualquier cosa interesante... busca incluso puertas traseras de ejecución de código o puertas traseras de autenticación (credenciales de administrador codificadas en la aplicación).
Solo echando un vistazo a las **cadenas de texto** del APK, puedes buscar **contraseñas**, **URLs** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)), claves de **API**, **encriptación**, **UUIDs de Bluetooth**, **tokens** y cualquier otra cosa interesante... busca incluso puertas traseras de ejecución de código o puertas traseras de autenticación (credenciales de administrador codificadas en la aplicación).
**Firebase**
@ -100,7 +100,7 @@ Leyendo el **manifiesto**, puedes encontrar **vulnerabilidades**:
* En primer lugar, verifica si **la aplicación se puede depurar**. Un APK de producción no debería serlo (o de lo contrario, otros podrán conectarse a él). Puedes verificar si una aplicación es depurable buscando en el manifiesto el atributo `debuggable="true"` dentro de la etiqueta _\<application_ Ejemplo: `<application theme="@2131296387" debuggable="true"`
* [Aprende aquí](drozer-tutorial/#is-debuggeable) cómo encontrar aplicaciones depurables en un teléfono y explotarlas.
* **Copia de seguridad**: El atributo **`android:allowBackup`** define si los datos de la aplicación se pueden respaldar y restaurar por un usuario que haya habilitado la depuración USB. Si la bandera de copia de seguridad está configurada en true, permite a un atacante hacer una copia de seguridad de los datos de la aplicación a través de adb incluso si el dispositivo no está rooteado. Por lo tanto, las aplicaciones que manejan y almacenan información sensible como detalles de tarjetas, contraseñas, etc. deben tener esta configuración explícitamente establecida en **false**, porque de forma predeterminada está establecida en **true** para evitar tales riesgos.
* **Copia de seguridad**: El atributo **`android:allowBackup`** define si los datos de la aplicación se pueden respaldar y restaurar por parte de un usuario que haya habilitado la depuración USB. Si la bandera de copia de seguridad está configurada en true, permite a un atacante hacer una copia de seguridad de los datos de la aplicación a través de adb incluso si el dispositivo no está rooteado. Por lo tanto, las aplicaciones que manejan y almacenan información sensible como detalles de tarjetas, contraseñas, etc. deben tener esta configuración explícitamente establecida en **false**, porque de forma predeterminada está establecida en **true** para evitar tales riesgos.
* `<application android:allowBackup="false"`
* **NetworkSecurity:** La seguridad de red de la aplicación puede sobrescribir los valores predeterminados con **`android:networkSecurityConfig="@xml/network_security_config"`**. Se puede colocar un archivo con ese nombre en _**res/xml.**_ Este archivo configurará ajustes de seguridad importantes como pines de certificado o si permite tráfico HTTP. Puedes leer aquí más información sobre todas las cosas que se pueden configurar, pero revisa este ejemplo sobre cómo configurar el tráfico HTTP para algunos dominios:
* `<domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">formation-software.co.uk </domain></domain-config>`
@ -110,7 +110,7 @@ Leyendo el **manifiesto**, puedes encontrar **vulnerabilidades**:
* **Servicios expuestos**: Dependiendo de lo que el servicio esté haciendo internamente, se podrían explotar vulnerabilidades. En el análisis dinámico [aprenderás cómo aprovecharlos](./#exploiting-services).
* **Receptores de difusión**: [Aprenderás cómo posiblemente explotarlos](./#exploiting-broadcast-receivers) durante el análisis dinámico.
* **Esquema de URL**: Lee el código de la actividad que gestiona el esquema y busca vulnerabilidades en la gestión de la entrada del usuario. Más información sobre [qué es un esquema de URL aquí](./#url-schemes).
* **minSdkVersion**, **targetSDKVersion**, **maxSdkVersion**: Indican las versiones de Android en las que se ejecutará la aplicación. Es importante tenerlos en cuenta porque, desde una perspectiva de seguridad, admitir versiones antiguas permitirá que se ejecuten versiones conocidas de Android que tienen vulnerabilidades.
* **minSdkVersion**, **targetSDKVersion**, **maxSdkVersion**: Indican las versiones de Android en las que se ejecutará la aplicación. Es importante tenerlos en cuenta porque, desde una perspectiva de seguridad, admitir versiones antiguas permitirá que se ejecuten versiones vulnerables conocidas de Android.
Leyendo **resources.arsc/strings.xml**, puedes encontrar información interesante:
@ -138,11 +138,11 @@ Un proyecto de ejemplo que implementa este tipo de característica se puede enco
La mitigación es relativamente simple, ya que el desarrollador puede optar por no recibir eventos táctiles cuando una vista está cubierta por otra. Usando la [Referencia del Desarrollador de Android](https://developer.android.com/reference/android/view/View#security):
> A veces es esencial que una aplicación pueda verificar que una acción se está realizando con el pleno conocimiento y consentimiento del usuario, como otorgar una solicitud de permiso, realizar una compra o hacer clic en un anuncio. Desafortunadamente, una aplicación maliciosa podría intentar engañar al usuario para que realice estas acciones sin darse cuenta, ocultando el propósito previsto de la vista. Como remedio, el marco ofrece un mecanismo de filtrado táctil que se puede utilizar para mejorar la seguridad de las vistas que proporcionan acceso a funcionalidades sensibles.
> A veces es esencial que una aplicación pueda verificar que una acción se esté realizando con el pleno conocimiento y consentimiento del usuario, como otorgar una solicitud de permiso, realizar una compra o hacer clic en un anuncio. Desafortunadamente, una aplicación maliciosa podría intentar engañar al usuario para que realice estas acciones sin darse cuenta, ocultando el propósito previsto de la vista. Como remedio, el marco ofrece un mecanismo de filtrado táctil que se puede utilizar para mejorar la seguridad de las vistas que proporcionan acceso a funcionalidades sensibles.
>
> Para habilitar el filtrado táctil, llama a [`setFilterTouchesWhenObscured(boolean)`](https://developer.android.com/reference/android/view/View#setFilterTouchesWhenObscured%28boolean%29) o establece el atributo de diseño android:filterTouchesWhenObscured en true. Cuando está habilitado, el marco descartará los toques que se reciban siempre que la ventana de la vista esté oculta por otra ventana visible. Como resultado, la vista no recibirá toques cada vez que aparezca un toast, un diálogo u otra ventana por encima de la ventana de la vista.
### Secuestro de Tareas
### Secuestro de tareas
{% content-ref url="android-task-hijacking.md" %}
[android-task-hijacking.md](android-task-hijacking.md)
@ -170,8 +170,8 @@ A partir de Android 4.4 (**API 17**), la tarjeta SD tiene una estructura de dire
**Datos sensibles almacenados en texto claro**
* **Preferencias compartidas**: Android permite que cada aplicación guarde fácilmente archivos XML en la ruta `/data/data/<nombrepaquete>/shared_prefs/` y a veces es posible encontrar información sensible en texto claro en esa carpeta.
* **Bases de datos**: Android permite que cada aplicación guarde bases de datos SQLite fácilmente en la ruta `/data/data/<nombrepaquete>/databases/` y a veces es posible encontrar información sensible en texto claro en esa carpeta.
* **Preferencias compartidas**: Android permite que cada aplicación guarde fácilmente archivos xml en la ruta `/data/data/<nombrepaquete>/shared_prefs/` y a veces es posible encontrar información sensible en texto claro en esa carpeta.
* **Bases de datos**: Android permite que cada aplicación guarde bases de datos sqlite fácilmente en la ruta `/data/data/<nombrepaquete>/databases/` y a veces es posible encontrar información sensible en texto claro en esa carpeta.
### TLS roto
@ -184,23 +184,23 @@ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
```
Una buena manera de probar esto es intentar capturar el tráfico utilizando un proxy como Burp sin autorizar el CA de Burp dentro del dispositivo. Además, puedes generar con Burp un certificado para un nombre de host diferente y usarlo.
### Criptografía rota
### Criptografía Rota
**Procesos de gestión de claves deficientes**
**Procesos de Gestión de Claves Débiles**
Algunos desarrolladores guardan datos sensibles en el almacenamiento local y los cifran con una clave codificada/predecible en el código. Esto no debería hacerse, ya que algunos procesos de reversión podrían permitir a los atacantes extraer la información confidencial.
**Uso de algoritmos inseguros y/o obsoletos**
**Uso de Algoritmos Inseguros y/o Obsoletos**
Los desarrolladores no deberían utilizar algoritmos **obsoletos** para realizar **comprobaciones** de autorización, **almacenar** o **enviar** datos. Algunos de estos algoritmos son: RC4, MD4, MD5, SHA1... Si se utilizan **hashes** para almacenar contraseñas, por ejemplo, se deben utilizar hashes resistentes a ataques de fuerza bruta con sal.
Los desarrolladores no deberían utilizar algoritmos **obsoletos** para realizar **verificaciones** de autorización, **almacenar** o **enviar** datos. Algunos de estos algoritmos son: RC4, MD4, MD5, SHA1... Si se utilizan **hashes** para almacenar contraseñas, por ejemplo, se deben utilizar hashes resistentes a ataques de fuerza bruta con sal.
### Otras comprobaciones
### Otras verificaciones
* Se recomienda **ofuscar el APK** para dificultar el trabajo de ingeniería inversa a los atacantes.
* Si la aplicación es sensible (como las aplicaciones bancarias), debería realizar sus **propias comprobaciones para ver si el dispositivo móvil está rooteado** y actuar en consecuencia.
* Si la aplicación es sensible (como las aplicaciones bancarias), debería comprobar si se está utilizando un **emulador**.
* Si la aplicación es sensible (como las aplicaciones bancarias), debería realizar sus **propias verificaciones para ver si el dispositivo móvil está rooteado** y actuar en consecuencia.
* Si la aplicación es sensible (como las aplicaciones bancarias), debería verificar si se está utilizando un **emulador**.
* Si la aplicación es sensible (como las aplicaciones bancarias), debería **verificar su propia integridad antes de ejecutarse** para comprobar si ha sido modificada.
* Utiliza [**APKiD**](https://github.com/rednaga/APKiD) para comprobar qué compilador/empaquetador/ofuscador se utilizó para construir el APK.
* Utiliza [**APKiD**](https://github.com/rednaga/APKiD) para verificar qué compilador/empaquetador/ofuscador se utilizó para construir el APK.
### Aplicación React Native
@ -220,6 +220,10 @@ Luego, descomprime todos los DLsL utilizando [**xamarin-decompress**](https://gi
```
python3 xamarin-decompress.py -o /path/to/decompressed/apk
```
### Aplicaciones supercomprimidas
Según esta [**publicación de blog**](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 solo archivo. El blog habla sobre la posibilidad de crear una aplicación que descomprima este tipo de aplicaciones... y una forma más rápida que implica **ejecutar la aplicación y recopilar los archivos descomprimidos del sistema de archivos**.
### Análisis de código estático automatizado
La herramienta [**mariana-trench**](https://github.com/facebook/mariana-trench) es capaz de encontrar **vulnerabilidades** mediante el **escaneo** del **código** de la aplicación. Esta herramienta contiene una serie de **fuentes conocidas** (que indican a la herramienta los **lugares** donde la **entrada** está **controlada por el usuario**), **sumideros** (que indican a la herramienta **lugares peligrosos** donde la entrada maliciosa del usuario podría causar daños) y **reglas**. Estas reglas indican la **combinación** de **fuentes-sumideros** que indica una vulnerabilidad.
@ -228,9 +232,9 @@ Con este conocimiento, **mariana-trench revisará el código y encontrará posib
### Secretos filtrados
Una aplicación puede contener secretos (claves de API, contraseñas, URL ocultas, subdominios...) en su interior que podrías descubrir. Puedes usar una herramienta como [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
Una aplicación puede contener secretos (claves de API, contraseñas, URL ocultas, subdominios...) en su interior que podrías descubrir. Puedes usar una herramienta como [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks).
### Bypass de autenticación biométrica
### Saltar la autenticación biométrica
{% content-ref url="bypass-biometric-authentication-android.md" %}
[bypass-biometric-authentication-android.md](bypass-biometric-authentication-android.md)
@ -268,7 +272,7 @@ Gana puntos de reputación con cada error verificado y conquista la cima de la c
## Análisis dinámico
> En primer lugar, necesitas un entorno donde puedas instalar la aplicación y todo el entorno (certificado Burp CA, Drozer y Frida principalmente). Por lo tanto, se recomienda encarecidamente un dispositivo rooteado (emulado o no).
> En primer lugar, necesitas un entorno donde puedas instalar la aplicación y todo el entorno (certificado de CA de Burp, Drozer y Frida principalmente). Por lo tanto, se recomienda encarecidamente un dispositivo con root (emulado o no).
### Análisis dinámico en línea
@ -284,23 +288,23 @@ Gracias a la conexión ADB, puedes usar **Drozer** y **Frida** dentro de los emu
Puedes usar algún **emulador** como:
* [**Android Studio**](https://developer.android.com/studio) (Puedes crear dispositivos **x86** y **arm**, y según [**esto** ](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**las últimas versiones x86** **soportan bibliotecas ARM** sin necesidad de un emulador ARM lento).
* Si quieres intentar **instalar** una **imagen** y luego quieres **eliminarla**, puedes hacerlo en Windows:`C:\Users\<User>\AppData\Local\Android\sdk\system-images\` o en Mac: `/Users/myeongsic/Library/Android/sdk/system-image`
* [**Android Studio**](https://developer.android.com/studio) (Puedes crear dispositivos **x86** y **arm**, y según [**esto**](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html), las **últimas versiones x86** **soportan bibliotecas ARM** sin necesidad de un emulador ARM lento).
* Si quieres intentar **instalar** una **imagen** y luego **eliminarla**, puedes hacerlo en Windows:`C:\Users\<User>\AppData\Local\Android\sdk\system-images\` o en Mac: `/Users/myeongsic/Library/Android/sdk/system-image`
* Este es el **emulador principal que recomiendo usar y puedes**[ **aprender a configurarlo en esta página**](avd-android-virtual-device.md).
* [**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 posibles errores._)
* [Nox](https://es.bignox.com) (Gratis, pero no es compatible con Frida o Drozer).
{% hint style="info" %}
Al crear un nuevo emulador en cualquier plataforma, recuerda que cuanto más grande sea la pantalla, más lento funcionará el emulador. Así que selecciona pantallas pequeñas si es posible.
Cuando crees un nuevo emulador en cualquier plataforma, recuerda que cuanto más grande sea la pantalla, más lento funcionará el emulador. Así que selecciona pantallas pequeñas si es posible.
{% endhint %}
Como la mayoría de las personas usarán **Genymotion**, ten en cuenta este truco. Para **instalar servicios de Google** (como AppStore) debes hacer clic en el botón marcado en rojo de la siguiente imagen:
Como la mayoría de las personas usarán **Genymotion**, ten en cuenta este truco. Para **instalar servicios de Google** (como AppStore) necesitas hacer clic en el botón marcado en rojo en la siguiente imagen:
![](<../../.gitbook/assets/image (200) (1).png>)
Además, ten en cuenta que en la **configuración de la VM de Android en Genymotion** puedes seleccionar el modo de red de puente (esto será útil si te conectarás a la VM de Android desde una VM diferente con las herramientas).
Además, ten en cuenta que en la **configuración de la máquina virtual de Android en Genymotion** puedes seleccionar el modo de red de puente (esto será útil si te conectarás a la máquina virtual de Android desde una máquina virtual diferente con las herramientas).
O puedes usar un **dispositivo físico** (necesitas activar las opciones de depuración y sería genial si puedes rootearlo):
O podrías usar un **dispositivo físico** (necesitas activar las opciones de depuración y sería genial si puedes rootearlo):
1. **Configuración**.
2. (A partir de Android 8.0) Selecciona **Sistema**.
@ -309,36 +313,36 @@ O puedes usar un **dispositivo físico** (necesitas activar las opciones de depu
5. Vuelve atrás y encontrarás las **Opciones de desarrollador**.
> 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.\
> Sugeriría **realizar este análisis dinámico inicial utilizando el análisis dinámico de MobSF + pidcat**, para que puedas **aprender cómo funciona la aplicación** mientras MobSF **captura** una gran cantidad de **datos interesantes** que puedes revisar más adelante.
> Sugiero **realizar este análisis dinámico inicial utilizando el análisis dinámico de MobSF + pidcat**, para que puedas **aprender cómo funciona la aplicación** mientras MobSF **captura** una gran cantidad de **datos interesantes** que puedes revisar más adelante.
### Fuga de datos no intencionada
**Registro**
A menudo, los desarrolladores dejan información de depuración de forma pública. Por lo tanto, cualquier aplicación con el permiso `READ_LOGS` puede **acceder a esos registros** y obtener información sensible a través de ellos.\
Mientras navegas por la aplicación, utiliza [**pidcat**](https://github.com/JakeWharton/pidcat)_(Recomendado, es más fácil de usar y leer)_ o [adb logcat](adb-commands.md#logcat) para leer los registros creados y **buscar información sensible**.
Al navegar por la aplicación, utiliza [**pidcat**](https://github.com/JakeWharton/pidcat)_(Recomendado, es más fácil de usar y leer)_ o [adb logcat](adb-commands.md#logcat) para leer los registros creados y **buscar información sensible**.
{% hint style="warning" %}
Ten en cuenta que a partir de las versiones posteriores a Android 4.0, **las aplicaciones solo pueden acceder a sus propios registros**. Por lo tanto, las aplicaciones no pueden acceder a los registros de otras aplicaciones.\
Ten en cuenta que a partir de **versiones posteriores a Android 4.0**, **las aplicaciones solo pueden acceder a sus propios registros**. Por lo tanto, las aplicaciones no pueden acceder a los registros de otras aplicaciones.\
De todos modos, se recomienda **no registrar información sensible**.
{% endhint %}
**Caché del portapapeles**
Android proporciona un marco basado en el portapapeles para proporcionar la función de copiar y pegar en las aplicaciones de Android. Pero esto crea un problema grave cuando alguna **otra aplicación** puede **acceder** al **portapapeles** que contiene datos sensibles. La función de **copiar/pegar** debería estar **deshabilitada** para las partes sensibles de la aplicación. Por ejemplo, deshabilita la copia de detalles de tarjetas de crédito.
Android proporciona un marco basado en el **portapapeles** para proporcionar la función de copiar y pegar en las aplicaciones de Android. Pero esto crea un problema grave cuando alguna **otra aplicación** puede **acceder** al **portapapeles** que contiene datos sensibles. La función de **copiar y pegar** debe estar **deshabilitada** para la **parte sensible** de la aplicación. Por ejemplo, deshabilita la copia de detalles de tarjetas de crédito.
**Registros de bloqueo**
**Registros de fallos**
Si una aplicación **se bloquea** durante la ejecución y guarda registros en algún lugar, esos registros pueden ser útiles para un atacante, especialmente en casos en los que no se puede ingeniería inversa de la aplicación de Android. Luego, evita crear registros cuando la aplicación se bloquea y, si los registros se envían a través de la red, asegúrate de que se envíen a través de un canal SSL.\
Si una aplicación **falla** durante la ejecución y **guarda registros** en algún lugar, esos registros pueden ser útiles para un atacante, especialmente en casos en los que no se puede realizar ingeniería inversa de la aplicación de Android. En ese caso, evita crear registros cuando la aplicación falla y, si los registros se envían a través de la red, asegúrate de que se envíen a través de un canal SSL.\
Como pentester, **intenta echar un vistazo a estos registros**.
**Datos de análisis enviados a terceros**
La mayoría de las aplicaciones utilizan otros servicios en su aplicación, como Google Adsense, pero a veces **filtrar datos sensibles** o datos que no es necesario enviar a ese servicio. Esto puede suceder porque el desarrollador no implementó correctamente la función. Puedes **verificar interceptando el tráfico** de la aplicación y ver si se envían datos sensibles a terceros o no.
La mayoría de las aplicaciones utilizan otros servicios en su aplicación, como Google Adsense, pero a veces **filtran datos sensibles** o datos que no es necesario enviar a ese servicio. Esto puede ocurrir porque el desarrollador no implementó correctamente la función. Puedes **verificar interceptando el tráfico** de la aplicación y ver si se envían datos sensibles a terceros o no.
### Bases de datos SQLite
La mayoría de las aplicaciones utilizarán **bases de datos SQLite internas** para guardar información. Durante la prueba de penetración, **verifica** las **bases de datos** creadas, los nombres de las **tablas** y las **columnas**, y todos los **datos** guardados, ya que podrías encontrar **información sensible** (lo cual sería una vulnerabilidad).\
Las bases de datos deben estar ubicadas en `/data/data/el.nombre.del.paquete/databases`, como `/data/data/com.mwr.example.sieve/databases`.
La mayoría de las aplicaciones utilizarán **bases de datos SQLite internas** para guardar información. Durante la prueba de penetración, **observa** las **bases de datos** creadas, los nombres de las **tablas** y las **columnas** y todos los **datos** guardados, ya que podrías encontrar **información sensible** (lo cual sería una vulnerabilidad).\
Las bases de datos deben estar ubicadas en `/data/data/el.nombre.del.paquete/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**.
@ -346,7 +350,7 @@ Enumera las tablas usando `.tables` y enumera las columnas de las tablas con `.s
### Drozer (Actividades de explotación, Proveedores de contenido y Servicios)
**Drozer** te permite **asumir el rol de una aplicación de Android** e interactuar con otras aplicaciones. Puede hacer **cualquier cosa que una aplicación instalada pueda hacer**, como utilizar el mecanismo de Comunicación entre Procesos (IPC) de Android e interactuar con el sistema operativo subyacente. De [Guía de Drozer](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf).\
**Drozer** te permite **asumir el rol de una aplicación de Android** e interactuar con otras aplicaciones. Puede hacer **cualquier cosa que una aplicación instalada pueda hacer**, como utilizar el mecanismo de Comunicación entre Procesos (IPC) de Android e interactuar con el sistema operativo subyacente. Extraído de [Guía de Drozer](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf).\
Drozer es una herramienta útil para **explotar actividades exportadas, servicios exportados y Proveedores de contenido**, como aprenderás en las siguientes secciones.
### Explotando actividades exportadas
@ -451,18 +455,18 @@ Se recomienda **aplicar SSL Pinning** para los sitios donde se enviará informac
En primer lugar, debes (debes) **instalar el certificado** de la herramienta de **proxy** que vas a utilizar, probablemente Burp. Si no instalas el certificado CA de la herramienta de proxy, es probable que no veas el tráfico cifrado en el proxy.\
**Por favor,** [**lee esta guía para aprender cómo instalar un certificado CA personalizado**](android-burp-suite-settings.md)**.**
Para las aplicaciones dirigidas a **API Level 24+ no es suficiente instalar el certificado CA** de Burp en el dispositivo. Para evitar esta nueva protección, debes modificar el archivo de configuración de seguridad de red. Por lo tanto, puedes modificar este archivo para autorizar tu certificado CA o puedes [**leer esta página para obtener un tutorial sobre cómo hacer que la aplicación vuelva a aceptar todos los certificados instalados en el dispositivo**](make-apk-accept-ca-certificate.md).
Para las aplicaciones dirigidas a **API Level 24+ no es suficiente con instalar el certificado CA** de Burp en el dispositivo. Para evitar esta nueva protección, debes modificar el archivo de configuración de seguridad de red. Por lo tanto, puedes modificar este archivo para autorizar tu certificado CA o puedes [**leer esta página para obtener un tutorial sobre cómo hacer que la aplicación vuelva a aceptar todos los certificados instalados en el dispositivo**](make-apk-accept-ca-certificate.md).
**SSL Pinning**
Ya hemos discutido qué es el SSL Pinning solo 2 párrafos antes. Cuando se implementa en una aplicación, deberás evitarlo para inspeccionar el tráfico HTTPS o no lo verás.\
Aquí voy a presentar algunas opciones que he utilizado para evitar esta protección:
Aquí presentaré algunas opciones que he utilizado para evitar esta protección:
* Modificar automáticamente el **apk** para **evitar** el SSL Pinning con [**apk-mitm**](https://github.com/shroudedcode/apk-mitm). La mejor ventaja de esta opción es que no necesitarás acceso root para evitar el SSL Pinning, pero deberás eliminar la aplicación y reinstalar la nueva, y esto no siempre funcionará.
* Puedes usar **Frida** (discutido a continuación) para evitar esta protección. Aquí tienes una guía para usar 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/)
* También puedes intentar **evitar automáticamente el SSL Pinning** utilizando [**objection**](frida-tutorial/objection-tutorial.md)**:** `objection --gadget com.package.app explore --startup-command "android sslpinning disable"`
* También puedes intentar **evitar automáticamente el SSL Pinning** utilizando el análisis dinámico de **MobSF** (explicado a continuación)
* Si aún crees que hay algún tráfico que no estás capturando, puedes intentar **redirigir el tráfico a Burp utilizando iptables**. Lee este blog: [https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
* Si aún crees que hay algún tráfico que no estás capturando, puedes intentar **redirigir el tráfico a burp utilizando iptables**. Lee este blog: [https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
**Vulnerabilidades web comunes**
@ -578,13 +582,13 @@ receivers
```
**Herramientas HTTP**
Cuando se captura el tráfico http, puedes ver una vista poco atractiva del tráfico capturado en la sección "**HTTP(S) Traffic**" o una vista más agradable en el botón verde "**Start HTTPTools**". Desde la segunda opción, puedes **enviar** las **solicitudes capturadas** a **proxies** como Burp o Owasp ZAP.\
Para hacerlo, _enciende Burp -->_ _desactiva Intercept --> en MobSB HTTPTools selecciona la solicitud_ --> presiona "**Send to Fuzzer**" --> _selecciona la dirección del proxy_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
Cuando se captura el tráfico http, puedes ver una vista poco atractiva del tráfico capturado en la parte inferior de "**HTTP(S) Traffic**" o una vista más agradable en el botón verde "**Start HTTPTools**". Desde la segunda opción, puedes **enviar** las **solicitudes capturadas** a **proxies** como Burp o Owasp ZAP.\
Para hacerlo, _enciende Burp -->_ _apaga Intercept --> en MobSB HTTPTools selecciona la solicitud_ --> presiona "**Send to Fuzzer**" --> _selecciona la dirección del proxy_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080)).
Una vez que hayas terminado el análisis dinámico con MobSF, puedes presionar "**Start Web API Fuzzer**" para **fuzzear las solicitudes http** y buscar vulnerabilidades.
{% hint style="info" %}
Después de realizar un análisis dinámico con MobSF, es posible que la configuración del proxy esté mal configurada y no puedas solucionarlo desde la interfaz gráfica. Puedes solucionar la configuración del proxy haciendo:
Después de realizar un análisis dinámico con MobSF, es posible que la configuración del proxy esté mal configurada y no puedas solucionarlo desde la GUI. Puedes solucionar la configuración del proxy haciendo:
```
adb shell settings put global http_proxy :0
```
@ -640,7 +644,7 @@ 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 se puede utilizar en Windows, MacOS X y Linux para analizar archivos _.apk_ en busca de vulnerabilidades. Lo hace descomprimiendo los APK y aplicando una serie de reglas para detectar esas vulnerabilidades.
SUPER es una aplicación de línea de comandos que se puede utilizar en Windows, MacOS X y Linux para analizar archivos _.apk_ en busca de vulnerabilidades. Esto se logra descomprimiendo los APK y aplicando una serie de reglas para detectar esas vulnerabilidades.
Todas las reglas se encuentran en un archivo `rules.json`, y cada empresa o probador puede crear sus propias reglas para analizar lo que necesiten.
@ -710,7 +714,7 @@ Las recompensas de HackenProof se lanzan solo cuando sus clientes depositan el p
**Conviértete en la leyenda del hacker web3**\
Gana puntos de reputación con cada error verificado y conquista la cima de la clasificación semanal.
[**Regístrate en HackenProof**](https://hackenproof.com/register) y comienza a ganar con tus hacks!
[**Regístrate en HackenProof**](https://hackenproof.com/register) ¡comienza a ganar con tus hacks!
{% embed url="https://hackenproof.com/register" %}
@ -740,7 +744,7 @@ Encuentra una guía paso a paso para desofuscar el apk en [https://blog.lexfo.fr
### [DeGuard](http://apk-deguard.com)
**DeGuard revierte el proceso de ofuscación realizado por las herramientas de ofuscación de Android. Esto permite realizar numerosos análisis de seguridad, incluida la inspección de código y la predicción de bibliotecas.**
**DeGuard revierte el proceso de ofuscación realizado por las herramientas de ofuscación de Android. Esto permite numerosos análisis de seguridad, incluida la inspección de código y la predicción de bibliotecas.**
Puedes subir una APK ofuscada a su plataforma.

View file

@ -7,155 +7,263 @@
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PR al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Introducción
GraphQL actúa como una alternativa a la API REST. Las API REST requieren que el cliente envíe múltiples solicitudes a diferentes puntos finales en la API para consultar datos de la base de datos del backend. Con GraphQL, solo necesita enviar una solicitud para consultar el backend. Esto es mucho más simple porque no tiene que enviar múltiples solicitudes a la API, una sola solicitud se puede utilizar para recopilar toda la información necesaria.
GraphQL actúa como una alternativa a las API REST. Las API REST requieren que el cliente envíe múltiples solicitudes a diferentes puntos finales en la API para consultar datos de la base de datos del backend. Con GraphQL, solo necesitas enviar una solicitud para consultar el backend. Esto es mucho más simple porque no tienes que enviar múltiples solicitudes a la API, una sola solicitud puede usarse para recopilar toda la información necesaria.
## GraphQL
A medida que surgen nuevas tecnologías, también lo harán nuevas vulnerabilidades. Por **defecto**, GraphQL no implementa **autenticación**, esto es responsabilidad del desarrollador para implementar. Esto significa que, por defecto, GraphQL permite que cualquiera lo consulte, cualquier información confidencial estará disponible para los atacantes no autenticados.
A medida que surgen nuevas tecnologías, también surgirán nuevas vulnerabilidades. Por **defecto**, GraphQL no implementa **autenticación**, esto es responsabilidad del desarrollador. Esto significa que, por defecto, GraphQL permite a cualquiera hacer consultas, y cualquier información sensible estará disponible para los atacantes sin autenticar.
Al realizar sus ataques de fuerza bruta de directorios, asegúrese de agregar las siguientes rutas para verificar las instancias de GraphQL.
Cuando realices tus ataques de fuerza bruta de directorios, asegúrate de agregar las siguientes rutas para buscar instancias de GraphQL.
* _/graphql_
* _/graphiql_
* _/graphql.php_
* _/graphql/console_
* `/graphql`
* `/graphiql`
* `/graphql.php`
* `/graphql/console`
* `/api`
* `/api/graphql`
* `/graphql/api`
* `/graphql/graphql`
<figure><img src="../../.gitbook/assets/image (6) (1) (3).png" alt=""><figcaption></figcaption></figure>
Una vez que encuentre una instancia de GraphQL abierta, debe saber **qué consultas admite**. Esto se puede hacer utilizando el sistema de introspección, se pueden encontrar más detalles aquí: [**GraphQL: un lenguaje de consulta para API.**\
A menudo es útil preguntar a un esquema de GraphQL por información sobre qué consultas admite. GraphQL nos permite hacerlo](https://graphql.org/learn/introspection/)
Una vez que encuentres una instancia de GraphQL abierta, necesitas saber **qué consultas admite**. Esto se puede hacer utilizando el sistema de introspección, se pueden encontrar más detalles aquí: [**GraphQL: Un lenguaje de consulta para APIs.**\
A menudo es útil preguntar a un esquema de GraphQL qué consultas admite. GraphQL nos permite hacerlo...](https://graphql.org/learn/introspection/)
### Huella digital
### Fingerprint
La herramienta [**graphw00f**](https://github.com/dolevf/graphw00f) es capaz de detectar qué motor de GraphQL se utiliza en un servidor y luego imprime información útil para el auditor de seguridad.
#### Consultas universales <a href="#universal-queries" id="universal-queries"></a>
Si envías `query{__typename}` a cualquier punto final de GraphQL, incluirá la cadena `{"data": {"__typename": "query"}}` en alguna parte de su respuesta. Esto se conoce como una consulta universal y es una herramienta útil para comprobar si una URL corresponde a un servicio de GraphQL.
La consulta funciona porque cada punto final de GraphQL tiene un campo reservado llamado `__typename` que devuelve el tipo del objeto consultado como una cadena.
### Enumeración básica
GraphQL generalmente admite GET, POST (x-www-form-urlencoded) y POST (json).
GraphQL generalmente admite **GET**, **POST** (x-www-form-urlencoded) y **POST**(json). Aunque por seguridad se recomienda permitir solo json para evitar ataques CSRF.
**query={\_\_schema{types{name,fields{name\}}\}}**
#### Introspección
Con esta consulta encontrará el nombre de todos los tipos que se están utilizando:
Para utilizar la introspección y descubrir información del esquema, consulta el campo `__schema`. Este campo está disponible en el tipo raíz de todas las consultas.
```bash
query={__schema{types{name,fields{name}}}}
```
Con esta consulta encontrarás el nombre de todos los tipos que se están utilizando:
![](<../../.gitbook/assets/image (202).png>)
**query={\_\_schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind\}}\}}\}}}**
{% code overflow="wrap" %}
```bash
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
```
{% endcode %}
Con esta consulta, puede extraer todos los tipos, sus campos y sus argumentos (y el tipo de los argumentos). Esto será muy útil para saber cómo consultar la base de datos.
Con esta consulta puedes extraer todos los tipos, sus campos y sus argumentos (y el tipo de los argumentos). Esto será muy útil para saber cómo consultar la base de datos.
![](<../../.gitbook/assets/image (207) (3).png>)
**Errores**
Es interesante saber si los **errores** se van a **mostrar** ya que contribuirán con información útil.
Es interesante saber si los **errores** se van a **mostrar**, ya que aportarán información útil.
```
?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}
```
![](<../../.gitbook/assets/image (205) (1).png>)
**Enumerar el esquema de la base de datos a través de la introspección**
La introspección es una técnica que se utiliza para descubrir información sobre una API GraphQL. En el contexto de la pentesting, se puede utilizar para enumerar el esquema de la base de datos subyacente. La mayoría de las implementaciones de GraphQL tienen una función de introspección incorporada que se puede utilizar para recuperar información sobre el esquema de la base de datos.
{% hint style="info" %}
Si la introspección está habilitada pero la consulta anterior no se ejecuta, intente eliminar las directivas `onOperation`, `onFragment` y `onField` de la estructura de la consulta.
{% endhint %}
```bash
#Full introspection query
Para utilizar la introspección, se puede enviar una consulta especial a la API GraphQL. La consulta debe incluir el campo "__schema" y una lista de campos que se desean recuperar. La respuesta incluirá información sobre los tipos de datos, los campos y las relaciones en el esquema de la base de datos.
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
onOperation #Often needs to be deleted to run query
onFragment #Often needs to be deleted to run query
onField #Often needs to be deleted to run query
}
}
}
La información obtenida a través de la introspección puede ser utilizada para identificar vulnerabilidades en la API GraphQL y en la base de datos subyacente. Por ejemplo, se puede utilizar para identificar campos que contienen información confidencial o para descubrir relaciones entre los datos que pueden ser explotadas para obtener acceso no autorizado a la base de datos.
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
```
Consulta de introspección en línea:
```
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
```
La última línea de código es una consulta graphql que volcará toda la meta-información de graphql (nombres de objetos, parámetros, tipos...)
La última línea de código es una consulta de GraphQL que volcará toda la meta-información de GraphQL (nombres de objetos, parámetros, tipos...)
![](<../../.gitbook/assets/image (206).png>)
Si la introspección está habilitada, puedes usar [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) para ver en una GUI todas las opciones.
Si la introspección está habilitada, puedes usar [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) para ver en una interfaz gráfica todas las opciones.
### Consultando
Ahora que sabemos qué tipo de información se guarda dentro de la base de datos, intentemos **extraer algunos valores**.
Ahora que sabemos qué tipo de información se guarda en la base de datos, intentemos **extraer algunos valores**.
En la introspección puedes encontrar **qué objeto puedes consultar directamente** (porque no puedes consultar un objeto solo porque existe). En la siguiente imagen puedes ver que el "_queryType_" se llama "_Query_" y que uno de los campos del objeto "_Query_" es "_flags_", que también es un tipo de objeto. Por lo tanto, puedes consultar el objeto flag.
En la introspección puedes encontrar **qué objeto puedes consultar directamente** (porque no puedes consultar un objeto solo porque existe). En la siguiente imagen puedes ver que el "_queryType_" se llama "_Query_" y que uno de los campos del objeto "_Query_" es "_flags_", que también es un tipo de objeto. Por lo tanto, puedes consultar el objeto de la bandera.
![](../../.gitbook/assets/screenshot-from-2021-03-13-18-17-48.png)
Ten en cuenta que el tipo de consulta "_flags_" es "_Flags_", y este objeto se define como sigue:
Ten en cuenta que el tipo de la consulta "_flags_" es "_Flags_", y este objeto se define de la siguiente manera:
![](../../.gitbook/assets/screenshot-from-2021-03-13-18-22-57.png)
Puedes ver que los objetos "_Flags_" están compuestos por **nombre** y **valor**. Luego puedes obtener todos los nombres y valores de las banderas con la consulta:
Puedes ver que los objetos "_Flags_" están compuestos por **nombre** y **valor**. Luego, puedes obtener todos los nombres y valores de las banderas con la consulta:
```javascript
query={flags{name, value}}
```
Ten en cuenta que en caso de que el **objeto a consultar** sea un **tipo primitivo** como una **cadena de texto** como en el siguiente ejemplo
Ten en cuenta que en caso de que el **objeto a consultar** sea un **tipo primitivo** como **string** como en el siguiente ejemplo
![](<../../.gitbook/assets/image (441).png>)
Puedes consultarla simplemente con:
Puedes consultar simplemente con:
```javascript
query={hiddenFlags}
```
En otro ejemplo donde había 2 objetos dentro del objeto tipo "_Query_": "_user_" y "_users_".\
Si estos objetos no necesitan ningún argumento para buscar, se puede **obtener toda la información** de ellos simplemente **pidiendo** los datos que se desean. En este ejemplo de Internet se podrían extraer los nombres de usuario y contraseñas guardados:
En otro ejemplo donde había 2 objetos dentro del objeto "_Query_": "_user_" y "_users_".\
Si estos objetos no necesitan ningún argumento para buscar, se puede **obtener toda la información de ellos** simplemente **pidiendo** los datos que se desean. En este ejemplo de Internet, se pueden extraer los nombres de usuario y las contraseñas guardadas:
![](<../../.gitbook/assets/image (208).png>)
Sin embargo, en este ejemplo si se intenta hacer esto se obtiene este **error**:
Sin embargo, en este ejemplo, si intentas hacerlo, obtendrás este **error**:
![](<../../.gitbook/assets/image (210).png>)
Parece que de alguna manera buscará usando el argumento "_**uid**_" de tipo _**Int**_.\
De todas formas, ya sabíamos que en la sección de [Enumeración Básica](graphql.md#basic-enumeration) se propuso una consulta que nos mostraba toda la información necesaria: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
Parece que de alguna manera buscará utilizando el argumento "_**uid**_" de tipo _**Int**_.\
De todos modos, ya sabíamos eso, en la sección de [Enumeración Básica](graphql.md#basic-enumeration) se propuso una consulta que nos mostraba toda la información necesaria: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
Si se lee la imagen proporcionada cuando se ejecuta esa consulta, se verá que "_**user**_" tenía el argumento "_**uid**_" de tipo _Int_.
Si lees la imagen proporcionada cuando ejecuto esa consulta, verás que "_**user**_" tenía el **arg** "_**uid**_" de tipo _Int_.
Así que, realizando una fuerza bruta ligera de _**uid**_, encontré que en _**uid**=**1**_ se recuperó un nombre de usuario y una contraseña:\
Entonces, realizando una ligera fuerza bruta de _**uid**_, descubrí que en _**uid**=**1**_ se recuperó un nombre de usuario y una contraseña:\
`query={user(uid:1){user,password}}`
![](<../../.gitbook/assets/image (211).png>)
Tenga en cuenta que **descubrí** que podía pedir los **parámetros** "_**user**_" y "_**password**_" porque si intento buscar algo que no existe (`query={user(uid:1){noExists}}`) obtengo este error:
Ten en cuenta que **descubrí** que podía pedir los **parámetros** "_**user**_" y "_**password**_" porque si intento buscar algo que no existe (`query={user(uid:1){noExists}}`) obtengo este error:
![](<../../.gitbook/assets/image (213).png>)
Y durante la fase de **enumeración** descubrí que el objeto "_**dbuser**_" tenía como campos "_**user**_" y "_**password**_".
Y durante la fase de **enumeración**, descubrí que el objeto "_**dbuser**_" tenía como campos "_**user**_" y "_**password**_.
**Truco de volcado de cadena de consulta (gracias a @BinaryShadow\_)**
Si se puede buscar por un tipo de cadena, como: `query={theusers(description: ""){username,password}}` y se **busca una cadena vacía**, se **volcarán todos los datos**. (_Tenga en cuenta que este ejemplo no está relacionado con el ejemplo de los tutoriales, para este ejemplo suponga que se puede buscar usando "**theusers**" por un campo de cadena llamado "**description**"_).
Si puedes buscar por un tipo de cadena, como: `query={theusers(description: ""){username,password}}` y **buscas una cadena vacía**, se **volcarán todos los datos**. (_Ten en cuenta que este ejemplo no está relacionado con el ejemplo de los tutoriales, para este ejemplo supongamos que puedes buscar usando "**theusers**" por un campo de tipo String llamado "**description**"_).
GraphQL es una tecnología relativamente nueva que está empezando a ganar terreno entre las startups y las grandes corporaciones. Además de la falta de autenticación por defecto, los puntos finales de GraphQL pueden ser vulnerables a otros errores como IDOR.
GraphQL es una tecnología relativamente nueva que está empezando a ganar popularidad entre startups y grandes corporaciones. Aparte de la falta de autenticación por defecto, los puntos finales de GraphQL pueden ser vulnerables a otros errores como IDOR.
### Búsqueda
Para este ejemplo, imagine una base de datos con **personas** identificadas por el correo electrónico y el nombre y **películas** identificadas por el nombre y la calificación. Una **persona** puede ser **amiga** de otras **personas** y una persona puede **tener películas**.
Para este ejemplo, imagina una base de datos con **personas** identificadas por el correo electrónico y el nombre, y **películas** identificadas por el nombre y la calificación. Una **persona** puede ser **amiga** de otras **personas** y una persona puede **tener películas**.
Se pueden **buscar** personas **por** el **nombre** y obtener sus correos electrónicos:
Puedes **buscar** personas **por** el **nombre** y obtener sus correos electrónicos:
```javascript
{
searchPerson(name: "John Doe") {
email
}
searchPerson(name: "John Doe") {
email
}
}
```
Puedes **buscar** personas **por** su **nombre** y obtener las **películas** a las que están **suscritas**:
```javascript
{
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
Ten en cuenta cómo se indica recuperar el `nombre` de las `subscribedMovies` de la persona.
@ -163,91 +271,91 @@ Ten en cuenta cómo se indica recuperar el `nombre` de las `subscribedMovies` de
También puedes **buscar varios objetos al mismo tiempo**. En este caso, se realiza una búsqueda de 2 películas:
```javascript
{
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
}r
```
O incluso **relaciones de varios objetos diferentes usando alias**:
```javascript
{
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
### Mutaciones
**Las mutaciones se utilizan para realizar cambios en el lado del servidor.**
En la **introspección** se pueden encontrar las **mutaciones** **declaradas**. En la siguiente imagen, el "_MutationType_" se llama "_Mutation_" y el objeto "_Mutation_" contiene los nombres de las mutaciones (como "_addPerson_" en este caso):
En la **introspección** puedes encontrar las **mutaciones** **declaradas**. En la siguiente imagen, el "_MutationType_" se llama "_Mutation_" y el objeto "_Mutation_" contiene los nombres de las mutaciones (como "_addPerson_" en este caso):
![](../../.gitbook/assets/screenshot-from-2021-03-13-18-26-27.png)
Para este ejemplo, imagina una base de datos con **personas** identificadas por el correo electrónico y el nombre y **películas** identificadas por el nombre y la calificación. Una **persona** puede ser **amiga** de otras **personas** y una persona puede **tener películas**.
Para este ejemplo, imagina una base de datos con **personas** identificadas por el correo electrónico y el nombre, y **películas** identificadas por el nombre y la calificación. Una **persona** puede ser **amiga** de otras **personas** y una persona puede **tener películas**.
Una mutación para **crear nuevas** películas dentro de la base de datos puede ser como la siguiente (en este ejemplo, la mutación se llama `addMovie`):
```javascript
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
}
```
**Nota cómo tanto los valores como el tipo de datos se indican en la consulta.**
**Ten en cuenta cómo se indican tanto los valores como el tipo de datos en la consulta.**
También puede haber una **mutación** para **crear** **personas** (llamada `addPerson` en este ejemplo) con amigos y archivos (nota que los amigos y películas tienen que existir antes de crear una persona relacionada con ellos):
También puede haber una **mutación** para **crear** **personas** (llamada `addPerson` en este ejemplo) con amigos y archivos (ten en cuenta que los amigos y las películas deben existir antes de crear una persona relacionada con ellos):
```javascript
mutation {
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
}
```
### Ataque de fuerza bruta en lote en 1 solicitud de API
### Ataque de fuerza bruta en 1 solicitud de API
Esta información fue tomada de [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
La autenticación a través de la API de GraphQL con **el envío simultáneo de muchas consultas con diferentes credenciales** para verificarla. Es un ataque de fuerza bruta clásico, pero ahora es posible enviar más de un par de inicio de sesión/contraseña por solicitud HTTP debido a la función de agrupación de GraphQL. Este enfoque engañaría a las aplicaciones externas de monitoreo de velocidad para que crean que todo está bien y que no hay un bot de fuerza bruta intentando adivinar contraseñas.
Autenticación a través de la API de GraphQL con **el envío simultáneo de muchas consultas con diferentes credenciales** para verificarla. Es un ataque de fuerza bruta clásico, pero ahora es posible enviar más de un par de inicio de sesión/contraseña por solicitud HTTP debido a la función de agrupación de GraphQL. Este enfoque engañaría a las aplicaciones de monitoreo de velocidad externas haciéndoles creer que todo está bien y que no hay un bot de fuerza bruta intentando adivinar contraseñas.
A continuación, se muestra la demostración más simple de una solicitud de autenticación de aplicación, con **3 pares de correo electrónico/contraseña diferentes a la vez**. Obviamente, es posible enviar miles en una sola solicitud de la misma manera:
A continuación, se muestra la demostración más simple de una solicitud de autenticación de la aplicación, con **3 pares de correo electrónico/contraseña diferentes a la vez**. Obviamente, es posible enviar miles en una sola solicitud de la misma manera:
![](<../../.gitbook/assets/image (182) (1).png>)
@ -259,19 +367,43 @@ Como podemos ver en la captura de pantalla de la respuesta, las primeras y terce
Cada vez más **los puntos finales de GraphQL están deshabilitando la introspección**. Sin embargo, los errores que GraphQL arroja cuando se recibe una solicitud inesperada son suficientes para que herramientas como [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) puedan recrear la mayor parte del esquema.
Además, la extensión de Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observa las solicitudes de API de GraphQL que pasan por Burp** y **construye** un **esquema** interno de GraphQL con cada nueva consulta que ve. También puede exponer el esquema para GraphiQL y Voyager. La extensión devuelve una respuesta falsa cuando recibe una consulta de introspección. Como resultado, GraphQuail muestra todas las consultas, argumentos y campos disponibles para su uso dentro de la API. Para obtener más información, [**consulte esto**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
Además, la extensión de Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observa las solicitudes de la API de GraphQL que pasan por Burp** y **construye** un **esquema** interno de GraphQL con cada nueva consulta que ve. También puede exponer el esquema para GraphiQL y Voyager. La extensión devuelve una respuesta falsa cuando recibe una consulta de introspección. Como resultado, GraphQuail muestra todas las consultas, argumentos y campos disponibles para su uso dentro de la API. Para obtener más información, [**consulte esto**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
### Bypassing defensas de introspección de GraphQL <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
Si no puedes hacer que se ejecuten consultas de introspección para la API que estás probando, intenta insertar un **carácter especial después de la palabra clave `__schema`**.
Cuando los desarrolladores deshabilitan la introspección, podrían usar una expresión regular para excluir la palabra clave `__schema` en las consultas. Deberías probar caracteres como **espacios**, **saltos de línea** y **comas**, ya que son **ignorados** por GraphQL pero no por una expresión regular defectuosa.
Por lo tanto, si el desarrollador solo ha excluido `__schema{`, entonces la siguiente consulta de introspección no sería excluida.
```bash
#Introspection query with newline
{
"query": "query{__schema
{queryType{name}}}"
}
```
Si esto no funciona, intenta ejecutar la sonda a través de un método de solicitud alternativo, ya que la introspección puede estar deshabilitada solo para POST. Prueba una solicitud GET o una solicitud POST con un tipo de contenido de `x-www-form-urlencoded`.
### Estructuras de GraphQL filtradas
Si la introspección está deshabilitada, intenta buscar en el código fuente del sitio web. Las consultas a menudo se cargan previamente en el navegador como bibliotecas de JavaScript. Estas consultas predefinidas pueden revelar información poderosa sobre el esquema y el uso de cada objeto y función. La pestaña `Sources` de las herramientas para desarrolladores puede buscar en todos los archivos para enumerar dónde se guardan las consultas. A veces, incluso las consultas protegidas por el administrador ya están expuestas.
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
## CSRF en GraphQL
Si no sabe qué es CSRF, lea la siguiente página:
Si no sabes qué es CSRF, lee la siguiente página:
{% content-ref url="../../pentesting-web/csrf-cross-site-request-forgery.md" %}
[csrf-cross-site-request-forgery.md](../../pentesting-web/csrf-cross-site-request-forgery.md)
{% endcontent-ref %}
Allí podrá encontrar varios puntos finales de GraphQL **configurados sin tokens CSRF.**
Allí podrás encontrar varios puntos finales de GraphQL **configurados sin tokens CSRF**.
Tenga en cuenta que las solicitudes de GraphQL generalmente se envían a través de solicitudes POST utilizando el tipo de contenido **`application/json`**.
Ten en cuenta que las solicitudes de GraphQL generalmente se envían a través de solicitudes POST utilizando el Content-Type **`application/json`**.
```javascript
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
```
@ -279,59 +411,76 @@ Sin embargo, la mayoría de los puntos finales de GraphQL también admiten solic
```javascript
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
```
Por lo tanto, como las solicitudes CSRF como las anteriores se envían sin solicitudes previas, es posible realizar cambios en el GraphQL abusando de un CSRF.
Por lo tanto, dado que las solicitudes CSRF como las anteriores se envían **sin solicitudes de preflight**, es posible **realizar** **cambios** en GraphQL abusando de un CSRF.
Sin embargo, tenga en cuenta que el nuevo valor predeterminado de la cookie de la bandera "samesite" de Chrome es "Lax". Esto significa que la cookie solo se enviará desde un sitio web de terceros en solicitudes GET.
Sin embargo, ten en cuenta que el nuevo valor predeterminado de la cookie `samesite` en Chrome es `Lax`. Esto significa que la cookie solo se enviará desde un sitio web de terceros en solicitudes GET.
También es posible enviar la solicitud de consulta como una solicitud GET y es posible que el token CSRF no se valide en una solicitud GET.
Ten en cuenta que generalmente es posible enviar la **solicitud de consulta** también como una solicitud **GET** y es posible que el token CSRF no se valide en una solicitud GET.
Además, mediante un ataque XS-Search, es posible exfiltrar contenido del punto final GraphQL abusando de las credenciales del usuario.
Además, abusando de un [ataque **XS-Search**](../../pentesting-web/xs-search.md), podría ser posible filtrar contenido del punto final de GraphQL abusando de las credenciales del usuario.
Para obtener más información, consulte la publicación original aquí.
Para obtener más información, **consulta la** [**publicación original aquí**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html).
Autorización en GraphQL
## Autorización en GraphQL
Muchas funciones de GraphQL definidas en el punto final solo pueden verificar la autenticación del solicitante pero no la autorización.
La modificación de las variables de entrada de la consulta podría llevar a la filtración de detalles de cuenta confidenciales.
Modificar las variables de entrada de la consulta podría llevar a la filtración de detalles sensibles de la cuenta [filtrada](https://hackerone.com/reports/792927).
La mutación incluso podría llevar a la toma de control de la cuenta intentando modificar los datos de otra cuenta.
Incluso la mutación podría llevar a la toma de control de la cuenta al intentar modificar los datos de otra cuenta.
```javascript
{
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}
```
### Bypass de autorización en GraphQL
La concatenación de consultas puede saltarse un sistema de autenticación débil.
[Encadenar consultas](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) puede evadir un sistema de autenticación débil.
En el siguiente ejemplo se puede ver que la operación es "forgotPassword" y que solo debería ejecutar la consulta de forgotPassword asociada a ella. Esto se puede saltar agregando una consulta al final, en este caso agregamos "register" y una variable de usuario para que el sistema se registre como un nuevo usuario.
En el siguiente ejemplo, se puede observar que la operación es "forgotPassword" y que solo debería ejecutar la consulta forgotPassword asociada a ella. Esto se puede evadir agregando una consulta al final, en este caso agregamos "register" y una variable de usuario para que el sistema lo registre como un nuevo usuario.
<figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
## Estructuras de GraphQL filtradas
## Bypass de límite de velocidad utilizando alias
Si la introspección está deshabilitada, intente mirar el código fuente del sitio web. Las consultas a menudo se precargan en el navegador como bibliotecas de JavaScript. Estas consultas preescritas pueden revelar información poderosa sobre el esquema y el uso de cada objeto y función. La pestaña `Sources` de las herramientas para desarrolladores puede buscar en todos los archivos para enumerar dónde se guardan las consultas. A veces, incluso las consultas protegidas por el administrador ya están expuestas.
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
Normalmente, los objetos de GraphQL no pueden contener múltiples propiedades con el mismo nombre. Los alias te permiten evadir esta restricción al **nombrar explícitamente las propiedades que deseas** que la API devuelva. Puedes usar alias para devolver **múltiples instancias del mismo** tipo de objeto en una sola solicitud.
Para obtener más información sobre los alias de GraphQL, consulta [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
Si bien los alias están destinados a limitar la cantidad de llamadas a la API que debes realizar, también se pueden utilizar para realizar un ataque de fuerza bruta en un punto final de GraphQL.
Muchos puntos finales tendrán algún tipo de **limitador de velocidad para evitar ataques de fuerza bruta**. Algunos limitadores de velocidad funcionan en función del **número de solicitudes HTTP** recibidas en lugar del número de operaciones realizadas en el punto final. Debido a que los alias te permiten enviar múltiples consultas en un solo mensaje HTTP, pueden evadir esta restricción.
El ejemplo simplificado a continuación muestra una serie de **consultas con alias que verifican si los códigos de descuento de la tienda son válidos**. Esta operación podría evadir el límite de velocidad, ya que es una sola solicitud HTTP, aunque potencialmente se podría utilizar para verificar una gran cantidad de códigos de descuento al mismo tiempo.
```bash
#Request with aliased queries
query isValidDiscount($code: Int) {
isvalidDiscount(code:$code){
valid
}
isValidDiscount2:isValidDiscount(code:$code){
valid
}
isValidDiscount3:isValidDiscount(code:$code){
valid
}
}
```
## Herramientas
### Escáneres de vulnerabilidades
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Conjunto de herramientas que se pueden utilizar para obtener esquemas y buscar datos sensibles, probar la autorización, forzar esquemas y encontrar rutas hacia un tipo determinado.
* [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): Se puede utilizar como una extensión independiente o de [Burp](https://github.com/doyensec/inql).
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Se puede utilizar como cliente CLI también para automatizar ataques.
* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): Herramienta que enumera las diferentes formas de llegar a un tipo determinado en un esquema de GraphQL.
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Conjunto de herramientas que se pueden utilizar para obtener esquemas y buscar datos sensibles, probar la autorización, forzar esquemas y encontrar rutas hacia un tipo específico.
* [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): Puede utilizarse como una extensión independiente o de [Burp](https://github.com/doyensec/inql).
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Puede utilizarse como un cliente de línea de comandos para automatizar ataques.
* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): Herramienta que enumera las diferentes formas de llegar a un tipo específico en un esquema de GraphQL.
### Clientes
* [https://github.com/graphql/graphiql](https://github.com/graphql/graphiql): Cliente GUI
* [https://altair.sirmuel.design/](https://altair.sirmuel.design/): Cliente GUI
* [https://github.com/graphql/graphiql](https://github.com/graphql/graphiql): Cliente de interfaz gráfica de usuario (GUI).
* [https://altair.sirmuel.design/](https://altair.sirmuel.design/): Cliente de GUI.
### Pruebas automáticas
@ -345,17 +494,18 @@ file:* query
* [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)
* [**https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4**](https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4)
* [**http://ghostlulz.com/api-hacking-graphql/**](http://ghostlulz.com/api-hacking-graphql/)
* [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.m**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md)
* [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md)
* [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)
* [**https://portswigger.net/web-security/graphql**](https://portswigger.net/web-security/graphql)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección de exclusivos [**NFTs**](https://opensea.io/collection/the-peass-family)
* Consigue el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PR a** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **y** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos.
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com).
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PR al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>