Network Layer Security - SSL Pinning bypass
este módulo de DVIA-v2 tiene 5 opciones, cada una simula un escenario distinto de la capa de red:
- Send over HTTP - manda la data en texto plano, sin cifrado
- Send over HTTPS - usa TLS estándar con cualquier cert de una CA válida, sin pinning
- Send using Certificate Pinning - la app tiene el certificado embebido y lo compara exacto contra el del servidor
- Send using Public Key Pinning - variante del pinning pero fija solo el hash de la llave pública en vez del cert completo
- App Transport Security (ATS) - política de iOS que exige TLS 1.2+ a nivel de sistema, este lo dejamos anotado y se documenta a fondo en una página aparte dedicada a ATS, para no repetir trabajo
vamos a ir en ese mismo orden
Configuración de Burp
antes de entrar a los retos dejamos Burp listo: configuramos el proxy en el dispositivo apuntando a la IP y puerto de Burp, e instalamos el certificado de Burp como confiable en el dispositivo
primero entramos a Burp Suite, a la sección de Proxy settings

una vez ahí, en Proxy listeners, le damos click en Add

agregamos el nuevo puerto y seleccionamos la opción All Interfaces, y le damos OK

Nos debe quedar de esta manera

ahora vamos a configurar la conexión en el iPhone, entramos a nuestro WiFi

entramos a la configuración del proxy

ponemos manual, y llenamos los campos de servidor y puerto: en servidor va la IP de nuestro PC donde está Burp, y en puerto el que configuramos. le damos en guardar

Vamos a instalar el certificado de Burp: abrimos Safari y entramos a http://burp

vamos a CA Certificate y le damos en permitir

y debe salirnos un mensaje como el siguiente

ahora vamos a Ajustes, y vemos que nos aparece la opción de Perfil descargado

y nos sale esta pantalla, le damos en Instalar

nos sale este mensaje, le damos de nuevo en Instalar

y una vez más en Instalar

y con esto ya nos sale verificado

y al darle en Listo, ya vemos el perfil agregado

pero todavía nos falta darle la confianza total al certificado
vamos a Ajustes →General →Información, y bajamos hasta la opción Conf. certificados de confianza

ahí vemos PortSwigger CA con el switch apagado

lo activamos, nos sale una ventana emergente, y le damos en Continuar

ahora vamos a un navegador y entramos a https://example.com, y vemos que ya tenemos el tráfico

ahora vamos con la aplicación, y el reto dice:
Hay tres formas de enviar datos a través de la red: usar HTTP, usar HTTPS o usar SSL/fijación de certificados para verificar un certificado codificado con el certificado proporcionado por el servidor para prevenir ataques MITM. Tu tarea es interceptar la información que se envía a través de la red cuando se toca el botón ‘Enviar’ en los tres casos.

Send over HTTP
el reto dice: manda la información sin cifrar, en texto plano
aquí no hace falta bypass, solo dejamos Burp escuchando y mandamos la petición

agregamos la información y le damos en SEND OVER HTTP y con esto vemos que podemos ver el tráfico de los datos ingresados y un mensaje en la aplicación que nos dice Solicitud enviada, ¡cuidado!

con esto queda evidenciado el peor escenario posible, cualquiera en la red ve la data sin necesidad de instalar ni un certificado
Send over HTTPS
el reto dice: manda la información usando TLS estándar, sin pinning. es un caso muy similar al anterior, solo que aquí la app sí valida el certificado, pero como ya contamos con el certificado de Burp instalado, el tráfico se ve directo, sin necesidad de Frida ni Objection

Send using Certificate Pinning
El SSL Pinning es un mecanismo que usan las apps para asegurarse que solo confían en un certificado específico (o una llave pública específica), en vez de confiar en cualquier certificado válido que venga de una CA. Esto es importante porque:
- Evita ataques Man-in-the-Middle (MITM), aunque el atacante tenga un certificado válido instalado en el dispositivo.
- Protege el tráfico de ser interceptado por herramientas como Burp Suite o mitmproxy.
- Dificulta el análisis dinámico de las comunicaciones de la app durante un pentest.
el reto dice: la aplicación tiene un mecanismo de Certificate Pinning implementado de forma insuficiente, hay que evadirlo y capturar el tráfico
al darle en la opción SEND USING CERTIFICATE PINNING, vemos que nos sale un mensaje que nos dice La validación del certificado ha fallado. ¡Tendrás que hacerlo mejor! y no vemos trafico en el Burp

revisamos si el dispositivo está conectado
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─# frida-ls-devices
Id Type Name OS
---------------------------------------- ------ --------------- ---------------------
local local Local System Kali GNU/Linux 2026.2
137e70f9805dfaa6291989bfed24126fc4abdd5f usb iOS Device iPhone OS 16.7.16
barebone remote GDB Remote Stub
socket remote Local Socket
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─#
buscamos el identificador de la aplicación
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─# frida-ps -Uai
PID Name Identifier
---- --------------- ---------------------------------
728 Calendario com.apple.mobilecal
1169 Configuración com.apple.Preferences
1160 DVIA-v2 com.highaltitudehacks.DVIAswiftv2
678 Dopamine com.opa334.Dopamine.8MP3V4USL6
1165 Filza com.tigisoftware.Filza
1164 Safari com.apple.mobilesafari
1167 TestFlight com.apple.TestFlight
1166 TrollStore Lite com.opa334.TrollStoreLite
- App Store com.apple.AppStore
- Archivos com.apple.DocumentsApp
- Atajos com.apple.shortcuts
- Bolsa com.apple.stocks
- Brújula com.apple.compass
- Calculadora com.apple.calculator
- Casa com.apple.Home
- Clima com.apple.weather
- Consejos com.apple.tips
- Contactos com.apple.MobileAddressBook
- Cámara com.apple.camera
- Drive com.google.Drive
- Encontrar com.apple.findmy
- FaceTime com.apple.facetime
- Fitness com.apple.Fitness
- FortiClientVPN com.fortinet.forticlient.vpn
- Fotos com.apple.mobileslideshow
- Freeform com.apple.freeform
- Libros com.apple.iBooks
- Lulo STG co.com.lulobank.stg.8MP3V4USL6
- Lupa com.apple.Magnifier
- Mail com.apple.mobilemail
- Mapas com.apple.Maps
- Medición com.apple.measure
- Mensajes com.apple.MobileSMS
- Música com.apple.Music
- NewTerm ws.hbang.Terminal
- Notas com.apple.mobilenotes
- Notas de voz com.apple.VoiceMemos
- Podcasts com.apple.podcasts
- Recordatorios com.apple.reminders
- Reloj com.apple.mobiletimer
- Salud com.apple.Health
- Sileo org.coolstar.SileoStore
- TV com.apple.tv
- Teléfono com.apple.mobilephone
- Traducir com.apple.Translate
- Wallet com.apple.Passbook
- Watch com.apple.Bridge
- Zebra xyz.willy.Zebra
- iTunes Store com.apple.MobileStore
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─#
Método 1: Objection
usamos la herramienta Objection para realizar el bypass al pinning
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─# objection -g "DVIA-v2" explore
DeprecationWarning: The option 'gadget' is deprecated. Please use '-n' or '--name' instead
DeprecationWarning: The command 'explore' is deprecated. Use 'objection start' instead of 'objection explore'
_ _ _ _
___| |_|_|___ ___| |_|_|___ ___
| . | . | | -_| _| _| | . | |
|___|___| |___|___|_| |_|___|_|_|
|___|(object)inject(ion) v1.12.5
Runtime Mobile Exploration
by: @leonjza from @sensepost
[tab] for command suggestions
DVIA-v2 (run) on (iPhone OS: 16.7.16) [usb] #
una vez adentro, ejecutamos el comando ios sslpinning disable, que desactiva el pinning en la app
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─# objection -g "DVIA-v2" explore
DeprecationWarning: The option 'gadget' is deprecated. Please use '-n' or '--name' instead
DeprecationWarning: The command 'explore' is deprecated. Use 'objection start' instead of 'objection explore'
_ _ _ _
___| |_|_|___ ___| |_|_|___ ___
| . | . | | -_| _| _| | . | |
|___|___| |___|___|_| |_|___|_|_|
|___|(object)inject(ion) v1.12.5
Runtime Mobile Exploration
by: @leonjza from @sensepost
[tab] for command suggestions
DVIA-v2 (run) on (iPhone OS: 16.7.16) [usb] # ios sslpinning disable
(agent) Hooking common framework methods
(agent) Found NSURLSession based classes. Hooking known pinning methods.
(agent) Hooking lower level SSL methods
(agent) Hooking lower level TLS methods
(agent) Hooking BoringSSL methods
(agent) Registering job 648846. Name: ios-sslpinning-disable
DVIA-v2 (run) on (iPhone OS: 16.7.16) [usb] #
volvemos al reto para probar si el tráfico ya se ve en Burp
en el dispositivo, le damos en SEND USING CERTIFICATE PINNING
al tocar el botón del reto, la app intenta la conexión y ahí vemos dos líneas nuevas en la terminal: Called SSL_CTX_set_custom_verify() confirma que la app registró su callback de validación de certificado justo en ese momento, y Called custom SSL context verify callback, returning SSL_VERIFY_NONE confirma que el hook de Objection interceptó esa llamada y forzó el resultado a “sin verificación” o sea, el pinning quedó desactivado exactamente cuando la app intentó validar el certificado.
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─# objection -g "DVIA-v2" explore
DeprecationWarning: The option 'gadget' is deprecated. Please use '-n' or '--name' instead
DeprecationWarning: The command 'explore' is deprecated. Use 'objection start' instead of 'objection explore'
_ _ _ _
___| |_|_|___ ___| |_|_|___ ___
| . | . | | -_| _| _| | . | |
|___|___| |___|___|_| |_|___|_|_|
|___|(object)inject(ion) v1.12.5
Runtime Mobile Exploration
by: @leonjza from @sensepost
[tab] for command suggestions
DVIA-v2 (run) on (iPhone OS: 16.7.16) [usb] # ios sslpinning disable
(agent) Hooking common framework methods
(agent) Found NSURLSession based classes. Hooking known pinning methods.
(agent) Hooking lower level SSL methods
(agent) Hooking lower level TLS methods
(agent) Hooking BoringSSL methods
(agent) Registering job 648846. Name: ios-sslpinning-disable
(agent) [648846] Called SSL_CTX_set_custom_verify(), setting custom callback.
(agent) [648846] Called custom SSL context verify callback, returning SSL_VERIFY_NONE.
DVIA-v2 (run) on (iPhone OS: 16.7.16) [usb] #
vemos que ya no sale la ventana emergente, y el tráfico aparece en Burp Suite

Método 2: Frida con script propio
ahora vamos a hacer el mismo bypass pero con un script de Frida directo, sin usar Objection, para documentar las dos formas
primero dejamos el dispositivo en el mismo estado, conectado y con el proxy de Burp configurado
Este script ataca el pinning a un nivel más bajo que el anterior, en vez de hookear SecTrustEvaluate (que es parte del framework Security de iOS), va directo a BoringSSL, la librería que Apple usa internamente para el handshake TLS desde iOS 13. hookea SSL_set_custom_verify, que es la función donde la app registra su callback de validación de certificado, y la reemplaza por una que siempre retorna SSL_VERIFY_NONE (0), o sea, que nunca rechaza el certificado sin importar qué mande el servidor. también parcha SSL_get_psk_identity por si la app usa autenticación PSK. como actúa más abajo en la pila que el hook anterior, suele funcionar incluso cuando el pinning está implementado de forma custom o cuando el hook a SecTrustEvaluate no alcanza a cubrirlo.
Fuente original: codeshare.frida.re/@federicodotta/ios13-pinning-bypass
try {
Module.ensureInitialized("libboringssl.dylib");
} catch (err) {
console.log("libboringssl.dylib no cargado, cargando manualmente...");
Module.load("libboringssl.dylib");
}
var SSL_VERIFY_NONE = 0;
var boringssl = Process.getModuleByName("libboringssl.dylib");
var ssl_set_custom_verify = new NativeFunction(
boringssl.getExportByName("SSL_set_custom_verify"),
'void', ['pointer', 'int', 'pointer']
);
var ssl_get_psk_identity = new NativeFunction(
boringssl.getExportByName("SSL_get_psk_identity"),
'pointer', ['pointer']
);
var ssl_verify_result_t = new NativeCallback(function (ssl, out_alert) {
return SSL_VERIFY_NONE;
}, 'int', ['pointer', 'pointer']);
Interceptor.replace(ssl_set_custom_verify, new NativeCallback(function (ssl, mode, callback) {
ssl_set_custom_verify(ssl, mode, ssl_verify_result_t);
}, 'void', ['pointer', 'int', 'pointer']));
Interceptor.replace(ssl_get_psk_identity, new NativeCallback(function (ssl) {
return Memory.allocUtf8String("notarealPSKidentity");
}, 'pointer', ['pointer']));
console.log("[+] Bypass de pinning (BoringSSL) cargado correctamente");
con el archivo listo, ejecutamos
┌──(root㉿angussMoody)-[/mnt/angussMoody]
└─# frida -U -f com.highaltitudehacks.DVIAswiftv2 -l script.js
____
/ _ | Frida 17.15.3 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to iOS Device (id=137e70f9805dfaa6291989bfed24126fc4abdd5f)
Spawning `com.highaltitudehacks.DVIAswiftv2`...
libboringssl.dylib no cargado, cargando manualmente...
[+] Bypass de pinning (BoringSSL) cargado correctamente
Spawned `com.highaltitudehacks.DVIAswiftv2`. Resuming main thread!
[iOS Device::com.highaltitudehacks.DVIAswiftv2 ]->
volvemos a Burp y confirmamos que el tráfico se ve igual que con Objection

asi quedan documentadas las dos formas, con Objection y con Frida directo
Send using Public Key Pinning
para este reto usamos el mismo proceso que en Certificate Pinning, tanto con Objection como con el script.js de Frida, sin necesidad de cambiar nada. la razón es que ninguno de los dos bypasses distingue entre comparar el certificado completo o solo el hash de la llave pública ios sslpinning disable desactiva la validación en todos los puntos donde la app pueda estar chequeando esto, y el script de BoringSSL actúa un paso antes, en SSL_set_custom_verify, que es la función que decide si la conexión es confiable o no, sin importar qué método de comparación use la app después. como el bypass ocurre antes de que se ejecute esa comparación, da igual si la app está validando el certificado completo o solo la llave pública: nunca llega a hacer esa validación.
Al realizar la validación de SEND USING PUBLIC KEY PINNING vemos que podemos tener el tráfico desde la aplicación.

App Transport Security (ATS)
App Transport Security es la política que Apple exige a nivel de sistema desde iOS 9, obligando a que toda conexión de red use TLS 1.2 o superior salvo que la app declare excepciones explícitas en su Info.plist. a diferencia de los retos anteriores, que se resuelven en tiempo de ejecución con Frida/Objection, este análisis es principalmente estático: se revisa el Info.plist de la app buscando banderas como NSAllowsArbitraryLoads desactiva ATS por completo, excepciones de dominio con NSExceptionAllowsInsecureHTTPLoads permite HTTP plano para dominios específicos, y la versión mínima de TLS permitida por excepción. por su naturaleza distinta al resto de este módulo, este reto lo vamos a documentar en una página aparte, dedicada solo a ATS.
