Безопасность мобильных приложений: OWASP MASVS, pinning и защита от реверса
OWASP Mobile Application Security Verification Standard — это не академический документ. Это список того, что проверяет пентестер в вашем приложении. И то, что находит — часто неприятно.
Certificate Pinning: зачем и как не сломать себе продакшн
Certificate Pinning — привязка приложения к конкретному TLS-сертификату или его публичному ключу. Без него трафик приложения перехватывается через прокси (Charles, mitmproxy) за пять минут — это OWASP MASVS-NETWORK-2.
На iOS реализуется через URLSessionDelegate.urlSession(_:didReceive:completionHandler:) с проверкой SecTrust. Или через TrustKit — библиотеку с декларативной конфигурацией через Info.plist. TrustKit также умеет отправлять отчёты о неудачных проверках на сервер — useful для мониторинга атак MITM в production.
На Android — network_security_config.xml:
<network-security-config>
<domain-config>
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2026-01-01">
<pin digest="SHA-256">base64_public_key_hash</pin>
<pin digest="SHA-256">backup_key_hash</pin>
</pin-set>
</domain-config>
</network-security-config>
Критически важно: всегда два пина — основной и резервный. Если сертификат истёк, а backup pin не настроен, все пользователи не смогут войти в приложение до следующего обновления. Именно так крупные приложения уходили в даунтайм.
Ещё одна точка отказа: CDN и third-party SDKs. Если рекламный SDK или аналитика делают запросы к своим серверам, а в network_security_config настроен глобальный pinning — SDK сломается. Конфигурация должна быть поддоменно-специфичной.
Обфускация и защита кода
iOS: Swift-код компилируется в нативный бинарник, который не декомпилируется до читаемого Swift. Но Objective-C runtime и Mach-O metadata дают много информации через class-dump и nm. Имена классов, методов, строки в бинарнике — всё видно. Для критичных строк (ключи конфигурации, не API-ключи — их там быть не должно) — обфускация через SwiftShield.
Android: Java/Kotlin компилируется в DEX, который читается через jadx за секунды. R8 (включён по умолчанию в release сборках) минифицирует и обфусцирует. Но ProGuard/R8 rules нужно тщательно настраивать: часто после включения обфускации приложение крашится в production из-за рефлексии или Gson-сериализации. Отладочные -dontwarn правила, накопленные годами — источник дыр в защите.
Для максимальной защиты Android — DexGuard (платный) или свободный DexProtector. Они добавляют runtime protection, шифрование строк и проверки целостности.
Обнаружение jailbreak и root
MASVS-RESILIENCE-1 требует обнаружения компрометированных устройств. Стандартные проверки: наличие /Applications/Cydia.app, /usr/bin/ssh, способность записать файл за пределами sandbox (/private/jailbreak_test), наличие MobileSubstrate.
Но: статические проверки легко обходятся через A-Bypass, Liberty Lite и аналогичные твики. Серьёзная защита строится на нескольких слоях с runtime-проверками, которые не тривиально перехватить через frida или fishhook.
Готовые решения: IOSSecuritySuite (iOS, open source), rootbeer (Android). Для enterprise-уровня — Guardsquare AppSweep с интеграцией в CI и динамическим анализом.
Хранение данных и Keychain
MASVS-STORAGE-1 и STORAGE-2 — самые часто нарушаемые требования.
Частая ошибка на iOS: токены авторизации хранятся в UserDefaults. Данные из UserDefaults бэкапируются в iCloud и доступны при восстановлении на другое устройство. Токен из UserDefaults на новом устройстве — это чужая авторизованная сессия. Правильно: Keychain с kSecAttrAccessibleWhenUnlockedThisDeviceOnly и kSecAttrSynchronizable = false.
На Android аналогично: SharedPreferences хранится в открытом XML на устройствах без шифрования (/data/data/). EncryptedSharedPreferences из Jetpack Security или Android Keystore для ключевых данных.
| Уязвимость | MASVS требование | Инструмент проверки |
|---|---|---|
| Незащищённый трафик | NETWORK-1,2 | mitmproxy, Burp Suite |
| Данные в UserDefaults/SharedPrefs | STORAGE-1 | frida, objection |
| Отсутствие pinning | NETWORK-2 | Charles Proxy |
| Слабая обфускация | RESILIENCE-3 | jadx, class-dump |
| Нет jailbreak detection | RESILIENCE-1 | Jailbroken device test |
Сроки: security-аудит по OWASP MASVS уровню L1 — 1-2 недели. Реализация защитного слоя для существующего приложения — 3-6 недель в зависимости от найденных проблем.







