Lista de verificación de seguridad para aplicaciones iOS
Fase 0: Gobernanza, entorno y CI/CD
Aplicar puertas de validación en CI (CI gates)
- Ejecutar comprobaciones estáticas en cada PR: swiftlint (o equivalente), pruebas unitarias/UI, auditoría de dependencias.
- Bloquear el lanzamiento ante hallazgos SAST/SCA/DAST Altos/Críticos; cero errores de lint en ramas de lanzamiento.
Manejo de secretos
- Asegurar que no haya secretos en el código fuente, Info.plist, storyboards o registros.
- Utilizar un gestor de entorno/secretos para los secretos.
- Ocultar secretos en las analíticas (analytics).
- Rotar claves/tokens periódicamente y ante sospecha de filtración.
Evidencia y trazabilidad
- Archivar informes de escaneo con cada artefacto.
- Archivar SBOM con cada artefacto.
- Archivar registros de compilación con cada artefacto.
- Archivar notas de la versión con cada artefacto.
Automatización de escaneos
- Integrar una plataforma móvil de SAST/DAST/SCA en CI/CD para ejecutarla en cada PR y pre-lanzamiento (ej. Ostorlab).
- Hacer fallar automáticamente las puertas de validación de CI en caso de problemas Altos/Críticos en SAST/DAST/SCA.
Fase 1: Modelado de amenazas (Threat modeling), clasificación de datos e inventario
- Clasificar los datos (PII, credenciales, tokens, pagos) y mapear su recopilación, procesamiento, almacenamiento y transmisión.
- Identificar los límites de confianza (dispositivo, Keychain/Archivo, URLSession, WebView, canales de plataforma hacia bibliotecas nativas).
- Inventariar los SDKs de terceros; preferir SDKs bien mantenidos, firmados, con el mínimo privilegio; minimizar la cantidad.
Fase 2: Fortalecimiento de la compilación y configuración (Xcode + Info.plist)
Ajustes de lanzamiento de Xcode (Release settings)
- Eliminar símbolos y código muerto (dead code).
- Habilitar la optimización de módulo completo (whole-module optimization).
- Desactivar los indicadores DEBUG en compilaciones de lanzamiento.
- Excluir frameworks de prueba/depuración del lanzamiento.
- Eliminar endpoints de desarrollo e indicadores de características (feature flags) del lanzamiento.
Firma de código y autorizaciones (entitlements)
- Otorgar solo las autorizaciones necesarias (sin App Groups, uso compartido de Keychain, NFC, Bluetooth, etc. sin usar).
- Utilizar la firma automática con perfiles de lanzamiento dedicados.
- Proteger las credenciales de firma (ej. almacén de secretos de CI, controles de acceso).
Seguridad de transporte de la aplicación (App Transport Security - ATS)
- Establecer
NSAllowsArbitraryLoads = false. - Preferir TLS 1.2+ únicamente.
- Utilizar
NSExceptionDomainsestrictos solo cuando sea necesario y por un tiempo limitado.
Higiene del Info.plist
- Desactivar el uso compartido de documentos a menos que sea necesario:
-
UIFileSharingEnabled = false -
LSSupportsOpeningDocumentsInPlace = false - Minimizar
LSApplicationQueriesSchemes; preferir Universal Links sobre esquemas personalizados. - Proporcionar cadenas
NS[AppData/AppleEvents/SystemAdministration]UsageDescriptionprecisas para todos los permisos.
Fase 3: Almacenamiento local y seguridad del Keychain
Uso del Keychain
- Almacenar tokens/secretos en el Keychain con la clase más sólida posible:
-
kSecAttrAccessibleWhenUnlockedThisDeviceOnly - O
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnlycuando aplique. - Controlar elementos sensibles con indicadores
kSecAccessControl(ej.biometryCurrentSet,userPresence) cuando la UX lo permita. - Eliminar elementos del Keychain al cerrar sesión.
- Considerar la vinculación al dispositivo (device-binding) para tokens de alto riesgo.
Protección de archivos y bases de datos
- Aplicar protección de datos a los archivos:
NSFileProtectionComplete(atributos predeterminados o por archivo). - Cifrar bases de datos/archivos sensibles (ej. SQLCipher o equivalente).
- Nunca almacenar secretos en texto claro.
Cachés y datos derivados
- Evitar persistir PII en cachés/archivos temporales.
- Purgar datos sensibles de cachés/archivos temporales al cerrar sesión, según sea necesario.
- Purgar datos sensibles de cachés/archivos temporales en segundo plano, según sea necesario.
- No escribir secretos en
UserDefaults.
Fase 4: Salvaguardas de privacidad (UI, portapapeles, capturas de pantalla)
- Ocultar la UI sensible cuando se pasa a segundo plano (desenfoque o imagen de reemplazo en
sceneWillResignActive/applicationWillResignActive). - Detectar la captura de pantalla (
UIScreen.main.isCaptured) y ajustar el comportamiento para vistas altamente sensibles. - Evitar leer el portapapeles al iniciar la aplicación.
- Nunca colocar secretos en
UIPasteboard.general.
Fase 5: Seguridad de la red y TLS/fijación (pinning)
URLSession/ATS
- Forzar HTTPS a hosts confiables.
- Rechazar certificados y nombres de host no válidos.
- Desactivar los respaldos (fallbacks) a HTTP.
- Establecer tiempos de espera estrictos.
- Implementar reintentos con variaciones (jitter) cuando sea apropiado.
- Fallar por defecto (fail closed) en caso de errores TLS.
- Forzar el uso de TLS 1.2+ en la configuración TLS del servidor.
Fijación de certificados (Certificate pinning)
- Preferir fijaciones SPKI SHA-256.
- Incluir al menos una fijación de respaldo por host.
- Implementar la fijación a través de la evaluación de confianza
URLSessionDelegate. - Validar el comportamiento contra intentos de MITM.
- Validar el comportamiento para certificados de hoja expirados/rotados.
- Planificar la rotación segura de fijaciones.
- Incluir telemetría sobre fallos de fijación.
Cookies y tokens
- Utilizar cookies seguras, HttpOnly, SameSite para los flujos web.
- Evitar tokens de portador (bearer tokens) de larga duración en el dispositivo.
- Borrar cookies y datos web después de sesiones sensibles.
Fase 6: Autenticación, autorización y sesión
Flujos de autenticación
- Utilizar OAuth2/OIDC con PKCE para clientes públicos.
- Nunca incrustar secretos del cliente en la aplicación.
- Preferir el navegador del sistema (
ASWebAuthenticationSession/SafariViewController) sobre WebView para la autenticación.
Tokens
- Utilizar tokens de acceso (access tokens) de corta duración.
- Almacenar tokens de actualización (refresh tokens) en el Keychain.
- Rotar e invalidar tokens al cerrar sesión.
- Rotar e invalidar tokens al cambiar de dispositivo.
- Vincular sesiones al riesgo del dispositivo (device risk) donde sea apropiado.
- Detectar anomalías (cambios de geo/IP/ASN) y responder a ellas.
Autorización
- Forzar la autorización en el servidor; tratar las comprobaciones del cliente como consultivas.
- Validar en busca de vulnerabilidades IDOR/BOLA.
- Validar en busca de problemas de escalada de privilegios.
Fase 7: Fortalecimiento del WebView (WKWebView)
- Utilizar
WKWebViewsolo cuando sea requerido. - Preferir dominios limitados a la aplicación para el aislamiento (
WKAppBoundDomains).
Valores predeterminados
- Desactivar JavaScript a menos que sea necesario.
- Desactivar
javaScriptCanOpenWindowsAutomatically. - Establecer listas de permitidos para la navegación a través de
WKNavigationDelegate. - Bloquear URLs
file://. - Bloquear URLs
javascript:. - Utilizar un almacén de datos no persistente para sesiones sensibles.
- Borrar
HTTPCookieStorey los datos del sitio web al cerrar sesión. - Asegurarse de que el Web Inspector esté deshabilitado en el lanzamiento (iOS 16+
isInspectable = false).
Seguridad del contenido
- Para el contenido web propio, aplicar la política CSP.
- Forzar HTTPS.
- No permitir contenido mixto.
Fase 8: Comunicación entre aplicaciones y enlaces profundos (deep links)
- Preferir los Universal Links.
- Validar los orígenes y parámetros de los enlaces entrantes.
Si se utilizan esquemas de URL personalizados
- Elegir un esquema único.
- Validar todos los parámetros.
- Defenderse del secuestro de URL.
- Defenderse de redireccionamientos abiertos.
- Limitar
LSApplicationQueriesSchemesa los esquemas conocidos y necesarios.
Fase 9: Ingeniería inversa y resistencia a la manipulación (tampering)
Reducir filtraciones estáticas
- Eliminar los símbolos de los binarios enviados a la tienda.
- Almacenar dSYMs en el lado del servidor para la simbolización de fallos.
- Eliminar registros detallados en compilaciones de lanzamiento.
- Eliminar menús de depuración en compilaciones de lanzamiento.
- Eliminar endpoints de prueba en compilaciones de lanzamiento.
- Eliminar alternadores de funciones (feature toggles) no destinados a producción.
Controles de entorno
- Registrar señales sobre la presencia de jailbreak (archivos, llamadas al sistema, bibliotecas sospechosas).
- Registrar señales sobre frameworks de hooking.
- Registrar señales sobre la presencia de un depurador.
- Responder de forma proporcional (degradación/bloqueo/telemetría) sin basarse únicamente en controles del cliente.
Pruebas de manipulación (Tamper testing)
- Validar que las compilaciones reempaquetadas fallen en los controles de integridad o en la certificación del servidor.
- Validar que las compilaciones re-firmadas fallen en los controles de integridad o en la certificación del servidor.
- Tratar los controles del lado del cliente como señales, nunca como el único control de seguridad.
Fase 10: Criptografía y aleatoriedad
- Utilizar criptografía de plataforma (
CryptoKit/CommonCrypto); no implementar criptografía personalizada. - Utilizar AES-GCM o ChaCha20-Poly1305 para el cifrado autenticado.
- Utilizar HKDF/PBKDF2 como KDF con la sal adecuada y parámetros adecuados.
- Generar claves/IVs con
SecRandomCopyBytes. - Nunca reutilizar IVs/nonces.
- Almacenar las claves criptográficas en el Keychain.
Fase 11: Permisos, notificaciones e identificadores
- Solicitar los permisos mínimos requeridos.
- Solicitar permisos en el momento de uso.
- Explicar claramente la propuesta de valor a los usuarios al solicitar permisos.
ATT (App Tracking Transparency)
- Solicitar ATT solo si es necesario.
- Degradar de forma elegante si se deniega el ATT.
- Evitar el fingerprinting y técnicas de seguimiento prohibidas similares.
Identificadores
- Preferir
identifierForVendor. - Evitar IDFA a menos que se haya otorgado ATT.
- Nunca usar identificadores persistentes prohibidos.
Fase 12: Registros, analíticas (analytics) e informes de fallos
- Utilizar
os_logcon anotaciones de privacidad. - Desactivar los registros detallados en compilaciones de lanzamiento.
- Ocultar PII de los registros.
- Ocultar secretos de los registros.
- Ocultar PII y secretos de los eventos analíticos.
- Ocultar PII y secretos de los informes de fallos.
- Muestrear y agregar analíticas donde sea posible.
- Asegurarse de que la simbolización de fallos se produzca del lado del servidor.
- Nunca incluir símbolos con la aplicación.
Fase 13: Pruebas, DAST y verificación en tiempo de ejecución
Pruebas de intercepción de tráfico
- Verificar la resistencia a MITM con un certificado no válido.
- Verificar la resistencia a MITM con nombres de host no coincidentes.
- Verificar la resistencia a MITM con una CA no confiable.
- Confirmar que la fijación (pinning) bloquea la intercepción donde se implementa.
Inspección en tiempo de ejecución
- Confirmar que no haya secretos/PII en los registros.
- Confirmar que los elementos del Keychain están presentes con las ACL (Listas de Control de Acceso) correctas.
- Confirmar que los archivos tienen
NSFileProtectionComplete(o más estricto cuando sea necesario).
Pruebas de abuso de API
- Probar la limitación de la tasa de peticiones (rate limiting).
- Probar las protecciones contra ataques de repetición (replay protections).
- Probar los límites de paginación.
- Probar si hay vulnerabilidades de asignación masiva (mass assignment).
- Probar si hay fugas detalladas de errores.
Análisis dinámico
- Ejecutar DAST móvil al ejercitar los flujos principales para descubrir configuraciones erróneas de transporte.
- Utilizar DAST para descubrir problemas de ejecución (ej. con Ostorlab).
- Exportar evidencia para clasificación y re-pruebas.
Fase 14: SBOM y evidencia
SBOM y dependencias
- Generar SBOM para el código Swift/Objective-C.
- Generar SBOM para SDKs incrustados.
- Realizar seguimiento de los CVEs que afectan a las dependencias.
- Actualizar dependencias periódicamente en función del riesgo.
Paquete de evidencia
- Adjuntar artefactos de escaneo al lanzamiento.
- Adjuntar SBOM al lanzamiento.
- Adjuntar diferencias (diffs) de Info.plist al lanzamiento.
- Adjuntar listas de autorizaciones (entitlements) al lanzamiento.
- Adjuntar informes de pruebas al lanzamiento.
Fase 15: Informes y alineación con estándares
Informe
- Elaborar un resumen ejecutivo.
- Documentar el alcance y la metodología.
- Documentar hallazgos detallados con PoCs y evidencia.
- Asignar calificaciones de riesgo a los hallazgos.
- Proporcionar orientación para la corrección.
- Incluir resultados de re-pruebas.
Mapeo con OWASP MASVS
- PLATFORM: Fases 2, 7–8, 11.
- STORAGE: Fases 3–4.
- CRYPTO: Fase 10.
- AUTH: Fase 6.
- NETWORK: Fase 5.
- CODE: Fases 2, 9, 12.
- RESILIENCE: Fase 9.
Referencia rápida para el profesional
- Info.plist/ATS: Sin cargas arbitrarias; dominios de excepción estrictos; deshabilitar uso compartido de documentos/archivos a menos que sea necesario.
- Keychain: Clases
ThisDeviceOnly;biometryCurrentSet/userPresenceopcional; eliminar secretos al cerrar sesión. - Archivos:
NSFileProtectionComplete; cifrar bases de datos/archivos; evitarUserDefaultspara los secretos. - Network: Solo HTTPS; fijación mediante
URLSessionDelegate(SPKI SHA-256 con respaldos); verificar que los intentos de MITM fallan. - Auth: OIDC + PKCE; tokens de corta duración; tokens de actualización en el Keychain; autorización del lado del servidor; probar IDOR/BOLA.
- WebView: Preferir el navegador del sistema para la autenticación; si es
WKWebView, JS desactivado por defecto, permitir navegación en listas, dominios vinculados a la aplicación, almacenamiento no persistente para flujos sensibles. - Privacidad: Enmascarar instantáneas de fondo; evitar secretos en el portapapeles; minimizar permisos y mantener cadenas de uso precisas.
- Higiene de lanzamiento: Eliminar símbolos en la aplicación, mantener dSYMs privados; eliminar registros/menús de depuración; validar autorizaciones (entitlements).
Configuraciones y fragmentos de ejemplo
ATS (Info.plist)
- Configurar
NSAppTransportSecurity: -
NSAllowsArbitraryLoads = false -
NSExceptionDomains = { yourdomain.com: { NSTemporaryExceptionAllowsInsecureHTTPLoads = false, NSIncludesSubdomains = true, NSTemporaryExceptionMinimumTLSVersion = TLSv1.2 } }
Protección de archivos (Swift)
- Utilizar la protección completa de archivos:
-
try data.write(to: url, options: .completeFileProtection)
Elemento del Keychain (ejemplo en Swift)
- Configurar el elemento del Keychain:
-
kSecClass: kSecClassGenericPassword -
kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly -
kSecAttrAccessControl: SecAccessControlCreateWithFlags(..., [.biometryCurrentSet, .userPresence])
Fijación de URLSession (resumen)
- En
urlSession(_:didReceive:completionHandler:): - Evaluar
SecTrust. - Extraer SPKI del certificado.
- Comparar SHA-256 del SPKI con una lista de permitidos de pines.
- Elegir
.useCredentialo.canceladecuadamente.
Flujos de trabajo ligeros
Puerta de validación previa a la fusión (Pre-merge gate)
- Ejecutar lints y pruebas.
- Ejecutar auditoría de dependencias.
- Desencadenar escaneos SAST/SCA.
- Bloquear la fusión ante problemas Altos/Críticos.
Entorno de ensayo previo al lanzamiento (Pre-release staging)
- Validar Info.plist y autorizaciones (entitlements).
- Compilar el binario de lanzamiento.
- Confirmar que los símbolos no se envían en la aplicación.
- Ejecutar DAST al ejercitar los principales flujos de usuario (ej. con Ostorlab) para validar TLS/fijación, la protección de almacenamiento y la higiene de registros.
- Solucionar problemas y volver a probar.
Monitoreo posterior al lanzamiento (Post-release monitoring)
- Realizar seguimiento de fallos y rendimiento.
- Rotar claves/tokens en un cronograma definido.
- Monitorear advertencias de seguridad sobre SDKs y CVEs.
- Mantener SCA vigilando SDKs/bibliotecas de terceros (ej. Ostorlab) para alertar sobre nuevas vulnerabilidades.
- Desencadenar re-pruebas focalizadas cuando se encuentren nuevas vulnerabilidades.