Segurança de aplicativos Swift: top 10 vulnerabilidades e métodos de proteção
Desenvolver em Swift para iOS e macOS requer atenção especial à segurança. Até mesmo um pequeno erro pode levar a vazamento de dados, invasão ou comprometimento do dispositivo. Neste artigo, vamos analisar as 10 vulnerabilidades mais comuns em aplicativos Swift, mostrar exemplos de código perigoso e dar recomendações práticas para corrigi-las.
1. Armazenamento inseguro de dados (Insecure Data Storage)
O erro mais comum é salvar dados confidenciais em UserDefaults ou arquivos Plist sem criptografia.
Código problemático:
UserDefaults.standard.set("password123", forKey: "userPassword")UserDefaults.standard.synchronize()Solução segura: Use Keychain Services ou Data Protection API.
import Security
func savePassword(_ password: String, for account: String) { let data = password.data(using: .utf8)! let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecValueData as String: data, kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly ] SecItemAdd(query as CFDictionary, nil)}2. Ausência de validação de entrada (Input Validation)
A entrada do usuário frequentemente contém dados maliciosos. Sempre verifique e sanitize a entrada.
Exemplo de SQL Injection:
let query = "SELECT * FROM users WHERE name = '\\(userInput)'" // Perigoso!Proteção: Use consultas parametrizadas.
let query = "SELECT * FROM users WHERE name = ?"let statement = try database.prepare(query)try statement.bind([userInput])3. Comunicação de rede insegura (Insecure Network Communication)
Uso de HTTP em vez de HTTPS, ignorando certificados SSL.
Código perigoso:
let url = URL(string: "http://example.com/api")! // HTTP, não HTTPSlet task = URLSession.shared.dataTask(with: url) { data, response, error in // Processamento dos dados}Abordagem segura:
let url = URL(string: "https://example.com/api")!let config = URLSessionConfiguration.defaultconfig.tlsMinimumSupportedProtocolVersion = .TLSv12let session = URLSession(configuration: config)let task = session.dataTask(with: url) { data, response, error in guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { return } // Processamento dos dados}task.resume()4. Injeção de código via WebView (WebView Injection)
Se você usa WKWebView sem restrições, um invasor pode executar código JavaScript.
Código vulnerável:
webView.loadHTMLString(htmlContent, baseURL: nil)Proteção: Desabilite o JavaScript ou use Content Security Policy.
let config = WKWebViewConfiguration()let preferences = WKPreferences()preferences.javaScriptEnabled = falseconfig.preferences = preferenceslet webView = WKWebView(frame: .zero, configuration: config)5. Chaves de API e tokens não protegidos (Hardcoded Secrets)
Nunca armazene chaves de API, tokens ou senhas no código fonte.
Incorreto:
let apiKey = "sk_live_1234567890abcdef"Correto: Use arquivos .env, autorização no servidor ou serviços em nuvem (por exemplo, AWS Secrets Manager).
// Chave criptografada no Info.plistif let apiKey = Bundle.main.object(forInfoDictionaryKey: "API_KEY") as? String { // Usamos a chave}