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

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

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

Начать курс

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

Swift — мощный и современный язык программирования, созданный Apple для разработки приложений под iOS, macOS, watchOS и tvOS. Несмотря на встроенные механизмы безопасности (ARC, безопасная работа с памятью, опциональные типы), тысячи приложений ежегодно становятся жертвами атак из-за ошибок разработчиков. Согласно отчету OWASP Mobile Top 10, большинство уязвимостей в мобильных приложениях возникают на стороне клиента. В этой статье мы разберем 10 наиболее распространенных уязвимостей Swift-приложений, приведем примеры кода и покажем, как их избежать.

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

Проблема

Разработчики часто сохраняют конфиденциальные данные (токены, пароли, ключи API) в UserDefaults, Plist-файлах или Core Data без шифрования. На джейлбрейкнутых устройствах злоумышленник может легко получить к ним доступ.

Пример уязвимого кода

// Уязвимый код
UserDefaults.standard.set("secret_token_123", forKey: "api_token")
UserDefaults.standard.set("password123", forKey: "user_password")

Решение

Используйте Keychain для хранения чувствительных данных. Swift имеет удобные обертки, такие как KeychainSwift или Security framework.

// Безопасное хранение с Keychain
import KeychainSwift

let keychain = KeychainSwift()
keychain.set("secret_token_123", forKey: "api_token")
keychain.set("password123", forKey: "user_password", withAccess: .accessibleWhenUnlockedThisDeviceOnly)

2. Инъекция кода и SQL-инъекции (Code Injection & SQL Injection)

Проблема

Если ваше приложение использует SQLite, Core Data с NSPredicate или WebView для отображения веб-контента, злоумышленник может внедрить вредоносный код через пользовательский ввод.

Пример уязвимого кода

// Уязвимый запрос к SQLite
let userInput = "1' OR '1'='1"
let query = "SELECT * FROM users WHERE id = '\(userInput)'"

Решение

Используйте параметризованные запросы или NSPredicate с безопасными подстановками.

// Безопасный запрос с параметрами
let query = "SELECT * FROM users WHERE id = ?"
let statement = try db.prepare(query)
try statement.bind(1, userInput)

3. Незащищенная сетевая коммуникация (Insecure Network Communication)

Проблема

Использование HTTP вместо HTTPS, игнорирование SSL-сертификатов (App Transport Security) или отправка данных без шифрования.

Пример уязвимого кода

// Уязвимый код: отключение ATS
let url = URL(string: "http://example.com/api/login")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
    // Обработка незащищенных данных
}

Решение

Настройте App Transport Security (ATS) в Info.plist и используйте HTTPS. Для проверки сертификатов применяйте SSL pinning.

// Безопасный запрос с SSL Pinning (пример с Alamofire)
let evaluator = PinnedCertificatesTrustEvaluator(certificates: [certificate])
let session = Session(serverTrustManager: ServerTrustManager(evaluators: ["example.com": evaluator]))
session.request("https://example.com/api/login").responseJSON { response in
    // Обработка защищенных данных
}

4. Инъекция через WebView (WebView Injection)

Проблема

Загрузка HTML-контента с пользовательскими данными в WKWebView без санитизации может привести к XSS-атакам и краже cookies.

Пример уязвимого кода

// Уязвимый код
let userComment = "<script>alert('XSS')</script>"
let html = "<html><body>\(userComment)</body></html>"
webView.loadHTMLString(html, baseURL: nil)

Решение

Экранируйте HTML-символы и используйте WKUserContentController для безопасной коммуникации.

// Безопасное экранирование
extension String {
    func escapeHTML() -> String {
        return self
            .replacingOccurrences(of: "&", with: "&")
            .replacingOccurrences(of: "<", with: "<")
            .replacingOccurrences(of: ">", with: ">")
            .replacingOccurrences(of: "\"", with: """)
    }
}
let safeComment = userComment.escapeHTML()
let html = "<html><body>\(safeComment)</body></html>"

5. Недостаточная защита от обратной разработки (Reverse Engineering)

Проблема

Swift-код компилируется в бинарный файл Mach-O, который можно дизассемблировать с помощью инструментов (Hopper, IDA Pro, Ghidra). Злоумышленник может извлечь строки, ключи шифрования и логику приложения.

Пример уязвимого кода

// Уязвимый код: хранение ключа в строке
let apiKey = "sk_live_1234567890abcdef"

Решение

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

// Обфускация ключа
let apiKey = String(data: Data(base64Encoded: "c2tfbGl2ZV8xMjM0NTY3ODkwYWJjZGVm")!, encoding: .utf8)!

// Проверка на джейлбрейк
func isJailbroken() -> Bool {
    let paths = ["/Applications/Cydia.app", "/Library/MobileSubstrate/MobileSubstrate.dylib"]
    return paths.contains { FileManager.default.fileExists(atPath:                

Блоги

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