Seguridad de aplicaciones Swift: top-10 vulnerabilidades para principiantes
El desarrollo de aplicaciones móviles y de escritorio en Swift requiere no solo conocimiento de sintaxis y frameworks, sino también comprensión de los fundamentos de ciberseguridad. Incluso un pequeño error en el código puede provocar una fuga de datos del usuario o comprometer el dispositivo. En este artículo analizaremos el top-10 de vulnerabilidades comunes en aplicaciones Swift que enfrentan los desarrolladores principiantes y mostraremos cómo evitarlas.
1. Almacenamiento de datos no seguro (Insecure Data Storage)
Uno de los errores más frecuentes es guardar información confidencial (contraseñas, tokens, claves de API) en UserDefaults o en archivos de texto plano. Estos datos se pueden extraer fácilmente en un dispositivo con jailbreak.
// Incorrecto: almacenar contraseña en UserDefaultsUserDefaults.standard.set("mySecretPassword", forKey: "userPassword")
// Correcto: usar Keychainimport Securitylet password = "mySecretPassword"let keychainItem = [ kSecClass: kSecClassGenericPassword, kSecAttrAccount: "userPassword", kSecValueData: password.data(using: .utf8)!] as CFDictionarySecItemAdd(keychainItem, nil)2. Inyecciones a través de SQLite y Core Data
Usar cadenas sin procesar en consultas a la base de datos abre la puerta a inyecciones SQL. Incluso si usas Core Data, los predicados no seguros pueden ser atacados.
// Incorrecto: sustitución directalet username = "admin' OR '1'='1"let query = "SELECT * FROM users WHERE name = '\\(username)'"
// Correcto: usar consultas parametrizadas (FMDB)let query = "SELECT * FROM users WHERE name = ?"db.executeQuery(query, withArgumentsIn: [username])3. Falta de HTTPS y SSL Pinning
Usar HTTP en lugar de HTTPS hace que la aplicación sea vulnerable a ataques de "hombre en el medio" (MITM). Incluso con HTTPS, se recomienda aplicar SSL Pinning para protección adicional.
// Configuración de HTTPS en Info.plist// <key>NSAppTransportSecurity</key>// <dict>// <key>NSAllowsArbitraryLoads</key>// <false/>// </dict>
// Implementación de SSL Pinning con URLSessionlet pinnedKeys = ["yourPublicKeyHash"]let delegate = URLSessionPinningDelegate(pinnedKeys: pinnedKeys)let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)4. Algoritmos de cifrado débiles
Usar algoritmos de cifrado obsoletos (MD5, SHA1) o funciones criptográficas caseras hace que los datos sean vulnerables. Siempre usa bibliotecas modernas.
// Incorrecto: MD5let hash = MD5(string: "password")
// Correcto: usar CommonCrypto con SHA256import CommonCryptofunc sha256(_ data: Data) -> Data { var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) data.withUnsafeBytes { _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash) } return Data(hash)}5. Validación de entrada insuficiente (Input Validation)
La falta de validación de la entrada del usuario puede provocar ataques XSS (en WebView) o corrupción de datos. Verifica todos los datos de entrada en cuanto a longitud, formato y contenido.
// Incorrecto: confiar en la entradalet userInput = textField.textwebView.loadHTMLString(userInput!, baseURL: nil)
// Correcto: sanitización de entradafunc sanitizeInput(_ input: String) -> String { return input .replacingOccurrences(of: "&", with: "&") .replacingOccurrences(of: "<", with: "<") .replacingOccurrences(of: ">", with: ">")}6. Fuga de datos a través de registros y depuración
Los print() o NSLog dejados en producción pueden revelar datos confidenciales. Usa compilación condicional para mensajes de depuración.
// Incorrecto: registro en producción