iOS Pentesting

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Conceptos básicos de iOS

iOS Basics

Entorno de pruebas

In this page you can find information about the iOS simulator, emulators and jailbreaking:

iOS Testing Environment

Análisis inicial

Operaciones básicas de pruebas en iOS

During the testing several operations are going to be suggested (connect to the device, read/write/upload/download files, use some tools…). Therefore, if you don’t know how to perform any of these actions please, start reading the page:

iOS Basic Testing Operations

Tip

For the following steps the app should be installed in the device and should have already obtained the IPA file of the application.
Read the Basic iOS Testing Operations page to learn how to do this.

Análisis estático básico

Some interesting iOS - IPA files decompilers:

It’s recommended to use the tool MobSF to perform an automatic Static Analysis to the IPA file.

Identificación de las protecciones presentes en el binario:

  • PIE (Position Independent Executable): When enabled, the application loads into a random memory address every-time it launches, making it harder to predict its initial memory address.
otool -hv <app-binary> | grep PIE   # It should include the PIE flag
  • Stack Canaries: To validate the integrity of the stack, a ‘canary’ value is placed on the stack before calling a function and is validated again once the function ends.
otool -I -v <app-binary> | grep stack_chk   # It should include the symbols: stack_chk_guard and stack_chk_fail
  • ARC (Automatic Reference Counting): To prevent common memory corruption flaws
otool -I -v <app-binary> | grep objc_release   # It should include the _objc_release symbol
  • Encrypted Binary: The binary should be encrypted
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # The cryptid should be 1

Identificación de funciones sensibles/inseguras

  • Weak Hashing Algorithms
# On the iOS device
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"

# On linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
  • Insecure Random Functions
# On the iOS device
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"

# On linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
  • Insecure ‘Malloc’ Function
# On the iOS device
otool -Iv <app> | grep -w "_malloc"

# On linux
grep -iER "_malloc"
  • Insecure and Vulnerable Functions
# On the iOS device
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"

# On linux
grep -R "_gets"
grep -iER "_memcpy"
grep -iER "_strncpy"
grep -iER "_strlen"
grep -iER "_vsnprintf"
grep -iER "_sscanf"
grep -iER "_strtok"
grep -iER "_alloca"
grep -iER "_sprintf"
grep -iER "_printf"
grep -iER "_vsprintf"

Métodos comunes de detección de jailbreak

  • File System Checks: Busca la presencia de archivos y directorios comunes de jailbreak, como /Applications/Cydia.app o /Library/MobileSubstrate/MobileSubstrate.dylib.
  • Sandbox Violations: Intenta acceder a áreas restringidas del sistema de archivos, lo cual debería estar bloqueado en dispositivos no-jailbroken.
  • API Checks: Comprueba si es posible usar llamadas prohibidas como fork() para crear un proceso hijo o system() para ver si /bin/sh existe.
  • Process Checks: Monitorea la presencia de procesos relacionados con jailbreak conocidos, como Cydia, Substrate, o ssh.
  • Kernel Exploits: Verifica la presencia de exploits de kernel que son comúnmente usados en jailbreaks.
  • Environment Variables: Inspecciona variables de entorno en busca de signos de jailbreak, como DYLD_INSERT_LIBRARIES.
  • Libraries Check: Comprueba las libs que están cargadas en el proceso de la app.
  • Check schemes: Como canOpenURL(URL(string: "cydia://")).

Métodos comunes de detección Anti-Debugging

  • Check for Debugger Presence: Usa sysctl u otros métodos para comprobar si hay un debugger adjunto.
  • Anti-Debugging APIs: Busca llamadas a APIs anti-debugging como ptrace o SIGSTOP como ptrace(PT_DENY_ATTACH, 0, 0, 0).
  • Timing Checks: Mide el tiempo que tardan ciertas operaciones y busca discrepancias que puedan indicar depuración.
  • Memory Checks: Inspecciona la memoria en busca de artefactos u modificaciones conocidas de debuggers.
  • Environment Variables: Comprueba variables de entorno que puedan indicar una sesión de debugging.
  • Mach Ports: Detecta si los mach exception ports están siendo usados por debuggers.

Anti-Debugging & Anti-Tamper Techniques (Layered Checks)

Las apps reales a menudo encadenan comprobaciones pre-exec, on-attach y continuas. Patrones comunes a buscar (y cómo neutralizarlos durante las pruebas):

  • Private API side-channel fingerprinting: private launch APIs (p. ej., SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions) se abusan para sondear bundle IDs instalados (com.opa334.TrollStore, org.coolstar.SileoStore, com.tigisoftware.Filza, etc.) basándose en códigos de retorno/logging. Hookea la llamada y sanea argumentos/valores de retorno para emular un dispositivo limpio.
  • Self-attestation via code-signing state: csops() con CS_OPS_ENTITLEMENTS_BLOB lee entitlements; valores inesperados disparan un exit. Combínalo con checks de integridad (CRC32/MD5 de recursos, validación de certificado, metadata Mach-O como LC_ENCRYPTION_INFO_64) para detectar re-signing o parcheo. Instrumenta estas rutinas y fuerza resultados “esperados” durante el análisis.
  • Kill-on-attach: ptrace(PT_DENY_ATTACH) combinado con abort()/exit() al adjuntarse. Bypass neutralizando la ruta de terminación o hookeando ptrace para que tenga éxito sin imponer la denegación.
  • Crash forensics sabotage: sobrescribe registros de CPU antes de hacer crash para destruir backtraces. Prefiere breakpoints/hooks más temprano en la ruta de detección en lugar de depender de logs de crash.
  • Jetsam-based termination: presión de memoria deliberada para desencadenar jetsam, que no produce un log de crash normal. Busca asignaciones grandes alrededor de la lógica de detección y limítalas/córtalas para conservar logs.
  • Continuous checks with delayed enforcement: timers de heartbeat re-ejecutan detección y aplican la medida más tarde. Traza timers/dispatch sources y mantiene el proceso vivo evitando la ruta de kill diferido.

Análisis dinámico básico

Check out the dynamic analysis that MobSF perform. You will need to navigate through the different views and interact with them but it will be hooking several classes on doing other things and will prepare a report once you are done.

Listar apps instaladas

Use the command frida-ps -Uai to determine the bundle identifier of the installed apps:

$ frida-ps -Uai
PID  Name                 Identifier
----  -------------------  -----------------------------------------
6847  Calendar             com.apple.mobilecal
6815  Mail                 com.apple.mobilemail
-  App Store            com.apple.AppStore
-  Apple Store          com.apple.store.Jolly
-  Calculator           com.apple.calculator
-  Camera               com.apple.camera
-  iGoat-Swift          OWASP.iGoat-Swift

Basic Enumeration & Hooking

Aprende cómo enumerar los componentes de la aplicación y cómo fácilmente hook methods and classes con objection:

iOS Hooking With Objection

IPA Structure

La estructura de un IPA file es esencialmente la de un zipped package. Renombrando su extensión a .zip, puede descomprimirse para revelar su contenido. Dentro de esta estructura, un Bundle representa una aplicación completamente empaquetada lista para la instalación. En su interior encontrarás un directorio llamado <NAME>.app, que encapsula los recursos de la aplicación.

  • Info.plist: Este archivo contiene detalles de configuración específicos de la aplicación.
  • _CodeSignature/: Este directorio incluye un archivo plist que contiene una firma, asegurando la integridad de todos los archivos en el bundle.
  • Assets.car: Un archivo comprimido que almacena archivos de assets como iconos.
  • Frameworks/: Esta carpeta alberga las bibliotecas nativas de la aplicación, que pueden estar en forma de archivos .dylib o .framework.
  • PlugIns/: Esto puede incluir extensiones de la aplicación, conocidas como archivos .appex, aunque no siempre están presentes. * Core Data: Se utiliza para guardar los datos permanentes de tu aplicación para uso offline, para cachear datos temporales y para añadir funcionalidad de deshacer en tu app en un solo dispositivo. Para sincronizar datos entre múltiples dispositivos bajo una misma cuenta iCloud, Core Data refleja automáticamente tu esquema en un contenedor CloudKit.
  • PkgInfo: El archivo PkgInfo es una manera alternativa de especificar los códigos de tipo y creador de tu aplicación o bundle.
  • en.lproj, fr.proj, Base.lproj: Son los paquetes de idioma que contienen recursos para esos idiomas específicos, y un recurso por defecto en caso de que un idioma no sea soportado.
  • Security: El directorio _CodeSignature/ desempeña un papel crítico en la seguridad de la app al verificar la integridad de todos los archivos incluidos mediante firmas digitales.
  • Asset Management: El archivo Assets.car utiliza compresión para gestionar eficientemente los assets gráficos, crucial para optimizar el rendimiento de la aplicación y reducir su tamaño total.
  • Frameworks and PlugIns: Estos directorios subrayan la modularidad de las aplicaciones iOS, permitiendo a los desarrolladores incluir bibliotecas de código reutilizable (Frameworks/) y extender la funcionalidad de la app (PlugIns/).
  • Localization: La estructura soporta múltiples idiomas, facilitando el alcance global de la aplicación al incluir recursos para paquetes de idiomas específicos.

Info.plist

El Info.plist sirve como piedra angular para las aplicaciones iOS, encapsulando datos de configuración clave en forma de pares key-value. Este archivo es obligatorio no solo para aplicaciones sino también para app extensions y frameworks incluidos en el bundle. Está estructurado en formato XML o binario y contiene información crítica que va desde permisos de la app hasta configuraciones de seguridad. Para una exploración detallada de las claves disponibles, se puede consultar la Apple Developer Documentation.

Para quienes desean trabajar con este archivo en un formato más accesible, la conversión a XML se puede lograr fácilmente mediante el uso de plutil en macOS (disponible de forma nativa en versiones 10.2 y posteriores) o plistutil en Linux. Los comandos para la conversión son los siguientes:

  • Para macOS:
$ plutil -convert xml1 Info.plist
  • Para Linux:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist

Entre la miríada de información que puede revelar el archivo Info.plist, las entradas más destacadas incluyen cadenas de permisos de la app (UsageDescription), esquemas de URL personalizados (CFBundleURLTypes) y configuraciones para App Transport Security (NSAppTransportSecurity). Estas entradas, junto con otras como tipos de documento personalizados exportados/importados (UTExportedTypeDeclarations / UTImportedTypeDeclarations), pueden localizarse fácilmente inspeccionando el archivo o empleando un simple comando grep:

$ grep -i <keyword> Info.plist

Rutas de datos

En el entorno iOS, los directorios están designados específicamente para aplicaciones del sistema y aplicaciones instaladas por el usuario. Las aplicaciones del sistema residen en el directorio /Applications, mientras que las apps instaladas por el usuario se colocan bajo /var/mobile/containers/Data/Application/. A estas aplicaciones se les asigna un identificador único conocido como 128-bit UUID, lo que hace que localizar manualmente la carpeta de una app sea un reto debido a la aleatoriedad de los nombres de directorio.

Warning

Como las aplicaciones en iOS deben ejecutarse en sandbox, cada app tendrá también una carpeta dentro de $HOME/Library/Containers con el CFBundleIdentifier de la app como nombre de carpeta.

Sin embargo, ambas carpetas (carpetas de datos & de contenedor) contienen el archivo .com.apple.mobile_container_manager.metadata.plist que enlaza ambos archivos en la clave MCMetadataIdentifier).

Para facilitar el descubrimiento del directorio de instalación de una app instalada por el usuario, la objection tool proporciona un comando útil, env. Este comando revela información detallada de directorios para la app en cuestión. A continuación hay un ejemplo de cómo usar este comando:

OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env

Name               Path
-----------------  -------------------------------------------------------------------------------------------
BundlePath         /var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app
CachesDirectory    /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library/Caches
DocumentDirectory  /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Documents
LibraryDirectory   /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library

Alternativamente, el nombre de la app se puede buscar dentro de /private/var/containers usando el comando find:

find /private/var/containers -name "Progname*"

Comandos como ps y lsof también pueden utilizarse para identificar el proceso de la aplicación y listar archivos abiertos, respectivamente, proporcionando información sobre las rutas de directorio activas de la aplicación:

ps -ef | grep -i <app-name>
lsof -p <pid> | grep -i "/containers" | head -n 1

Directorio Bundle:

  • AppName.app
  • Este es el Application Bundle visto anteriormente en el IPA; contiene datos esenciales de la aplicación, contenido estático así como el binario compilado de la aplicación.
  • Este directorio es visible para los usuarios, pero los usuarios no pueden escribir en él.
  • El contenido de este directorio no se respalda.
  • El contenido de esta carpeta se utiliza para validar la firma de código.

Directorio de datos:

  • Documents/
  • Contiene todos los datos generados por el usuario. El usuario final de la aplicación inicia la creación de estos datos.
  • Visible para los usuarios y los usuarios pueden escribir en él.
  • El contenido de este directorio está respaldado.
  • La app puede excluir rutas estableciendo NSURLIsExcludedFromBackupKey.
  • Library/
  • Contiene todos los archivos que no son específicos del usuario, como caches, preferences, cookies, y archivos de configuración property list (plist).
  • Las apps iOS suelen usar los subdirectorios Application Support y Caches, pero la app puede crear subdirectorios personalizados.
  • Library/Caches/
  • Contiene archivos en caché semi-persistentes.
  • Invisible para los usuarios y los usuarios no pueden escribir en él.
  • El contenido de este directorio no se respalda.
  • El sistema operativo puede eliminar automáticamente los archivos de este directorio cuando la app no se está ejecutando y el espacio de almacenamiento es bajo.
  • Library/Application Support/
  • Contiene archivos persistentes necesarios para ejecutar la app.
  • Invisible para usuarios y los usuarios no pueden escribir en él.
  • El contenido de este directorio está incluido en copias de seguridad.
  • La app puede excluir rutas estableciendo NSURLIsExcludedFromBackupKey.
  • Library/Preferences/
  • Se usa para almacenar propiedades que pueden persistir incluso después de reiniciar la aplicación.
  • La información se guarda sin cifrar dentro del sandbox de la aplicación en un archivo plist llamado [BUNDLE_ID].plist.
  • Todos los pares clave/valor almacenados usando NSUserDefaults se pueden encontrar en este archivo.
  • tmp/
  • Usa este directorio para escribir archivos temporales que no necesitan persistir entre lanzamientos de la app.
  • Contiene archivos cacheados no persistentes.
  • Invisible para los usuarios.
  • El contenido de este directorio no se respalda.
  • El sistema operativo puede eliminar automáticamente los archivos de este directorio cuando la app no se está ejecutando y el espacio de almacenamiento es bajo.

Let’s take a closer look at iGoat-Swift’s Application Bundle (.app) directory inside the Bundle directory (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):

OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType      Perms  NSFileProtection    ...  Name
------------  -------  ------------------  ...  --------------------------------------
Regular           420  None                ...  rutger.html
Regular           420  None                ...  mansi.html
Regular           420  None                ...  splash.html
Regular           420  None                ...  about.html

Regular           420  None                ...  LICENSE.txt
Regular           420  None                ...  Sentinel.txt
Regular           420  None                ...  README.txt

Binary Reversing

Dentro de la carpeta <application-name>.app encontrarás un archivo binario llamado <application-name>. Este es el archivo que se ejecutará. Puedes realizar una inspección básica del binario con la herramienta otool:

otool -Vh DVIA-v2 #Check some compilation attributes
magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64    ARM64        ALL  0x00     EXECUTE    65       7112   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE

otool -L DVIA-v2 #Get third party libraries
DVIA-v2:
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.6.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
@rpath/Bolts.framework/Bolts (compatibility version 1.0.0, current version 1.0.0)
[...]

Comprueba si la app está cifrada

Revisa si hay alguna salida para:

otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO

Desensamblando el binario

Desensambla la sección .text:

otool -tV DVIA-v2
DVIA-v2:
(__TEXT,__text) section
+[DDLog initialize]:
0000000100004ab8    sub    sp, sp, #0x60
0000000100004abc    stp    x29, x30, [sp, #0x50]   ; Latency: 6
0000000100004ac0    add    x29, sp, #0x50
0000000100004ac4    sub    x8, x29, #0x10
0000000100004ac8    mov    x9, #0x0
0000000100004acc    adrp    x10, 1098 ; 0x10044e000
0000000100004ad0    add    x10, x10, #0x268

Para imprimir el Objective-C segment de la aplicación de ejemplo se puede usar:

otool -oV DVIA-v2
DVIA-v2:
Contents of (__DATA,__objc_classlist) section
00000001003dd5b8 0x1004423d0 _OBJC_CLASS_$_DDLog
isa        0x1004423a8 _OBJC_METACLASS_$_DDLog
superclass 0x0 _OBJC_CLASS_$_NSObject
cache      0x0 __objc_empty_cache
vtable     0x0
data       0x1003de748
flags          0x80
instanceStart  8

Para obtener un código Objective-C más compacto, puedes usar class-dump:

class-dump some-app
//
//     Generated by class-dump 3.5 (64 bit).
//
//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//

#pragma mark Named Structures

struct CGPoint {
double _field1;
double _field2;
};

struct CGRect {
struct CGPoint _field1;
struct CGSize _field2;
};

struct CGSize {
double _field1;
double _field2;
};

However, the best options to disassemble the binary are: Hopper and IDA.

Almacenamiento de datos

Para aprender cómo iOS almacena datos en el dispositivo lee esta página:

iOS Basics

Warning

The following places to store information should be checked right after installing the application, after checking all the functionalities of the application and even after login out from one user and login into a different one.
The goal is to find unprotected sensitive information of the application (contraseñas, tokens), of the current user and of previously logged users.

Plist

plist files are structured XML files that contains key-value pairs. It’s a way to store persistent data, so sometimes you may find sensitive information in these files. It’s recommended to check these files after installing the app and after using intensively it to see if new data is written.

The most common way to persist data in plist files is through the usage of NSUserDefaults. This plist file is saved inside the app sandbox in Library/Preferences/<appBundleID>.plist

The NSUserDefaults class provides a programmatic interface for interacting with the default system. The default system allows an application to customize its behaviour according to user preferences. Data saved by NSUserDefaults can be viewed in the application bundle. This class stores data in a plist file, but it’s meant to be used with small amounts of data.

This data cannot be longer accessed directly via a trusted computer, but can be accessed performing a copia de seguridad.

You can dump the information saved using NSUserDefaults using objection’s ios nsuserdefaults get

To find all the plist of used by the application you can access to /private/var/mobile/Containers/Data/Application/{APPID} and run:

find ./ -name "*.plist"

Para convertir archivos desde el formato XML o binary (bplist) a XML, están disponibles varios métodos según tu sistema operativo:

Para usuarios de macOS: Utiliza el comando plutil. Es una herramienta integrada en macOS (10.2+), diseñada para este propósito:

$ plutil -convert xml1 Info.plist

Para usuarios de Linux: Instala libplist-utils primero, luego usa plistutil para convertir tu archivo:

$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist

Dentro de una sesión de Objection: Para analizar aplicaciones móviles, un comando específico te permite convertir archivos plist directamente:

ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist

Core Data

Core Data es un framework para gestionar la capa de modelo de objetos en tu aplicación. Core Data puede usar SQLite como su almacenamiento persistente, pero el framework en sí no es una base de datos.\
CoreData no cifra sus datos por defecto. Sin embargo, se puede añadir una capa adicional de cifrado a CoreData. Véase el GitHub Repo para más detalles.

Puedes encontrar la información de Core Data (SQLite) de una aplicación en la ruta /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support

Si puedes abrir la base de datos SQLite y acceder a información sensible, entonces has encontrado una configuración incorrecta.

-(void)storeDetails {
AppDelegate * appDelegate = (AppDelegate *)(UIApplication.sharedApplication.delegate);

NSManagedObjectContext *context =[appDelegate managedObjectContext];

User *user = [self fetchUser];
if (user) {
return;
}
user = [NSEntityDescription insertNewObjectForEntityForName:@"User"
inManagedObjectContext:context];
user.email = CoreDataEmail;
user.password = CoreDataPassword;
NSError *error;
if (![context save:&error]) {
NSLog(@"Error in saving data: %@", [error localizedDescription]);

}else{
NSLog(@"data stored in core data");
}
}

YapDatabase

YapDatabase es una key/value store construida sobre SQLite.
Como las bases de datos Yap son bases de datos SQLite, puedes encontrarlas usando el comando propuesto en la sección anterior.

Other SQLite Databases

Es común que las aplicaciones creen su propia base de datos SQLite. Puede que estén almacenando datos sensibles en ellas y dejándolos sin cifrar. Por lo tanto, siempre es interesante revisar cada base de datos dentro del directorio de la aplicación. Dirígete al directorio de la aplicación donde se guardan los datos (/private/var/mobile/Containers/Data/Application/{APPID})

find ./ -name "*.sqlite" -or -name "*.db"

Firebase Real-Time Databases

Los desarrolladores pueden almacenar y sincronizar datos en una base de datos NoSQL alojada en la nube mediante Firebase Real-Time Databases. Almacenados en formato JSON, los datos se sincronizan con todos los clientes conectados en tiempo real.

Puedes encontrar cómo comprobar bases de datos de Firebase mal configuradas aquí:

Firebase Database

Realm databases

Realm Objective-C y Realm Swift ofrecen una alternativa potente para el almacenamiento de datos, no proporcionada por Apple. Por defecto, almacenan los datos sin cifrar, con cifrado disponible mediante una configuración específica.

The databases are located at: /private/var/mobile/Containers/Data/Application/{APPID}. To explore these files, one can utilize commands like:

iPhone:/private/var/mobile/Containers/Data/Application/A079DF84-726C-4AEA-A194-805B97B3684A/Documents root# ls
default.realm  default.realm.lock  default.realm.management/  default.realm.note|

$ find ./ -name "*.realm*"

Para ver estos archivos de base de datos, se recomienda la herramienta Realm Studio.

Para implementar cifrado en una base de datos Realm, se puede usar el siguiente fragmento de código:

// Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server
let config = Realm.Configuration(encryptionKey: getKey())
do {
let realm = try Realm(configuration: config)
// Use the Realm as normal
} catch let error as NSError {
// If the encryption key is wrong, `error` will say that it's an invalid database
fatalError("Error opening realm: \(error)")
}

Bases de datos de Couchbase Lite

Couchbase Lite se describe como un motor de base de datos ligero y embebido que sigue el enfoque orientado a documentos (NoSQL). Diseñado para ser nativo en iOS y macOS, ofrece la capacidad de sincronizar datos de forma transparente.

Para identificar posibles bases de datos Couchbase en un dispositivo, se debe inspeccionar el siguiente directorio:

ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/

Cookies

iOS almacena las cookies de las apps en el Library/Cookies/cookies.binarycookies dentro de la carpeta de cada app. Sin embargo, algunos desarrolladores a veces deciden guardarlas en el keychain, ya que el mencionado archivo de cookies puede ser accedido en las copias de seguridad.

Para inspeccionar el archivo de cookies puedes usar este script de Python o usar objection con ios cookies get.
También puedes usar objection para convertir estos archivos a formato JSON e inspeccionar los datos.

...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json
[
{
"domain": "highaltitudehacks.com",
"expiresDate": "2051-09-15 07:46:43 +0000",
"isHTTPOnly": "false",
"isSecure": "false",
"name": "username",
"path": "/",
"value": "admin123",
"version": "0"
}
]

Caché

Por defecto NSURLSession almacena datos, como solicitudes y respuestas HTTP en Cache.db. Esta base de datos puede contener datos sensibles, si tokens, nombres de usuario u otra información sensible ha sido almacenada en caché. Para encontrar la información en caché abre el directorio de datos de la app (/var/mobile/Containers/Data/Application/<UUID>) y ve a /Library/Caches/<Bundle Identifier>. El cache de WebKit también se almacena en el archivo Cache.db. Objection puede abrir e interactuar con la base de datos con el comando sqlite connect Cache.db, ya que es una base de datos SQLite normal.

Se recomienda desactivar el almacenamiento en caché de estos datos, ya que pueden contener información sensible en la solicitud o respuesta. La lista siguiente muestra distintas formas de lograrlo:

  1. Se recomienda eliminar las respuestas en caché tras cerrar sesión. Esto puede hacerse con el método proporcionado por Apple llamado removeAllCachedResponses Puedes llamar a este método de la siguiente manera:

URLCache.shared.removeAllCachedResponses()

Este método eliminará todas las solicitudes y respuestas en caché del archivo Cache.db.

  1. Si no necesitas usar la ventaja de las cookies, se recomienda usar la propiedad de configuración .ephemeral de URLSession, que deshabilita el guardado de cookies y cachés.

Apple documentation:

An ephemeral session configuration object is similar to a default session configuration (see default), except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM. The only time an ephemeral session writes data to disk is when you tell it to write the contents of a URL to a file.

  1. El cache también se puede desactivar estableciendo la Cache Policy en .notAllowed. Esto impedirá almacenar Cache de cualquier forma, ya sea en memoria o en disco.

Instantáneas

Cada vez que pulsas el botón Home, iOS toma una instantánea de la pantalla actual para poder realizar la transición a la aplicación de forma más fluida. Sin embargo, si hay datos sensibles presentes en la pantalla, se guardarán en la imagen (la cual persiste a través de reinicios). Estas son las instantáneas a las que también puedes acceder al pulsar dos veces el botón Home para cambiar entre apps.

A menos que el iPhone esté jailbroken, el atacante necesita tener acceso al dispositivo desbloqueado para ver estas capturas. Por defecto la última instantánea se almacena en el sandbox de la aplicación en Library/Caches/Snapshots/ o Library/SplashBoard/Snapshots (the trusted computers can’ t access the filesystem from iOX 7.0).

Una forma de prevenir este mal comportamiento es mostrar una pantalla en blanco o eliminar los datos sensibles antes de tomar la instantánea usando la función ApplicationDidEnterBackground().

El siguiente es un método de remediación de ejemplo que establecerá una captura de pantalla por defecto.

Swift:

private var backgroundImage: UIImageView?

func applicationDidEnterBackground(_ application: UIApplication) {
let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage"))
myBanner.frame = UIScreen.main.bounds
backgroundImage = myBanner
window?.addSubview(myBanner)
}

func applicationWillEnterForeground(_ application: UIApplication) {
backgroundImage?.removeFromSuperview()
}

Objective-C:

@property (UIImageView *)backgroundImage;

- (void)applicationDidEnterBackground:(UIApplication *)application {
UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
self.backgroundImage = myBanner;
self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
[self.window addSubview:myBanner];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
[self.backgroundImage removeFromSuperview];
}

Esto establece la imagen de fondo a overlayImage.png cada vez que la aplicación pasa a segundo plano. Evita sensitive data leaks porque overlayImage.png siempre sobrescribirá la vista actual.

Keychain

Para acceder y gestionar el keychain de iOS, hay herramientas como Keychain-Dumper disponibles, adecuadas para dispositivos jailbroken. Además, Objection proporciona el comando ios keychain dump para fines similares.

Almacenamiento de credenciales

La clase NSURLCredential es ideal para guardar información sensible directamente en el keychain, evitando la necesidad de NSUserDefaults u otros wrappers. Para almacenar credenciales después del inicio de sesión, se usa el siguiente código Swift:

NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];

Para extraer estas credenciales almacenadas se utiliza el comando de Objection ios nsurlcredentialstorage dump.

Teclados personalizados y caché del teclado

A partir de iOS 8.0, los usuarios pueden instalar extensiones de teclado personalizadas, que se gestionan en Settings > General > Keyboard > Keyboards. Aunque estos teclados ofrecen funcionalidades extendidas, suponen un riesgo de keystroke logging y de transmitir datos a servidores externos, aunque los usuarios son avisados acerca de los teclados que requieren acceso a la red. Las apps pueden, y deben, restringir el uso de teclados personalizados para la introducción de información sensible.

Recomendaciones de seguridad:

  • Se recomienda desactivar los teclados de terceros para mejorar la seguridad.
  • Tenga en cuenta las funciones de autocorrección y sugerencias automáticas del teclado iOS por defecto, que podrían almacenar información sensible en archivos de caché ubicados en Library/Keyboard/{locale}-dynamic-text.dat o /private/var/mobile/Library/Keyboard/dynamic-text.dat. Estos archivos de caché deben revisarse regularmente en busca de datos sensibles. Se recomienda restablecer el diccionario del teclado a través de Settings > General > Reset > Reset Keyboard Dictionary para borrar los datos en caché.
  • Interceptar el tráfico de red puede revelar si un teclado personalizado está transmitiendo keystrokes de forma remota.

Prevención del almacenamiento en caché de campos de texto

El UITextInputTraits protocol ofrece propiedades para gestionar la autocorrección y la entrada de texto segura, esenciales para prevenir el almacenamiento en caché de información sensible. Por ejemplo, desactivar la autocorrección y habilitar la entrada de texto segura se puede lograr con:

textObject.autocorrectionType = UITextAutocorrectionTypeNo;
textObject.secureTextEntry = YES;

Además, los desarrolladores deben asegurarse de que los campos de texto, especialmente aquellos para introducir información sensible como passwords and PINs, deshabiliten el almacenamiento en caché estableciendo autocorrectionType en UITextAutocorrectionTypeNo y secureTextEntry en YES.

UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;

Logs

La depuración de código a menudo implica el uso de logging. Existe un riesgo, ya que los logs pueden contener información sensible. Anteriormente, en iOS 6 y versiones anteriores, los logs eran accesibles para todas las apps, lo que representaba un riesgo de fuga de datos sensibles. Ahora, las aplicaciones están restringidas a acceder solo a sus logs.

A pesar de estas restricciones, un atacante con acceso físico a un dispositivo desbloqueado aún puede explotar esto conectando el dispositivo a un ordenador y leer los logs. Es importante tener en cuenta que los logs permanecen en el disco incluso después de la desinstalación de la app.

Para mitigar riesgos, se aconseja interactuar exhaustivamente con la app, explorando todas sus funcionalidades e entradas para asegurarse de que no se registre información sensible de forma inadvertida.

Al revisar el código fuente de la app en busca de posibles leaks, busca declaraciones de logging tanto predefinidas como personalizadas usando palabras clave como NSLog, NSAssert, NSCAssert, fprintf para funciones integradas, y cualquier mención de Logging o Logfile para implementaciones personalizadas.

Monitoring System Logs

Las apps generan logs con diversos tipos de información que pueden ser sensibles. Para monitorizar estos logs, herramientas y comandos como:

idevice_id --list   # To find the device ID
idevicesyslog -u <id> (| grep <app>)   # To capture the device logs

son útiles. Además, Xcode proporciona una forma de recopilar registros de la consola:

  1. Abre Xcode.
  2. Conecta el dispositivo iOS.
  3. Navega a Window -> Devices and Simulators.
  4. Selecciona tu dispositivo.
  5. Provoca el problema que estás investigando.
  6. Usa el Open Console button para ver los logs en una nueva ventana.

Para un registro más avanzado, conectarse al shell del dispositivo y usar socat puede proporcionar monitorización de logs en tiempo real:

iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock

Seguido de comandos para observar la actividad de los registros, lo cual puede ser invaluable para diagnosticar problemas o identificar una posible data leakage.

Copias de seguridad

Funciones de copia automática están integradas en iOS, facilitando la creación de copias de datos del dispositivo a través de iTunes (up to macOS Catalina), Finder (from macOS Catalina onward), or iCloud. Estas copias incluyen casi todos los datos del dispositivo, excluyendo elementos altamente sensibles como detalles de Apple Pay y configuraciones de Touch ID.

Riesgos de seguridad

La inclusión de aplicaciones instaladas y sus datos en las copias de seguridad plantea el problema de una potencial data leakage y el riesgo de que las modificaciones de la copia de seguridad podrían alterar la funcionalidad de la app. Se recomienda no almacenar información sensible en texto plano dentro del directorio de ninguna app ni de sus subdirectorios para mitigar estos riesgos.

Excluir archivos de las copias de seguridad

Los archivos en Documents/ y Library/Application Support/ se respaldan por defecto. Los desarrolladores pueden excluir archivos o directorios específicos de las copias de seguridad usando NSURL setResourceValue:forKey:error: con la clave NSURLIsExcludedFromBackupKey. Esta práctica es crucial para proteger datos sensibles y evitar que sean incluidos en las copias de seguridad.

Pruebas de vulnerabilidades

Para evaluar la seguridad de las copias de seguridad de una app, comience por crear una copia de seguridad usando Finder, y luego localícela siguiendo la guía de Apple’s official documentation. Analice la copia de seguridad en busca de datos sensibles o configuraciones que podrían ser alteradas para afectar el comportamiento de la app.

Se puede buscar información sensible usando herramientas de línea de comandos o aplicaciones como iMazing. Para las copias cifradas, la presencia de cifrado puede confirmarse comprobando la clave “IsEncrypted” en el archivo “Manifest.plist” en la raíz de la copia de seguridad.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
...
<key>Date</key>
<date>2021-03-12T17:43:33Z</date>
<key>IsEncrypted</key>
<true/>
...
</plist>

Para tratar con copias de seguridad cifradas, los scripts de Python disponibles en DinoSec’s GitHub repo, como backup_tool.py y backup_passwd.py, pueden ser útiles, aunque podrían requerir ajustes para compatibilidad con las versiones más recientes de iTunes/Finder. La herramienta iOSbackup es otra opción para acceder a archivos dentro de copias de seguridad protegidas por contraseña.

Modificar el comportamiento de la aplicación

Un ejemplo de alterar el comportamiento de una aplicación mediante modificaciones del backup se demuestra en la Bither bitcoin wallet app, donde el PIN de bloqueo de la UI se almacena en net.bither.plist bajo la clave pin_code. Eliminar esta clave del plist y restaurar la copia de seguridad elimina el requisito del PIN, proporcionando acceso sin restricciones.

Resumen sobre pruebas de memoria para datos sensibles

Al tratar con información sensible almacenada en la memoria de una aplicación, es crucial limitar el tiempo de exposición de estos datos. Hay dos enfoques principales para investigar el contenido de la memoria: crear un volcado de memoria y analizar la memoria en tiempo real. Ambos métodos presentan desafíos, incluyendo la posibilidad de pasar por alto datos críticos durante el proceso de volcado o el análisis.

Recuperación y análisis de un volcado de memoria

Para dispositivos tanto jailbroken como no jailbroken, herramientas como objection y Fridump permiten volcar la memoria del proceso de una aplicación. Una vez volcados, analizar estos datos requiere diversas herramientas, dependiendo de la naturaleza de la información que se busque.

Para extraer strings de un volcado de memoria, se pueden usar comandos como strings o rabin2 -zz:

# Extracting strings using strings command
$ strings memory > strings.txt

# Extracting strings using rabin2
$ rabin2 -ZZ memory > strings.txt

Para un análisis más detallado, que incluye la búsqueda de tipos de datos o patrones específicos, radare2 ofrece amplias capacidades de búsqueda:

$ r2 <name_of_your_dump_file>
[0x00000000]> /?
...

Runtime Memory Analysis

r2frida proporciona una alternativa potente para inspeccionar la memoria de una app en tiempo real, sin necesidad de un memory dump. Esta herramienta permite ejecutar comandos de búsqueda directamente en la memoria de la app en ejecución:

$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>

Criptografía débil

Procesos deficientes de gestión de claves

Algunos desarrolladores guardan datos sensibles en el almacenamiento local y los cifran con una key hardcoded/predictable en el código. Esto no debería hacerse, ya que cierto 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 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, se deben usar hashes resistentes al brute-force con salt.

Comprobación

Las principales comprobaciones a realizar son si puedes encontrar contraseñas/secretos hardcoded en el código, si estos son predictable, y si el código está usando algún tipo de weak cryptography algorithms.

Es interesante saber que puedes monitor algunas crypto libraries automáticamente usando objection con:

ios monitor crypt

Para más información sobre iOS cryptographic APIs and libraries access https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography

Autenticación local

Local authentication juega un papel crucial, especialmente cuando se trata de proteger el acceso en un endpoint remoto mediante métodos criptográficos. La esencia aquí es que sin una implementación adecuada, los mecanismos de autenticación local pueden ser eludidos.

Apple’s Local Authentication framework y el keychain proporcionan APIs robustas para que los desarrolladores muestren diálogos de autenticación de usuario y manejen datos secretos de forma segura, respectivamente. El Secure Enclave asegura fingerprint ID para Touch ID, mientras que Face ID se basa en reconocimiento facial sin comprometer los datos biométricos.

Para integrar Touch ID/Face ID, los desarrolladores tienen dos opciones de API:

  • LocalAuthentication.framework para autenticación de usuario de alto nivel sin acceso a datos biométricos.
  • Security.framework para acceso de bajo nivel a los servicios de keychain, asegurando datos secretos con autenticación biométrica. Varios open-source wrappers facilitan el acceso al keychain.

Caution

Sin embargo, tanto LocalAuthentication.framework como Security.framework presentan vulnerabilidades, ya que principalmente devuelven valores booleanos sin transmitir datos para los procesos de autenticación, lo que los hace susceptibles de ser eludidos (consulta Don’t touch me that way, by David Lindner et al).

Implementación de autenticación local

Para solicitar autenticación a los usuarios, los desarrolladores deben utilizar el método evaluatePolicy dentro de la clase LAContext, eligiendo entre:

  • deviceOwnerAuthentication: Solicita Touch ID o el código de acceso del dispositivo, falla si ninguno está habilitado.
  • deviceOwnerAuthenticationWithBiometrics: Solicita exclusivamente Touch ID.

Una autenticación exitosa se indica mediante un valor booleano devuelto por evaluatePolicy, lo que resalta un posible fallo de seguridad.

Autenticación local usando keychain

Implementar la autenticación local en apps iOS implica el uso de las keychain APIs para almacenar de forma segura datos secretos como tokens de autenticación. Este proceso garantiza que los datos solo puedan ser accedidos por el usuario, usando su código de acceso del dispositivo o autenticación biométrica como Touch ID.

El keychain ofrece la capacidad de establecer ítems con el atributo SecAccessControl, que restringe el acceso al ítem hasta que el usuario se autentique correctamente mediante Touch ID o el código de acceso del dispositivo. Esta característica es crucial para mejorar la seguridad.

A continuación hay ejemplos de código en Swift y Objective-C que demuestran cómo guardar y recuperar una cadena desde el keychain, aprovechando estas funciones de seguridad. Los ejemplos muestran específicamente cómo configurar el control de acceso para requerir autenticación con Touch ID y asegurar que los datos sean accesibles solo en el dispositivo donde fueron configurados, bajo la condición de que exista un código de acceso en el dispositivo.

// From https://github.com/mufambisi/owasp-mstg/blob/master/Document/0x06f-Testing-Local-Authentication.md

// 1. create AccessControl object that will represent authentication settings

var error: Unmanaged<CFError>?

guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
SecAccessControlCreateFlags.biometryCurrentSet,
&error) else {
// failed to create AccessControl object

return
}

// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute

var query: [String: Any] = [:]

query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecAttrAccount as String] = "OWASP Account" as CFString
query[kSecValueData as String] = "test_strong_password".data(using: .utf8)! as CFData
query[kSecAttrAccessControl as String] = accessControl

// 3. save item

let status = SecItemAdd(query as CFDictionary, nil)

if status == noErr {
// successfully saved
} else {
// error while saving
}

Ahora podemos solicitar el elemento guardado del keychain. Keychain services presentarán el diálogo de autenticación al usuario y devolverán datos o nil dependiendo de si se proporcionó una huella dactilar adecuada o no.

// 1. define query
var query = [String: Any]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecAttrAccount as String] = "My Name" as CFString
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString

// 2. get item
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}

if status == noErr {
let password = String(data: queryResult as! Data, encoding: .utf8)!
// successfully received password
} else {
// authorization not passed
}

Detección

El uso de frameworks en una app también puede detectarse analizando la lista de bibliotecas dinámicas compartidas del binario de la app. Esto se puede hacer usando otool:

$ otool -L <AppName>.app/<AppName>

Si LocalAuthentication.framework se usa en una app, la salida contendrá las dos líneas siguientes (recuerda que LocalAuthentication.framework utiliza Security.framework internamente):

/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security

Si se usa Security.framework, solo se mostrará el segundo.

Local Authentication Framework Bypass

Objection

Through the Objection Biometrics Bypass, located at this GitHub page, a technique is available for overcoming the LocalAuthentication mechanism. El núcleo de este enfoque consiste en aprovechar Frida para manipular la función evaluatePolicy, asegurando que consistentemente devuelva True, independientemente del éxito real de la autenticación. Esto es especialmente útil para eludir procesos de autenticación biométrica defectuosos.

Para activar este bypass, se emplea el siguiente comando:

...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios ui biometrics_bypass
(agent) Registering job 3mhtws9x47q. Type: ios-biometrics-disable
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # (agent) [3mhtws9x47q] Localized Reason for auth requirement: Please authenticate yourself
(agent) [3mhtws9x47q] OS authentication response: false
(agent) [3mhtws9x47q] Marking OS response as True instead
(agent) [3mhtws9x47q] Biometrics bypass hook complete

Este comando inicia una secuencia en la que Objection registra una tarea que efectivamente altera el resultado de la comprobación evaluatePolicy a True.

Frida

Un ejemplo de uso de evaluatePolicy en DVIA-v2 application:

+(void)authenticateWithTouchID {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = @"Please authenticate yourself";

if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Successful" withTitle:@"Success"];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Failed !" withTitle:@"Error"];
});
}
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Your device doesn't support Touch ID or you haven't configured Touch ID authentication on your device" withTitle:@"Error"];
});
}
}

Para lograr el bypass de Local Authentication, se escribe un script de Frida. Este script apunta a la verificación evaluatePolicy, interceptando su callback para asegurar que devuelva success=1. Al alterar el comportamiento del callback, la comprobación de autenticación queda efectivamente bypass.

El script que sigue se inyecta para modificar el resultado del método evaluatePolicy. Cambia el resultado del callback para que siempre indique éxito.

// from https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/
if(ObjC.available) {
console.log("Injecting...");
var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"];
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
var block = new ObjC.Block(args[4]);
const callback = block.implementation;
block.implementation = function (error, value)  {

console.log("Changing the result value to true")
const result = callback(1, null);
return result;
};
},
});
} else {
console.log("Objective-C Runtime is not available!");
}

Para inyectar el script de Frida y omitir la autenticación biométrica, se usa el siguiente comando:

frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js

Exposición de Funcionalidades Sensibles a través de IPC

iOS Custom URI Handlers / Deeplinks / Custom Schemes

iOS Universal Links

UIActivity Sharing

iOS UIActivity Sharing

UIPasteboard

iOS UIPasteboard

App Extensions

iOS App Extensions

WebViews

iOS WebViews

Serialisation and Encoding

iOS Serialisation and Encoding

Comunicación de red

Es importante comprobar que no exista comunicación sin encriptación y también que la aplicación esté correctamente validando el certificado TLS del servidor.
Para comprobar este tipo de problemas puedes usar un proxy como Burp:

iOS Burp Suite Configuration

Comprobación del hostname

Un problema común al validar el certificado TLS es comprobar que el certificado fue firmado por una CA de confianza, pero no comprobar si el hostname del certificado coincide con el hostname al que se está accediendo.
Para comprobar este problema usando Burp, después de confiar en la CA de Burp en el iPhone, puedes crear un nuevo certificado con Burp para un hostname diferente y usarlo. Si la aplicación sigue funcionando, entonces algo es vulnerable.

Certificate Pinning

Si una aplicación está usando correctamente SSL Pinning, entonces la aplicación solo funcionará si el certificado es el esperado. Al probar una aplicación esto puede ser un problema ya que Burp sirve su propio certificado.
Para bypassear esta protección dentro de un dispositivo jailbroken, puedes instalar la aplicación SSL Kill Switch o instalar Burp Mobile Assistant

También puedes usar objection ios sslpinning disable

Misceláneo

  • En /System/Library puedes encontrar los frameworks instalados en el teléfono usados por las aplicaciones del sistema
  • Las aplicaciones instaladas por el usuario desde el App Store se encuentran dentro de /User/Applications
  • Y /User/Library contiene los datos guardados por las aplicaciones a nivel de usuario
  • Puedes acceder a /User/Library/Notes/notes.sqlite para leer las notas guardadas dentro de la aplicación.
  • Dentro de la carpeta de una aplicación instalada (/User/Applications/<APP ID>/) puedes encontrar algunos archivos interesantes:
  • iTunesArtwork: El icono usado por la app
  • iTunesMetadata.plist: Información de la app usada en el App Store
  • /Library/*: Contiene las preferencias y la caché. En /Library/Cache/Snapshots/* puedes encontrar el snapshot realizado a la aplicación antes de enviarla al background.

Hot Patching/Enforced Updateing

Los desarrolladores pueden parchear remotamente todas las instalaciones de su app al instante sin tener que reenviar la aplicación al App Store y esperar a que sea aprobada.
Para este propósito normalmente se usa JSPatch. Pero también hay otras opciones como Siren y react-native-appstore-version-checker.
Este es un mecanismo peligroso que podría ser abusado por SDKs de terceros maliciosos por lo que se recomienda comprobar qué método se usa para la actualización automática (si existe) y probarlo. Podrías intentar descargar una versión anterior de la app para este propósito.

Third Parties

Un desafío significativo con los 3rd party SDKs es la falta de control granular sobre sus funcionalidades. Los desarrolladores se enfrentan a una elección: integrar el SDK y aceptar todas sus características, incluidas las posibles vulnerabilidades de seguridad y preocupaciones de privacidad, o renunciar por completo a sus beneficios. A menudo, los desarrolladores no pueden parchear las vulnerabilidades dentro de estos SDKs por sí mismos. Además, a medida que los SDKs ganan confianza en la comunidad, algunos pueden empezar a contener malware.

Los servicios proporcionados por SDKs de terceros pueden incluir seguimiento del comportamiento de los usuarios, mostrar publicidad o mejoras en la experiencia de usuario. Sin embargo, esto introduce un riesgo ya que los desarrolladores pueden no ser totalmente conscientes del código que ejecutan estas librerías, lo que conduce a posibles riesgos de privacidad y seguridad. Es crucial limitar la información compartida con servicios de terceros a lo estrictamente necesario y asegurarse de que no se exponga información sensible.

La implementación de servicios de terceros suele venir en dos formas: una librería independiente o un SDK completo. Para proteger la privacidad del usuario, cualquier dato compartido con estos servicios debe ser anonimizado para evitar la divulgación de Personal Identifiable Information (PII).

Para identificar las librerías que una aplicación usa, se puede emplear el comando otool. Esta herramienta debe ejecutarse contra la aplicación y cada librería compartida que usa para descubrir librerías adicionales.

otool -L <application_path>

Vulnerabilidades interesantes y estudios de caso

Air Keyboard Remote Input Injection

Itunesstored Bookassetd Sandbox Escape

Zero Click Messaging Image Parser Chains

Referencias y más recursos

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks