Безопасность Swift приложений: топ-10 уязвимостей для новичков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Безопасность Swift приложений: топ-10 уязвимостей для начинающих

Разработка мобильных и десктопных приложений на Swift требует не только знания синтаксиса и фреймворков, но и понимания основ кибербезопасности. Даже небольшая ошибка в коде может привести к утечке пользовательских данных или компрометации устройства. В этой статье мы разберем топ-10 распространенных уязвимостей Swift-приложений, с которыми сталкиваются начинающие разработчики, и покажем, как их избежать.

1. Незащищенное хранение данных (Insecure Data Storage)

Одна из самых частых ошибок — сохранение конфиденциальной информации (паролей, токенов, ключей API) в UserDefaults или в обычных текстовых файлах. Эти данные легко извлечь на джейлбрейкнутом устройстве.

// Неправильно: хранение пароля в UserDefaults
UserDefaults.standard.set("mySecretPassword", forKey: "userPassword")

// Правильно: использование Keychain
import Security
let password = "mySecretPassword"
let keychainItem = [
    kSecClass: kSecClassGenericPassword,
    kSecAttrAccount: "userPassword",
    kSecValueData: password.data(using: .utf8)!
] as CFDictionary
SecItemAdd(keychainItem, nil)

2. Инъекции через SQLite и Core Data

Использование необработанных строк в запросах к базе данных открывает путь для SQL-инъекций. Даже если вы используете Core Data, небезопасные предикаты могут быть атакованы.

// Неправильно: прямая подстановка
let username = "admin' OR '1'='1"
let query = "SELECT * FROM users WHERE name = '\(username)'"

// Правильно: использование параметризованных запросов (FMDB)
let query = "SELECT * FROM users WHERE name = ?"
db.executeQuery(query, withArgumentsIn: [username])

3. Отсутствие HTTPS и SSL Pinning

Использование HTTP вместо HTTPS делает приложение уязвимым для атак "человек посередине" (MITM). Даже с HTTPS рекомендуется применять SSL Pinning для дополнительной защиты.

// Настройка HTTPS в Info.plist
// <key>NSAppTransportSecurity</key>
// <dict>
//     <key>NSAllowsArbitraryLoads</key>
//     <false/>
// </dict>

// Реализация SSL Pinning с помощью URLSession
let pinnedKeys = ["yourPublicKeyHash"]
let delegate = URLSessionPinningDelegate(pinnedKeys: pinnedKeys)
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)

4. Слабые алгоритмы шифрования

Использование устаревших алгоритмов шифрования (MD5, SHA1) или самодельных криптографических функций делает данные уязвимыми. Всегда используйте современные библиотеки.

// Неправильно: MD5
let hash = MD5(string: "password")

// Правильно: использование CommonCrypto с SHA256
import CommonCrypto
func 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. Недостаточная проверка ввода (Input Validation)

Отсутствие валидации пользовательского ввода может привести к XSS-атакам (в WebView) или повреждению данных. Проверяйте все входные данные на длину, формат и содержание.

// Неправильно: доверие вводу
let userInput = textField.text
webView.loadHTMLString(userInput!, baseURL: nil)

// Правильно: санитизация ввода
func sanitizeInput(_ input: String) -> String {
    return input
        .replacingOccurrences(of: "&", with: "&")
        .replacingOccurrences(of: "<", with: "<")
        .replacingOccurrences(of: ">", with: ">")
}

6. Утечка данных через логи и отладку

Оставленные в продакшене print() или NSLog могут выдать конфиденциальные данные. Используйте условную компиляцию для отладочных сообщений.

// Неправильно: логирование в продакшене
print("User token: \(userToken)")

// Правильно: условная компиляция
#if DEBUG
    print("User token: \(userToken)")
#endif

7. Небезопасное использование WebView

Загрузка произвольных URL или включение JavaScript без ограничений может привести к XSS и фишинговым атакам. Настройте WKWebView правильно.

// Неправильно: полный доступ
let webView = WKWebView()
webView.load(URLRequest(url: URL(string: "http://example.com")!))

// Правильно: ограничения
let config = WKWebViewConfiguration()
config.preferences.javaScriptEnabled = false // если не нужен JS
let webView = WKWebView(frame: .zero, configuration: config)
webView.loadFileURL(localURL, allowingReadAccessTo: baseURL)

8. Отсутствие проверки целостности кода (Code Integrity)

Приложение должно проверять свою подпись при запуске, чтобы предотвратить модификацию злоумышленником. Используйте UIApplication или библиотеки.

// Проверка подписи приложения
func verifyAppIntegrity() -> Bool {
    guard let mainBundle = Bundle.main.executablePath else { return false }
    var fileStat = stat()
    stat(mainBundle, &fileStat)
    // Проверяем, что файл не был изменен
    return fileStat.st_size > 0 && fileStat.st_mtime > 0
}

9. Слабые пароли и отсутствие биометрии

Принуждение пользователей к сложным паролям и использование Face ID / Touch ID повышает безопасность. Не храните пароли в открытом виде.

// Использование LocalAuthentication
import LocalAuthentication
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, 
                          localizedReason: "Подтвердите личность") { success, error in
        if success {
            // Доступ разрешен
        }
    }
}

10. Неправильная обработка ошибок и исключений

Слишком подробные сообщения об ошибках могут раскрыть структуру приложения или пути к файлам. Всегда обрабатывайте ошибки корректно.

// Неправильно: раскрытие информации
catch let error                

Блоги

Рекомендаций по книгам