Обходим защиту iOS клиента Dropbox

Что в первую очередь сделает iOS разработчик, если перед ним встанет задача спрятать пользовательские данные от любопытных глаз? Конечно же, встроит экран парольной защиты. Особо хитрый разработчик даже не будет хранить установленный пользователем пароль в NSUserDefaults, а аккуратно спрячет его в связку ключей — в этом случае приложение в глазах как его, так и заказчика, сразу же перемещается в разряд «сверхзащищенных».
Мы не будем углубляться в описание опасностей хранения ключа в открытом доступе — ведь есть гораздо более интересный способ обхода такой защиты.

IMG_0008

Cycript — консольная утилита, позволяющая подключаться к Mac OS X и iOS приложениям во время их выполнения. Для работы с кодом исполняемого приложения используется гибрид Javascript и Objective-C++. Проект живет с 2007 года, изначально представляв собой мост между Javascript и Objective-C. Cycript интересен в первую очередь тем, что позволяет исследовать приложение “изнутри”, посылая сообщения любому из его объектов. Кстати, автор проекта — сам @saurik.

Внимание: для работы с Cycript необходим Jailbreak (разработчики, тем не менее, могут подключить библиотеку к своему проекту, чтобы получить возможность тестировать приложение на “чистом» устройстве).

Установка Cycript предельно проста — качаем последнюю версию пакета и заливаем ее по sftp на наше устройство:
sftp>put cycript.deb

после чего подключаемся по ssh и устанавливаем пакет:
iPad:/tmp root# dpkg -i cycript.deb

В качестве объекта тестирования был выбран клиент Dropbox, позволяющий установить экран парольной защиты, который появляется каждый раз при открытии приложения. Запустим Dropbox, заранее включив опцию запроса пароля:
IMG_0006

Узнаем идентификатор процесса запущенного приложения, после чего подключимся к нему:
iPad:~ root# ps aux | grep Dropbox
mobile 283 0.0 10.1 641388 52020 ?? Ss 5:41PM 0:19.15 /var/mobile/Containers/Bundle/Application/93E2B5E6-B7EC-4D18-9697-021D24429D29/Dropbox.app/Dropbox
root 328 0.0 0.1 536256 440 s000 S+ 6:07PM 0:00.01 grep Dropbox
iPad:~ root# cycript -p 283

Посмотрим, что представляет собой rootViewController запущенного приложения:
cy# UIApp.keyWindow.rootViewController
#DBSplitViewController: 0x16bc02a0

Теперь проверим, какой контроллер сейчас отображен на экране:
cy# UIApp.keyWindow.rootViewController.presentedViewController
#PasscodeFullscreenController: 0x187c8b50

Название обнадеживает :) Обратимся к одной из сильных сторон использования Cycript и определим свою функцию, которая покажет нам все методы, определенные для выбранного класса:

Теперь мы можем использовать эту функцию и посмотреть, чем занимается PasscodeFullscreenController:
cy# printMethods(PasscodeFullscreenController)

А теперь объявим переменную, содержащую текущий экземпляр этого класса, и посмотрим список его переменных:
cy# var PasscodeFullscreenController = #0x187c8b50
#»PasscodeFullscreenController: 0x187c8b50″
cy# *PasscodeFullscreenController

Судя по всему, нам нужно прямиком в PasscodeViewController:

cy# printMethods(PasscodeViewController)

Похоже, что первый метод делает именно то, что нас интересует. Проверим:
cy# var PasscodeViewController = #0x187c8730
#»PasscodeViewController: 0x187c8730″
cy# [PasscodeViewController dismissPasscodeAnimated:YES]

При вызове этого метода экран с вводом пароля волшебным образом скрывается, и мы получаем полный доступ к файлам залогиненного пользователя.
IMG_0007

Тем не менее, каждый раз вводить пароль достаточно утомительно, поэтому нашей задачей максимум является полное его отключение. Исследуем настройки приложения:
IMG_0001

При выборе пункта “Passcode Lock” появляется уже знакомая форма ввода пароля. Воспользуемся уже знакомым нам способом чтобы от нее избавиться:
cy# var PasscodeController2 = #0x1992aab0
#»PasscodeViewController: 0x1992aab0″
cy# [PasscodeController2 dismissPasscodeAnimated:YES]

Но на этот раз простым скрытием формы проблема не решается, так как меню работы с паролем не появляется. Попробуем найти другой путь.
Посмотрим все сообщения, которые может принимать PasscodeViewController (сюда включаются также методы его родителей и категорий):
cy# PasscodeViewController.messages

Среди сотни различных селекторов интерес представляет следующий:
db_handleVerifyModeCorrectPasscodeEntered:0xb1bd5

И действительно, его вызов закрывает экран ввода пароля и открывает настройки. Повторим то же самое при подтверждении отключения пароля:
IMG_0005

Теперь приложение можно спокойно закрывать — ввод пароля больше не требуется.

Мы рассмотрели отнюдь не весь функционал Cycript — помимо этого, он позволяет определять свои классы, категории, работать с блоками, импортировать дополнительные библиотеки, производить method swizzling — одним словом, это очень мощный инструмент для пентестинга как своих, так и сторонних приложений.

Ну и напоследок небольшой список ссылок для дальнейшего изучения: