iOS Basics

Support HackTricks

Separación de Privilegios y Sandbox

En iOS, existe una distinción en privilegios entre las aplicaciones accesibles para el usuario y los procesos centrales del sistema. Las aplicaciones se ejecutan bajo la identidad de usuario mobile, mientras que los procesos cruciales del sistema operan como root. Esta separación se ve reforzada por un mecanismo de sandbox, que impone estrictas limitaciones sobre las acciones que pueden realizar las aplicaciones. Por ejemplo, incluso si las aplicaciones comparten la misma identidad de usuario, se les prohíbe acceder o modificar los datos de otras.

Las aplicaciones se instalan en un directorio específico (private/var/mobile/Applications/{random ID}) y tienen acceso de lectura restringido a ciertas áreas y funcionalidades del sistema, como SMS y llamadas telefónicas. El acceso a áreas protegidas activa una solicitud emergente de permiso del usuario.

Protección de Datos

iOS ofrece a los desarrolladores las APIs de Protección de Datos, construidas sobre el Procesador de Enclave Seguro (SEP) — un coprocesador dedicado a operaciones criptográficas y gestión de claves. El SEP asegura la integridad de la protección de datos a través de una clave única específica del dispositivo, el UID del dispositivo, incrustada en él.

Al crear un archivo, se genera una clave de cifrado AES de 256 bits única, cifrando el contenido del archivo. Esta clave de cifrado, junto con un ID de clase, se cifra utilizando una clave de clase y se almacena dentro de los metadatos del archivo. Desencriptar un archivo implica usar la clave del sistema para acceder a los metadatos, recuperar la clave de clase con el ID de clase y luego desencriptar la clave de cifrado única del archivo.

iOS define cuatro clases de protección para la seguridad de los datos, que determinan cuándo y cómo se puede acceder a los datos:

  • Protección Completa (NSFileProtectionComplete): Los datos son inaccesibles hasta que el dispositivo se desbloquee usando el código de acceso del usuario.

  • Protegido a Menos que Esté Abierto (NSFileProtectionCompleteUnlessOpen): Permite el acceso al archivo incluso después de que el dispositivo esté bloqueado, siempre que el archivo se haya abierto cuando el dispositivo fue desbloqueado.

  • Protegido Hasta la Primera Autenticación del Usuario (NSFileProtectionCompleteUntilFirstUserAuthentication): Los datos son accesibles después de la primera desbloqueo del usuario tras el arranque, permaneciendo accesibles incluso si el dispositivo se bloquea nuevamente.

  • Sin Protección (NSFileProtectionNone): Los datos están protegidos solo por el UID del dispositivo, facilitando un borrado rápido de datos de forma remota.

El cifrado de todas las clases, excepto NSFileProtectionNone, implica una clave derivada tanto del UID del dispositivo como del código de acceso del usuario, asegurando que la desencriptación solo sea posible en el dispositivo con el código de acceso correcto. A partir de iOS 7, la clase de protección predeterminada es "Protegido Hasta la Primera Autenticación del Usuario".

Los desarrolladores pueden usar FileDP, una herramienta para inspeccionar la clase de protección de datos de los archivos en un iPhone.

# Example code to use FileDP for checking file protection class
# Note: Ensure your device is jailbroken and has Python installed to use FileDP.
# Installation and usage of FileDP:
git clone https://github.com/abjurato/FileDp-Source
cd FileDp-Source
python filedp.py /path/to/check

El llavero

En iOS, un llavero sirve como un contenedor encriptado seguro para almacenar información sensible, accesible solo por la aplicación que lo almacenó o aquellas explícitamente autorizadas. Esta encriptación se refuerza con una contraseña única generada por iOS, que a su vez está encriptada con AES. Este proceso de encriptación utiliza una función PBKDF2, combinando el código de acceso del usuario con una sal derivada del UID del dispositivo, un componente al que solo puede acceder el chipset de enclave seguro. En consecuencia, incluso si se conoce el código de acceso del usuario, el contenido del llavero permanece inaccesible en cualquier dispositivo que no sea aquel donde fueron encriptados originalmente.

La gestión y el acceso a los datos del llavero son manejados por el demonio securityd, basado en derechos específicos de la aplicación como Keychain-access-groups y application-identifier.

Operaciones de la API del Llavero

La API del llavero, detallada en la documentación de servicios de llavero de Apple, proporciona funciones esenciales para la gestión de almacenamiento seguro:

  • SecItemAdd: Agrega un nuevo elemento al llavero.

  • SecItemUpdate: Actualiza un elemento existente en el llavero.

  • SecItemCopyMatching: Recupera un elemento del llavero.

  • SecItemDelete: Elimina un elemento del llavero.

Forzar la contraseña del llavero implica atacar la clave encriptada directamente o intentar adivinar el código de acceso en el dispositivo mismo, obstaculizado significativamente por la aplicación de un retraso entre intentos fallidos por parte del enclave seguro.

Configuración de la Protección de Datos de Elementos del Llavero

Los niveles de protección de datos para los elementos del llavero se establecen utilizando el atributo kSecAttrAccessible durante la creación o actualización del elemento. Estos niveles, según lo especificado por Apple, determinan cuándo y cómo son accesibles los elementos del llavero:

  • kSecAttrAccessibleAlways: Accesible en cualquier momento, independientemente del estado de bloqueo del dispositivo.

  • kSecAttrAccessibleAlwaysThisDeviceOnly: Siempre accesible, pero no incluido en copias de seguridad.

  • kSecAttrAccessibleAfterFirstUnlock: Accesible después del primer desbloqueo tras un reinicio.

  • kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: Igual que lo anterior, pero no transferible a nuevos dispositivos.

  • kSecAttrAccessibleWhenUnlocked: Solo accesible cuando el dispositivo está desbloqueado.

  • kSecAttrAccessibleWhenUnlockedThisDeviceOnly: Accesible cuando está desbloqueado, no incluido en copias de seguridad.

  • kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: Requiere el código de acceso del dispositivo, no incluido en copias de seguridad.

AccessControlFlags refinan aún más los métodos de acceso, permitiendo la autenticación biométrica o el uso de un código de acceso.

Advertencia sobre Dispositivos Jailbroken

En dispositivos jailbroken, las protecciones del llavero están comprometidas, lo que representa un riesgo de seguridad significativo.

Persistencia de los Datos del Llavero

A diferencia de los datos específicos de la aplicación que se eliminan al desinstalar la aplicación, los datos del llavero persisten en el dispositivo. Esta característica podría permitir a los nuevos propietarios de un dispositivo de segunda mano acceder a los datos de la aplicación del propietario anterior simplemente reinstalando las aplicaciones. Se aconseja a los desarrolladores que eliminen proactivamente los datos del llavero al instalar la aplicación o durante el cierre de sesión para mitigar este riesgo. Aquí hay un ejemplo de código Swift que demuestra cómo limpiar los datos del llavero al primer lanzamiento de la aplicación:

let userDefaults = UserDefaults.standard

if userDefaults.bool(forKey: "hasRunBefore") == false {
// Remove Keychain items here

// Update the flag indicator
userDefaults.set(true, forKey: "hasRunBefore")
userDefaults.synchronize() // Forces the app to update UserDefaults
}

Capacidades de la App

En el ámbito del desarrollo de aplicaciones, sandboxing juega un papel crucial en la mejora de la seguridad. Este proceso asegura que cada aplicación opere dentro de su propio directorio de inicio único, evitando así que acceda a archivos del sistema o datos pertenecientes a otras aplicaciones. La aplicación de estas restricciones se lleva a cabo a través de políticas de sandbox, que son parte del Trusted BSD (MAC) Mandatory Access Control Framework.

Los desarrolladores tienen la capacidad de configurar ciertas capacidades o permisos para sus aplicaciones, como Data Protection o Keychain Sharing. Estos permisos se aplican inmediatamente después de que la aplicación es instalada. No obstante, para acceder a ciertos recursos protegidos, la aplicación debe obtener el consentimiento explícito del usuario en el momento del primer intento. Esto se logra mediante el uso de purpose strings o usage description strings, que se presentan a los usuarios en una alerta de solicitud de permiso.

Para aquellos con acceso al código fuente, la verificación de permisos incluidos en el archivo Info.plist se puede hacer mediante:

  1. Abrir el proyecto en Xcode.

  2. Localizar y abrir el archivo Info.plist.

  3. Buscar claves con el prefijo "Privacy -", con la opción de ver claves/valores en bruto para mayor claridad.

Al tratar con un archivo IPA, se pueden seguir los siguientes pasos:

  1. Descomprimir el IPA.

  2. Localizar el archivo Info.plist dentro de Payload/<appname>.app/.

  3. Convertir el archivo a formato XML si es necesario, para una inspección más fácil.

Por ejemplo, las purpose strings en el archivo Info.plist podrían verse así:

<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location is used to provide turn-by-turn directions to your destination.</string>

Device Capabilities

El archivo Info.plist de una aplicación especifica capacidades del dispositivo que ayudan a la App Store a filtrar aplicaciones para la compatibilidad del dispositivo. Estas se definen bajo la clave UIRequiredDeviceCapabilities. Por ejemplo:

<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>

Este ejemplo indica que la aplicación es compatible con el conjunto de instrucciones armv7. Los desarrolladores también pueden especificar capacidades como nfc para garantizar que su aplicación solo esté disponible para dispositivos que admiten NFC.

Derechos

Derechos son otro aspecto crítico del desarrollo de aplicaciones iOS, sirviendo como pares clave-valor que otorgan a las aplicaciones permiso para realizar ciertas operaciones más allá de las verificaciones en tiempo de ejecución. Por ejemplo, habilitar Protección de Datos en una aplicación implica agregar un derecho específico en el proyecto de Xcode, que luego se refleja en el archivo de derechos de la aplicación o en el archivo de provisión móvil incrustado para IPAs.

Referencias

Support HackTricks

Last updated