Исследование безопасности iOS-приложений, предназначенных для защиты фотографий
Многие люди хранят в телефоне пикантные фото, но по каким причинам – тема другой статьи. И здесь остро встает вопрос о том, как защитить фотографии, хранящиеся на мобильном устройстве.
Автор: Michael Allen @_Dark_Knight_
Мы слишком часто слышим печальные истории людей, потерявших мобильные телефоны с конфиденциальными фотографиями. Другой случай: кто-то одалживает телефон своим друзьям, а те начинают копаться внутри и просматривать фотоальбомы. Как бы то ни было, многие люди хранят в телефоне пикантные фото, но по каким причинам – тема другой статьи. И здесь остро встает вопрос о том, как защитить фотографии, хранящиеся на мобильном устройстве.
Один из вариантов решения этой проблемы – использовать специальное приложение, предназначенное для защиты фотографий, видео и другого контента. Подобные программы создают альбомы внутри контейнеров, доступ к которым осуществляется при помощи пароля, отпечатка пальца или TouchID. Последняя технология используется в случае, если устройство является одной из последних моделей.
Я решил присмотреться к некоторым из этих приложений под операционную систему iOS. Быстро вбив запрос «best photo vaults iOS» в гугле, я получил следующие варианты:
Рисунок 1: Перечень популярных iOS-приложений, предназначенных для защиты фотографий
В этой статье я буду исследовать несколько наиболее популярных бесплатных приложений, которые мне удалось найти.
Ингредиенты, необходимые для работы:
Джейлбрейковый iPhone 4S (7.1.2)
Шестнадцатеричный редактор (на ваш выбор)
Private Photo Vault
Photo+Video Vault Keep Safe (My Media)
Я буду рассказывать о наиболее распространенных техниках, используемых мной во время экспертизы iOS-приложений. Кроме того, на примере приложения Private Photo Vault мы немного углубимся в область реверс-инжиниринга. Техники, изложенные ниже, можно применять и при исследовании других приложений (останется читателю в качестве домашнего задания).
Примечание: если не сказано иного, все команды выполняются в Mac OS после подключения к джейлбрейковому устройству через ssh.
Анализ приложения Private Photo Vault
Первым подопытным приложением будет Private Photo Vault. Выяснилось, что уже написано несколько статей о проблемах, связанных с безопасностью этого приложения (см. раздел Ссылки). Поскольку уже прошло какое-то время с момента написания тех статей, я решил проверить, устранили ли разработчики приложения найденные проблемы. Оказалось, что (на момент написания данной заметки) некоторые уязвимости до сих пор не исправлены.
Обход экрана блокировки
При запуске приложения появляется экран с предложением о вводе пароля:
Рисунок 2: Экран блокировки
Обходи экрана блокировки не представляет особых сложностей. Вначале нужно найти процесс приложения, а затем подцепить cycript. Для тех, кто не знаком с cycript, привожу выдержку с сайта cycript.org:
«Cycript позволяет разработчикам исследовать и модифицировать приложения как в iOS, так и в Mac OS X. Синтаксис команд унаследован от Objective-C++ и JavaScript. Работа ведется через интерактивную консоль, в которой предусмотрена подсветка синтаксиса и автодополнение».
Чтобы найти нужный процесс используем следующую команду:
ps –e | grep “Photo”
Затем подцепляем cycript:
cycript –p PhotoVault
Рисунок 3: Подцепляем cycript к процессу приложения Photo Vault
Далее выводим иерархию представлений при помощи следующей команды:
[[UIApp keyWindow] recursiveDescription]
Рисунок 4: Иерархия представлений
По иерархии представлений находим несколько упоминаний PasswordBox. Попробуем поиграться с видимость этого элемента при помощи следующей команды:
В качестве адреса используем 0x15f687f0.
Рисунок 5: Сокрытие первого поля ввода пароля
После выполнения команды видим, что первый PasswordBox исчез:
Рисунок 6: Экран блокировки с исчезнувшим элементом PasswordBox
Далее мы будем использовать команду nextResponder для того, чтобы найти контроллер текущего представления. Ссылки на подробную документацию об этой команде и о MVC-модели указаны в разделе Ссылки.
Суть идеи заключается в том, что мы вызываем команду nextResponder до тех пор, пока не доберемся до контроллера. Начинаем с команды [#0x15f687f0 nextResponder], которая возвращает <UIView: 0x15f68790>. Далее вызываем команду [#0x15f68790 nextResponder] и добираемся до контроллера, как показано на рисунке ниже:
Рисунок 7: Поиск контроллера текущего представления
В итоге мы нашли контроллер WhiteLockScreenViewController, соответствующий представлению экрана блокировки. Ранее я выгрузил информацию о классах при помощи утилиты class-dump-z и нашел интересный метод dismissLockScreen.
Неужели все настолько просто? Оказалось, что да. Мы можем просто вызвать этот метод и обойти экран блокировки:
Рисунок 8: Обход экрана блокировки при помощи метода dismissLockScreen
Незащищенное хранилище
Далее я решил проверить, где находится пароль от хранилища. Свои фотографии я «защитил» при помощи пароля 1337. Оказалось, что пароль хранится в открытом виде в файле com.enchantedcloud.photovault.plist, который находится в директории /var/mobile/Applications/A025EF5F-ED84-4D82-A23D-BBCFE183F539/Library/Preferences.
Попутно мне стало интересно, на что повлияет изменение параметра Request Pin (см. ниже).
Рисунок 9: Пароль хранится в открытом виде
Не только PIN хранится в открытом виде. У пользователя есть возможность установить пароль на отдельные альбомы. И снова пароль хранится как обычный текст в файле Albums.plist:
Рисунок 10: Содержимое файла Albums.plist
Отсутствие шифрования
Пароли в открытом виде, это еще полбеды. Оказалось, что и сами картинки хранятся в незашифрованном виде в директории /0:
Рисунок 11: Директория, где хранятся незашифрованные фотографии
Рисунок 12: Содержимое незашифрованной фотографии
Реверс-инжиниринг приложения Private Photo Vault
На данный момент мы научились обходить экран блокировки при помощи cycript. Давайте попробуем сделать то же самое при помощи других методов.
Настройка рабочей среды
Подключите мобильное устройство к вашей системе и запустите скрипт tcprelay (из директории usbmuxd) при помощи следующей команды:
tcprelay.py -t <remote-port-to-forward><local-port-to-listen>
Рисунок 13: Запуск скрипта tcprelay
Tcprelay позволяет нам отлаживать приложение через USB. Можно было бы то же самое делать через Wi-Fi, но этот протокол часто замедляет весь процесс.
Подключаемся к устройству через SSH, запускаем debugserver и цепляемся к процессу при помощи следующей команды:
debugserver *:8080 –a “PhotoVault”
Рисунок 14: Запуск debugserver на мобильном устройстве
Далее в нашей системе запускаем lldb и подключаемся к серверу отладки на мобильном устройстве. Запускаем следующую команду из lldb:
process connect connect://localhost:8080
Рисунок 15: Подключаемся к debugserver через lldb
Дешифровка бинарного файла
После всех настроек можно приступать к отладке. Но вначале расшифруем бинарный файл при помощи следующей команды:
DYLD_INSERT_LIBRARIES=dumpdecrypted_armv7.dylib /var/mobile/Applications/A025EF5F-ED84-4D82-A23D-BBCFE183F539/PhotoVault.app/PhotoVault mach -o decryption dumper
Рисунок 16: Дешифровка бинарного файла приложения PhotoVault
Обычно я проверяю, какие еще архитектуры поддерживает бинарный файл, при помощи следующей команды:
otool –hV PhotoVault.decrypted
Рисунок 17: Проверка на то, является ли бинарный файл мультиархитектурным
Если файл поддерживает несколько архитектур, я оставляю только ту, с которой я работаю в данный момент. Допустим, файл запускается на устройстве iPhone 4S. Тогда используем следующую команду:
lipo -thin armv7 -output PhotoVault-v7 PhotoVault.decrypted
В итоге получаем файл PhotoVault-v7, который далее будем анализировать в IDA или Hopper (инструкции по настройке lldb и debugserver находятся в разделе Ссылки).
Ранее мы выяснили, что контроллер WhiteLockScreenViewController управляет экраном блокировки. Если мы введем некорректный пароль, появится сообщение «Wrong Passcode – Try Again» Наша первая задача – выяснить при помощи IDA, какие задействуются участки кода, когда мы вводим неправильный пароль.
Рисунок 18: Поиск участков кода, связанных с неверным вводом пароля
Мы нашли несколько соответствий, но особый интерес для нас представляет контроллер WhiteLockScreenViewController. После небольших исследований, выясняется следующее:
Рисунок 19: Содержимое функции customKeyboardButtonPressed, принадлежащей контроллеру WhiteLockScreenViewController
По адресу 0013A102 вызывается метод lockScreen:isPasswordCorrect. По адресу 0013A114 происходит проверка возвращаемого значения. По адресу 0013A118 принимается решение, куда двигаться дальше. Если мы ввели некорректный пароль, приложение переходит к ветке loc_13A146 и выводит сообщение «Wrong Passcode», как показано на рисунке ниже.
Рисунок 20: Ветка, связанная с выводом сообщения о неверном пароле
Наша задача – сделать так, чтобы в приложении выполнялась ветка 0013A11A, и вызвался метод selRef_lockScreen_didEnterCorrectPassword_ .
Рисунок 21: Интересующая нас ветка
Устанавливаем точку останова по адресу 0013A110 перед тем, как происходит проверка возвращаемого значения. Но вначале нужно учесть, что приложение защищено ASLR, и нам нужно найти смещение для нашего устройства.
Рисунок 22: Точка останова будет установлена по адресу 0013A110
Чтобы решить эту проблему, используем следующую команду (внутри сессии lldb):
Рисунок 23: Поиск смещения
Приложение загружено по адресу 0xef000, и точка останова будет установлена по адресу 0x229110 (0x000ef000 + 0013A110) при помощи следующей команды:
br s -a 0x229110
Все последующие точки останова также будут вычисляться как сумма двух смещений (ASLR и IDA).
Рисунок 24: Установка точки останова
Далее вводим произвольный пароль, и срабатывает точка останова. Смотрим содержимое регистра r8:
Рисунок 25: Содержимое регистра r8
Поскольку в регистре значение 0, далее инструкция TST.W R8, #0xFF переведет нас в ветку, где выводится сообщение «Wrong Passcode». Нам нужно изменить это значение, чтобы перейти в другую ветку. Используем следующую команду:
register write r8 1
Рисунок 26: В регистр r8 устанавливаем значение 1
Перед тем как продолжить, повнимательнее посмотрим на ту ветку, в которую мы хотим попасть. Там есть вызов функции lockScreen_didEnterCorrectPassword. Через поиск в IDA выясняем, что функция принадлежит классу PasswordManager.
Рисунок 27: Поиск ссылок на функцию lockScreen_didEnterCorrectPassword
Внутри функции lockScreen_didEnterCorrectPassword находим кое-что интересное:
Рисунок 28: Содержимое функции lockScreen_didEnterCorrectPassword
В коде на рисунке выше считывается PIN-код, хранящийся на устройстве, и полученное значение сравнивается с тем, что вводим мы (по адресу 0012D498). Естественно, проверка закончится неудачно, поскольку мы ввели неправильный PIN-код. Далее вызывается уже знакомая нам функция dismissLockScreen. Если не забыли, мы вызывали эту функцию ранее при помощи cycript.
Рисунок 29: Ветка, где вызывается функция dismissLockScreen
Чтобы оказаться в этой ветке нам нужно изменить значение в регистре r0 так, чтобы инструкция TST возвратила нужный результат, и система думала, что мы ввели корректный PIN-код. Устанавливаем точку останова по адресу 0012D49C, где сравнивается введенное значение. Напоминаю, что мы находимся внутри метода lockScreen_didEnterCorrectPassword, принадлежащего классу PasswordManager.
Рисунок 30: Место, где происходит сравнение введенного PIN-кода
Чтобы проверка PIN-кода оказалась удачной, нужно установить в регистр r0 значение 1.
Рисунок 31: Обновляем регистр r0, чтобы вызвать функцию dismissLockScreen
После обновления регистра вызывается функция dismissLockScreen, экран блокировки исчезает, и мы получаем доступ к фотографиям.
Подводим итоги. Первый трюк позволяет нам вызывать функцию lockScreen_didEnterCorrectPassword, второй - функцию dismissLockScreen. Вызовы этих функций происходят вне зависимости от того, какой PIN-код мы ввели.
Теперь рассмотрим другие приложения.
Анализ приложения My Media
Незащищенный веб-сервер
Приложение My Media довольно популярно, однако содержит те же самые уязвимости, которые описаны выше. Особенность этого приложения заключается в том, что для управления пользовательскими альбомами используется веб-сервер, запущенный на 5555 порту.
Рисунок 32: Веб-сервер запущен на 5555 порту
Перейдя по адресу выше, оказывается в менеджере фотографий:
Рисунок 33: Менеджер фотографий
Первое, что я заметил – отсутствие аутентификации. Все, кто находится в той же подсети, потенциально могут получить доступ к пользовательским альбомам. Более глубокий анализ показал, что имеются уязвимости, наиболее распространенные в веб-приложениях. Например, через имя альбома можно выполнить межсайтовый скриптинг:
Рисунок 34: XSS-уязвимость в имени альбома
Незащищенное хранилище
Как и в предыдущем случае, фотографии не шифруются, что легко проверить в любом шестнадцатеричном редакторе. Фото и видео хранятся в следующей директории:
Рисунок 35: Незащищенное хранилище с фотографиями
На устройстве список альбомов и фотографии выглядят так:
Рисунок 36: Перечень альбомов и фотографий на устройстве
Еще одна из фишек подобных приложений – возможность установить специальный пароль, введя который пользователь попадает в фальшивый альбом. Фотографии, хранимые в фальшивом альбоме, также не зашифрованы. «Левые» фотографии хранятся в следующей директории:
Пользовательские данные хранятся в незашифрованном виде в базе sqlite. Мне без труда удалось получить перечень всех паролей, в том числе административных.
Рисунок 37: Содержимое таблицы с паролями
Анализ приложения KeepSafe
Обход экрана блокировки
Обход экрана блокировки в приложении KeepSafe также не представляет особых сложностей.
Рисунок 38: Экран блокировки
Экран блокировки можно обойти, если вызвать метод showMainStoryboard, принадлежащий классу KeepSafe.AppDelegate. Подключаемся к процессу приложения, но в этот раз смотрим список экземпляров методов.
Рисунок 39: Перечень экземпляров методов
Для обхода экрана блокировки достаточно вызвать либо метод showAccountStoryboard, либо метод showMainStoryboard, как показано на рисунке ниже:
Рисунок 40: Обход экрана блокировки
В приложении KeepSafe можно защитить паролем каждый альбом. Каждый альбом синхронизируется с облаком.
Рисунок 41: Облако в KeepSafe
Выяснилось, что пароль возвращается сервером в открытом виде, как показано на рисунке ниже:
Рисунок 42: Пароль от альбомов возвращается сервером в открытом виде
Помимо обхода экрана блокировки злоумышленник может получить пароль к каждому альбому.
Подведем краткие итоги того, чего нам удалось добиться. Мы использовали:
Cycript для обхода экранов блокировки.
Sqlite для извлечения конфиденциальной информации из баз данных.
Plutil для чтения конфиденциальной информации из plist-файлов.
BurpSuite Pro для перехвата трафика.
IDA Pro для анализа бинарных файлов и решения задач, схожих с теми, что мы решали при помощи cycript.
В среднем, чтобы получить доступ к фотографиям и пользовательским учетных данным, нам требовалось не более 30 минут. Единственное исключение – анализ бинарных файлов в IDA, но мы проводили этот анализ лишь с целью показать вам альтернативные методы работы. Злоумышленник может получить доступ к конфиденциальным фотографиям в течение нескольких минут.
Во всех случаях обход экрана блокировки не представлял особых сложностей. Основные проблемы в системе безопасности приложений:
Отсутствует детектирование джейлбрейкового устройства.
Хранилище с учетными данными не защищено.
Отсутствует шифрование фотографий.
Обход экрана блокировки не представляет никаких сложностей.
Присутствуют распространенные уязвимости в веб-приложениях.
Однако следует отметить, что не все приложения, предназначенные для защиты фотографий, настолько уязвимы. Я лишь взял наиболее популярные программы и провел быстрый анализ. С другой стороны, я бы не удивился, если в других приложения оказались бы те же самые проблемы, поскольку разработчики часто делают неверные предположения и думают, что у пользователей нет доступа к файловой системе.
Так в чем заключаются основные риски? Во-первых, если вы запускаете эти приложения на джейлбрейковом устройстве, то легко получите доступ к конфиденциальной информации. В случае с My Media даже если у вас нет джейлбрейкового устройства, но вы подключены к веб-серверу, то легко сможете получить доступ к фотографиям.
Еще более важным является то, что ваши данные не зашифрованы, и любое вредоносное приложение может получить доступ как к фотографиям, так и к учетным записям.
В следующий раз, когда вы захотите воспользоваться одним из приложений, описанных в этой заметке, имейте в виду, что функционал данных приложений может быть не тот, каким кажется на первый взгляд. Еще лучше, если вы не будете хранить конфиденциальные фото на мобильных устройствах.