Безопасность IOS-приложений (часть 12) – выгрузка данных из Keychain

Безопасность IOS-приложений (часть 12) – выгрузка данных из Keychain

В предыдущей статье мы рассмотрели различные способы анализа сетевого трафика и api-вызовов, которые совершаются IOS-приложением. В этой статье мы рассмотрим способы выгрузки информации из хранилища Keychain IOS-устройства.

Автор: Пратик Джианчандани (Prateek Gianchandani)

В предыдущей статье мы рассмотрели различные способы анализа сетевого трафика и api-вызовов, которые совершаются IOS-приложением. В этой статье мы рассмотрим способы выгрузки информации из хранилища Keychain IOS-устройства.

Основы Keychain

Согласно документации Apple, Keychain представляет собой безопасный контейнер для хранения конфиденциальной информации (имен пользователей, паролей, сетевых паролей, аутентификационных токенов различных приложений). Встроенные средства операционной системы Apple хранят в Keychain сетевые пароли для Wifi, учетные записи Vpn и т. д. Эти данные зашифрованы и хранятся в базе данных sqlite в файле /private/var/Keychains/keychain-2.db. Разработчики обычно используют эту возможность для хранения учетных записей, вместо использования NSUserDefaults, plist-файлов и т. д. Причиной тому может быть желание разработчика сохранить информацию об аутентификации, чтобы пользователю при повторном открытии приложения не приходилось каждый раз вводить учетные данные. Данные keychain для каждого приложения хранятся вне изолированной среды (песочницы).

Также возможно совместное использование между приложениями данных keychain через группы доступа (keychain access groups). Эта группа должна быть определена во время сохранения информации в keychain. Наилучший способ сохранения информации в keychain – использовать класс KeychainItemWrapper. На сайте разработчиков Apple можно найти тестовый проект. Для начала необходимо создать экземпляр класса.

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@”Password” accessGroup:nil];

Идентификатор поможет в будущем в получении информации из keychain. Если вы хотите совместно использовать информацию из keychain с другими приложениями, то необходимо определить группу доступа. Приложения с одной и той группой доступа могут получать доступ к одной и той же информации из keychain.

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@”Account Number”
accessGroup:@”YOUR_APP_ID_HERE.com.yourcompany.GenericKeychainSuite”];

Для сохранения информации в keychain используйте метод setObject:forKey:. В этом случае (id)kSecAttrAccount представляет собой предопределенный ключ, который мы можем использовать для объявления имени учетной записи, для которой мы храним информацию. Ключ kSecClass – определяет вид хранимой информации (в нашем случае это групповой пароль (generic password)). Ключ kSecValueData можно использовать для хранения любых данных (в нашем случае это пароль).

[keychainItemWrapper setObject:kSecClassGenericPassword forKey:(id)kSecClass];
[wrapper setObject:@"username" forKey:(id)kSecAttrAccount];
[keychainItemWrapper setObject:@"password"forKey:(id)kSecValueData];
[wrapper setObject:(id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(id)kSecAttrAccessible];

Переменная kSecAttrAccessible используется для регулирования доступа к данным keychain. Следует быть осторожным при использовании этой переменной. Как сказано в документации Apple, переменная kSecAttrAccessible может принимать шесть возможных значений. Ниже приводится выдержка из документации.

Константы

kSecAttrAccessibleAfterFirstUnlock

К информации из keychain нет доступа после перезагрузки устройства до тех пор, пока устройство не разблокировано пользователем. После первой разблокировки данные становятся доступными до следующей перезагрузки. Рекомендуется использовать эту константу для записей, к которым осуществляется доступ со стороны фоновых приложений. Записи с этим атрибутом мигрируют на новое устройство при использовании зашифрованных резервных копий.

Константу можно использовать, начиная с iOS 4.0 и выше.

Объявлено в SecItem.h.

kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly

К информации из keychain нет доступа после перезагрузки устройства до тех пор, пока устройство не разблокировано пользователем. После первой разблокировки данные становятся доступными до следующей перезагрузки. Рекомендуется использовать эту константу для записей, к которым осуществляется доступ со стороны фоновых приложений. Записи с этим атрибутом не мигрируют на новое устройство или при новой установке. Таким образом, после восстановления резервной копии этих данных не будет.

Константу можно использовать, начиная с iOS 4.0 и выше.

Объявлено в SecItem.h.

kSecAttrAccessibleAlways

Данные в keychain будут доступны всегда, даже если устройство заблокировано. Не рекомендуется использовать эту константу. Записи с этим атрибутом мигрируют на новое устройство при использовании зашифрованных резервных копий.

Константу можно использовать, начиная с iOS 4.0 и выше.

Объявлено в SecItem.h.

kSecAttrAccessibleAlwaysThisDeviceOnly

Данные в keychain будут доступны всегда, даже если устройство заблокировано. Не рекомендуется использовать эту константу. Записи с этим атрибутом не мигрируют на новое устройство или при новой установке. Таким образом, после восстановления резервной копии этих данных не будет.

Константу можно использовать, начиная с iOS 4.0 и выше.

Объявлено в SecItem.h.

kSecAttrAccessibleWhenUnlocked

Данные будут доступны только, когда устройство разблокировано пользователем. Рекомендуется использовать эту константу, когда необходимо разрешить доступ для приложений, работающих на переднем плане. Записи с этим атрибутом мигрируют на новое устройство при использовании зашифрованных резервных копий.

Константу можно использовать, начиная с iOS 4.0 и выше.

Объявлено в SecItem.h.

kSecAttrAccessibleWhenUnlockedThisDeviceOnly

Данные будут доступны только, когда устройство разблокировано пользователем. Рекомендуется использовать эту константу, когда необходимо разрешить доступ для приложений, работающих на переднем плане. Записи с этим атрибутом не мигрируют на новое устройство или при новой установке. Таким образом, после восстановления резервной копии этих данных не будет.

Константу можно использовать, начиная с iOS 4.0 и выше.

Объявлено в SecItem.h.

Конечно, никогда не следует использовать константу kSecAttrAccessibleAlways. Наиболее безопасно использовать константу kSecAttrAccessibleWhenUnlocked. Также обратите внимание на константы, которые оканчиваются на ThisDeviceOnly. В случае использования констант из этой группы, данные шифруются при помощи аппаратно зависимого ключа и, следовательно, не могут быть переданы или просмотрены на другом устройстве. Несмотря на то, что при использовании этих констант повышается уровень безопасности, их следует использовать лишь в тех случаях, если у вас на это есть веские причины, и вы хотите запретить перенос данных между устройствами.

Для получения информации из keychain используйте следующий код.

NSString *accountName = [wrapper objectForKey:(id)kSecAttrAccount];

Анализ взаимодействия приложения с keychain при помощи Snoop-it

Одной из наиболее полезных утилит, позволяющих анализировать данные, записываемые в keychain, является Snoop-it. Если вы еще не знакомы с этой утилитой, рекомендую вам ознакомиться с девятой статьей этой серии. Запустите проект GenericKeychain на вашем джейлбрейковом устройстве и проанализируйте его при помощи Snoop-it. В седьмой статье этой серии рассказывается о том, как запускать собственные приложения на джейлбрейковом устройстве и привязывать к ним самоподписанный сертификат. Наш проект – лишь пример, демонстрирующий, как читать и писать данные в Keychain при помощи класса-обертки KeychainWrapper для Obective-C. Удостоверьтесь в том, что приложение анализируется при помощи Snoop-it. Внешний вид приложения показан на рисунке ниже.

http://2we26u4fam7n16rz3a44uhbe1bq2.wpengine.netdna-cdn.com/wp-content/uploads/080513_1630_IOSApplicat2.png

Рисунок 1: Интерфейс тестового приложения

Введите какое-нибудь имя пользователя и пароль и сохраните их. Я ввел имя пользователя «Test User» и пароль «password». После этого вы увидите, что Snoop-it обнаружил изменения, вносимые в keychain, и может показать нам информацию, которую приложение сохраняет в keychain. Также мы можем увидеть защитные атрибуты сохраненной информации.

Click to Enlarge

Рисунок 2: Процесс чтения-записи информации в keychain

Ниже показана информация, раскрывающая имя пользователя и пароль.

http://2we26u4fam7n16rz3a44uhbe1bq2.wpengine.netdna-cdn.com/wp-content/uploads/080513_1630_IOSApplicat4.png

Рисунок 3: Информация, раскрывающая имя пользователя и пароль

Теперь введите номер учетной записи. Как видно из рисунка ниже, Snoop-it и здесь в состоянии обнаружить работу с keychain.

Click to Enlarge

Рисунок 4: Следы работы с keychain при изменении параметра учетной записи

Как вы могли убедиться, Snoop-it может детектировать взаимодействие с базой данных keychain, будь то чтение, запись или удаление данных. Если вы удалите записи из keychain, нажав Reset, Snoop-it также отразит эти действия.

Click to Enlarge

Рисунок 5: Следы работы по удалению записей из keychain

Выгрузка информации из Keychain при помощи Keychain Dumper

Keychain dumper – одна из наиболее распространенных утилит, используемых для выгрузки информации из keychain. Страница в github для этого проекта доступа по ссылке https://github.com/ptoomey3/Keychain-Dumper. Зайдите по этому адресу, загрузите и распакуйте zip-файл. В распакованной папке единственный файл, который нас интересует, - бинарный файл keychain_dumper. Информация в keychain, к которой позволен доступ со стороны приложения, определяется в entitlements. Наш бинарный файл подписан самоподписанным сертификатом с файлом entitlements.xml, что позволяет получить доступ ко всем записям в keychain. Также существуют и другие способы проверки доступности всех записей в keychain. Например, если есть в наличии файл с entitlements, содержащий все группы доступа keychain или одну группу, которая позволяет получить доступ ко всем данным в keychain. К примеру, утилита Keychain-viewer используется следующие entitlements.

com.apple.keystore.access-keychain-keys
com.apple.keystore.device

Загрузите бинарный файл на ваше устройство в папку /tmp и установите права на запуск.

Рисунок 6: Загрузка и установление прав на запуск для файла keychain_dumper

Убедитесь в том, что файл /private/var/Keychains/keychain-2.db может прочитать кто угодно (то есть, у файла установлен атрибут world readable).

http://2we26u4fam7n16rz3a44uhbe1bq2.wpengine.netdna-cdn.com/wp-content/uploads/080513_1630_IOSApplicat8.png

Рисунок 7: Установка прав на чтение у файла /private/var/Keychains/keychain-2.db

Теперь запустите бинарный файл.

Click to Enlarge

Click to Enlarge

Рисунок 8: Информация, выгруженная из keychain при помощи Keychain Dumper

Как видно из рисунка выше, выгрузилась вся информация (множество имен пользователей и паролей). Например, видно, что приложение Mail хранит имя пользователя и пароль вашей учетной записи в keychain. Схожим образом, возможно нахождение паролей некоторых беспроводных сетей, к которым вы ранее подсоединялись, а также много другой информации. По умолчанию происходит выгрузка только групповых паролей и паролей для интернета. Более подробную информацию об использовании можно получить, если использовать параметр «-h»

Click to Enlarge

Рисунок 9: Информация о ключах, которые можно использовать при запуске Key Dumper

Для выгрузки всей информации используйте ключ «-a».

http://2we26u4fam7n16rz3a44uhbe1bq2.wpengine.netdna-cdn.com/wp-content/uploads/080513_1630_IOSApplicat12.png

Рисунок 10: Выгрузка всей информации из keychain

Один из способов, повышающий уровень безопасности при хранении информации в keychain, - использование более устойчивого кода-пароля (passcode), поскольку код-пароль используется для шифрования данных в keychain для определенных защитных атрибутов и, таким образом, его длина напрямую коррелирует с уровнем безопасности. По умолчанию IOS позволяет задавать код-пароль из 4 цифр. Такой пароль может быть подобран в течение нескольких минут. В следующих статьях мы рассмотрим подбор паролей методом брутфорс. Однако вы можете установить настройку, которая позволяет задавать буквенно-цифровые пароли. Подводя итог, следует отметить, что использование правильного защитного атрибута в комбинации со стойким паролем, поможет значительно повысить уровень безопасности и затруднить работу злоумышленникам.

Заключение

В этой статье мы убедились в том, что выгрузить данные из Keychain проще простого. Даже несмотря на то, что keychain намного лучше защищает конфиденциальные данные, чем NSUserDefaults или plist-файлы, осуществить взлом этого хранилища не так сложно.

Ссылки

· Keychain-Dumper
https://github.com/ptoomey3/Keychain-Dumper

Домашний Wi-Fi – ваша крепость или картонный домик?

Узнайте, как построить неприступную стену