Jailbreak checker — как обезопасить свое iOS-приложение
Привет! Меня зовут Тоня, я продуктовый разработчик в продукте QIWI Кошелек. Недавно мы делали задачу по предотвращению рисков в связи с использованием приложения с Jailbreak. Хочу рассказать о трудностях, с которыми столкнулись на пути, и о том, как мы их разрешили.
Кто такой этот ваш Jailbreak?
Наверное, каждый хоть раз слышал слово jailbreak, но давайте разберемся, зачем это нужно, чем опасно и как его обнаружить.
Дословно jailbreak переводится как «побег из тюрьмы» или «взлом». Данный термин, как правило, используется в отношении iOS. Простыми словами — это использование уязвимостей устройства для получения полного доступа к операционной системе. Из-за такого полного доступа к системе появляется и доступ до keychain, который становится уже не таким защищенным. После взлома у пользователя появляется доступ к альтернативным сторам, из которых можно скачать приложения, не проходившие ревью в App Store. Одним из самых популярных таких альтернативных сторов является Cydia, который чаще всего сразу же устанавливается в момент взлома устройства.
Зачем его отслеживать?
После джейлбрейка у мошенников появляется возможность взлома устройства по нескольким причинам. Приложения, которые становится возможным скачать в результате джейлбрейка, не проверяются никем, в отличие от случая с App Store, поэтому могут быть небезопасны. Также Apple не поддерживает устройства с jailbreak, из-за чего после взлома они перестают получать важные обновления, в том числе обновления системы безопасности. В случае взлома устройства компания Apple аннулирует гарантию на него, и при поломке его уже нельзя будет отремонтировать в официальном сервисе.
Чем же это может быть опасно для вашего приложения? Если оно работает с персональными данными либо с денежными средствами — следует, как минимум, предупредить пользователя о том, что это небезопасно. Тем более, это будет небезопасно, если ваше приложение используется в качестве двухфакторной аутентификации. Так как устройство не получает необходимые обновления безопасности, это упрощает для мошенников получение доступа к данным, например с использованием приложений, которые не проходили ревью от Apple.
Мы реализовывали проверку устройства на JailBreak, прежде чем предоставить пользователю возможность подключить себе Apple Pay, для того, чтобы избежать быстрого и простого доступа мошенников к картам. Но с уходом Apple Pay эта проблема стала уже не такой актуальной.
В памятке Центрального банка о мерах по обеспечению безопасности при работе в системе дистанционного банковского обслуживания физических лиц Банка России сказано следующее:
В целях минимизации рисков при использовании Системы дистанционного банковского обслуживания Банк просит клиентов для обеспечения безопасности их денежных средств не выполнять операции по повышению привилегий или взлому операционной системы мобильного устройства (получение root-прав для Android, установка jailbreak для iOS), на котором установлено или планируется установка мобильного приложения. Не устанавливать мобильное приложение на устройство, которое уже получило такие привилегии.
Данный пункт памятки приводит нас к тому, что в банковских приложениях необходимо отслеживать jailbreak и предупреждать пользователя о всех рисках, связанных со взломом.
Как же его отследить?
Есть несколько признаков того, что на телефоне настроен jailbreak. Вот так реализовали проверку мы:
Наличие альтернативных сторов на устройстве. В первую — очередь проверка стора Cydia. Сделать это можно несколькими способами. Например, проверить, устройство на наличие обработчика протокола
cydia://
: вот так:
static func hasCydiaInstalled() -> Bool {
return UIApplication.shared.canOpenURL(URL(string: "cydia://")!)
}
Либо можно просто проверить, установлены ли сторонние сторы на устройстве. Вот список таких сторов:
private static var suspiciousAppsPathToCheck: [String] {
return [
"/Applications/Cydia.app",
"/Applications/blackra1n.app",
"/Applications/FakeCarrier.app",
"/Applications/Icy.app",
"/Applications/IntelliScreen.app",
"/Applications/MxTube.app",
"/Applications/RockApp.app",
"/Applications/SBSettings.app",
"/Applications/WinterBoard.app",
]
}
Для того чтобы узнать, есть ли эти приложения на устройстве, нужно проверить с помощью FileManager, существует ли какой-нибудь файл на устройстве из списка, написанного ранее.
for path in suspiciousAppsPathToCheck where FileManager.default.fileExists(atPath: path) {
return true
}
Проверить устройство на наличие подозрительных файлов. К списку таких файлов можно отнести следующие:
static var suspiciousSystemPathsToCheck: [String] {
return [
"/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
"/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
"/private/var/lib/apt",
"/private/var/lib/apt/",
"/private/var/lib/cydia",
"/private/var/mobile/Library/SBSettings/Themes",
"/private/var/stash",
"/private/var/tmp/cydia.log",
"/System/Library/LaunchDaemons/com.ikey.bbot.plist",
"/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
"/usr/bin/sshd",
"/usr/libexec/sftp-server",
"/usr/sbin/sshd",
"/etc/apt",
"/bin/bash",
"/Library/MobileSubstrate/MobileSubstrate.dylib"
]
}
Проверка на наличие этих файлов осуществляется так же, как и проверка на наличие подозрительных сторов — с помощью FileManager:
static func isSuspiciousSystemPathsExists() -> Bool {
for path in suspiciousSystemPathsToCheck {
if FileManager.default.fileExists(atPath: path) {
return true
}
}
return false
}
Список таких файлов и приложений может постепенно пополняться. Наиболее актуальные списки можно найти на разных ресурсах в открытом доступе, например вот тут.
Проверить, может ли приложение создавать или изменять файлы, которые находятся за пределами изолированной среды приложения. Например, может ли приложение записать текст в файл в каталоге
/private
. Если ошибок во время выполнения этого действия не возникнет — устройство взломано:
static func canEditSystemFiles() -> Bool {
let jailBreakText = "Device is JailBroken ?"
do {
try jailBreakText.write(toFile: "/private/jailbreak.txt", atomically: true, encoding: .utf8)
return true
} catch {
return false
}
}
Также проверить доступ к подозрительным файлам можно проверить с помощью функции
fopen()
:
if UnsafeMutablePointer<FILE>(fopen("/bin/bash", "r")) != nil ||
UnsafeMutablePointer<FILE>(fopen("/Library/MobileSubstrate/MobileSubstrate.dylib", "r")) != nil ||
UnsafeMutablePointer<FILE>(fopen("/usr/sbin/sshd", "r")) != nil ||
UnsafeMutablePointer<FILE>(fopen("/etc/apt", "r")) != nil ||
UnsafeMutablePointer<FILE>(fopen("/Applications/Cydia.app", "r")) != nil {
return true
}
По итогам всех проверок можно сказать — если хоть в одном из мест вернулось true, то мы можем утверждать, что на этом девайсе JailBreak.
Как предупредить пользователя и обезопасить приложение?
Лучше всего отловить пользователя с JailBreak до того, как он получит доступ к персональным данным или к денежным средствам. В нашей ситуации достаточно было лишь предупредить пользователя об опасности и сохранить данные о том, что он принял риски.
Для этого мы проверяем устройство пользователя еще до того, как он успел войти в свой аккаунт. После чего в случае согласия на риски мы локально на устройстве сохраняем время и факт согласия.
Также локальное хранилище помогает без авторизации отследить, предупреждали ли мы уже этого пользователя о рисках, или нет, чтобы каждый раз не показывать ему предупреждение при входе.
А как теперь все протестить?
Если вы уже попробовали эти проверки, наверняка заметили, что на симуляторе каждый раз показывается, что настроен JailBreak. Это происходит из-за того, что срабатывает проверка на открытие "/bin/bash"
.
Это упрощает тестирование и отладку работы проверки на JailBreak, но при этом создает проблемы для автотестов и для дальнейшей работы с симулятором. Исправить это можно простой проверкой на таргет устройства, на котором запущено приложение, до того, как начать проверять на наличие JailBreak на устройстве:
#if targetEnvironment(simulator)
return false
#else
// все остальные проверки
#endif
А для того, чтобы написать автотесты на данную фичу, мы просто добавили новый булевый аргумент запуска приложения, который кидаем из автотестов и проверяем его перед началом всех проверок на JailBreak.
P.S.
Когда только реализовывали фичу, нам казалось, что в 2023 году уже никто не взламывает свои телефоны, но к нашему удивлению аналитика показала, что таких случаев достаточно. Поэтому данная задача потерять свою актуальность еще не успела.