Skip to content

Latest commit

 

History

History
989 lines (671 loc) · 102 KB

0x06d-Testing-Data-Storage.md

File metadata and controls

989 lines (671 loc) · 102 KB

Хранилища данных в iOS

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

Тестирование локального хранилища данных

Хранение чувствительной информации в локальном хранилище необходимо избегать. Однако на практике, по крайней мере некоторая информация о пользователе должна быть сохранена. К счастью, iOS предлагает безопасные API для хранения данных, которые позволяют разработчикам использовать аппартаные криптографические возможности на каждом устройстве iOS. Если предположить, что данные API используются правильно, важная информация(ключи, файлы) может быть защищена аппаратными средствами, используя 256-битное шифрование алгоритмом AES.

API защиты данных

Разработчики приложений могут задействовать API защиты данных(Data Protection) в iOS для реализации контроля доступа к данным пользователя, хранящимся в оперативной памяти. API построены на базе SEP(Secure Enclave Processor), который был впервый представлен в iPhone 5S. SEP – это сопроцессор, который отвечает за криптографические операции для защиты данных и управления ключами. Аппаратный ключ, уникальный для каждого устройства, – идентификатор устройства UID(Unique ID) – интегрирован в SEP, обеспечивая целостность защиты данных, даже если ядро операционной системы скомпрометировано.

Архитектура защиты данных основывается на иерархии ключей. UID и ключ пользовательского пароля(passcode key), которые были получены из пользовательского кода доступа(passphrase), используя алгоритм PBKDF2, находятся на верхушке этой иерархии. Вместе они могут "разблокировать", так называемые, ключи классов, которые связаны с различными состояниями приложения (устройство разблокировано/заблокировано).

Каждый файл, хранящийся на iOS, зашифрован с использованием индивидуального ключа, уникального для каждого файла, который хранится в метаданных файла. Метаданные зашифрованы с использованием ключа файловой системы и обработаны одним из ключей класса, в зависимости от выбора класса защиты, указанного при создании файла.

Иерархия ключей в iOS

Иерархия ключей защиты данных в iOS

Файлам может быть присвоен один из четырех классов защиты, про которые можно почитать подробнее в iOS Security Guide:

  • Полная защита (NSFileProtectionComplete): Ключ, полученный из пользовательского кода доступа и UID устройства, используется для обеспечения безопасности данного класса. Он удаляется из памяти почти сразу после блокировки устройства, создавая тем самым невозможность получения данных до моменты разблокировки устройства.

  • Защищено до открытия (NSFileProtectionCompleteUnlessOpen): Похожее поведение с вышестоящим классом, но если файл открыт, когда он "разблокирован", приложение может продолжить его использование даже в том случае, если пользователь заблокирует устройство. Этот класс защиты используется, например, во время скачивания вложения(в письме) в фоновом режиме.

  • Защищено до момента первой аутентификации пользователя (NSFileProtectionCompleteUntilFirstUserAuthentication): Файл может быть доступен с момента первой разблокировки устройства, после перезапуска. Файл может быть доступен, даже если пользователь постоянно блокирует устройство; ключ класса не будет удален из памяти.

  • Нет защиты (NSFileProtectionNone): Ключ данного класса безопасности защищен только с использованием UID. Он хранится в так называемом "Effaceable Storage", которое является участком в оперативаной памяти устройства, предназначенное для хранения небольших объемов данных. Данный класс безопасности существует для быстрой удаленной очистки устройства(remote wipe): удаление ключа класса сразу же делает данные недоступными.

Все ключи класса, за исключением NSFileProtectionNone, зашифрованы ключом, полученным из UID устройства и кода доступа ползователя. Как результат, дешифрование может случиться только на самом устройстве и только при условии, что правильный код-пароль был введен.

Начиная с iOS 7, стандарный класс защиты - это "Protected Until First User Authentication".

Keychain

iOS Keychain может быть использован для хранения коротких, чувствительных последовательностей данных, таких как ключи шифрования и токены сессии. Он реализован как база данных SQLite, с доступом через Keychain API.

На OS X каждое приложение может создавать сколько угодно Keychains и каждый аккаунт имеет свой собственный Keychain. Структура Keychain на iOS отличается, так как существует только один Keychain для всех приложений. Доступ к его элементам может быть использован совместно для приложений, разработанных одним разработчиком, используя access groups feature в атрибуте kSecAttrAccessGroup. Доступ к Keychain управляется демоном securityd, который предоставляет доступ, основываясь на Keychain-access-groups, application-identifier приложения и разрешениях(entitlements) application-group.

Keyсhain API состоит из следующих основных операций:

  • SecItemAdd
  • SecItemUpdate
  • SecItemCopyMatching
  • SecItemDelete

Данные, хранящиеся в Keychain, защищены с помощью похожей на файловое шифрование структурой классов. Элементы, добавляемые в Keychain, кодируются в бинарные plist файлы и шифруются, используя 128-битный AES ключ, уникальный для каждого элемента, в режиме GCM(Galois/Counter Mode). Обратите внимание, что большие куски данных не предназначены для прямого хранения в Keychain - для этого и были придуманы API защиты данных. Защита данных для элементов Keychain настраивается с помощью установки ключа kSecAttrAccessible в вызовах SecItemAdd или SecItemUpdate. Следующие значения доступности для kSecAttrAccessible могут быть настроены и являются классами защиты Keychain:

  • kSecAttrAccessibleAfterFirstUnlock: К данным элемента Keychain не может быть осуществлен доступ, до момента первой разблокировки устройства пользователем.
  • kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: Не может быть осуществлен доступ к элементу Keychain после рестарта и до момента разблокировки устройства пользователем.
  • kSecAttrAccessibleAlways: Данные доступны всегда, не зависимо от того заблокировано ли устройство.
  • kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: К элементам Keychain может быть осуществлен доступ только когда устройство разблокировано. Работает только если установлен код-пароль. Данные не включаются в бекап iTunes или iCloud.
  • kSecAttrAccessibleAlwaysThisDeviceOnly: Данные в Keychain доступны всегда, независимо от блокировки устройства. Данные не включаются в бекап iTunes или iCloud.
  • kSecAttrAccessibleWhenUnlocked: Доступ к элементам Keychain разрешен, когда устройство разблокировано пользователем.
  • kSecAttrAccessibleWhenUnlockedThisDeviceOnly: Доступ к элементам Keychain разрешен, когда устройство разблокировано пользователем. Данные не включаются в бекап iTunes или iCloud.

AccessControlFlags - определяют механизм, которым может воспользоваться пользователь для аутентификации разблокироваки ключа(SecAccessControlCreateFlags):

  • kSecAccessControlDevicePasscode: доступ по код-паролю.
  • kSecAccessControlTouchIDAny : доступ к элементу осуществляется с использованием отпечатков пальцев, зарегистрированных в Touch ID. Добавление или удаление отпечатка пальца не аннулирует элемент Keychain.
  • kSecAccessControlTouchIDCurrentSet: доступ к элементу осуществляется с использованием отпечатков пальцев, зарегистрированных в Touch ID. Добавление или удаление отпечатка пальца аннулирует элемент Keychain.
  • kSecAccessControlUserPresence: доступ к элементу осуществляется с использованием отпечатков пальцев, зарегистрированных в Touch ID или же ввод код-пароля.

Обратите внимание, что ключи, которым обеспечивается безопасность с использованием Touch ID(kSecAccessControlTouchIDCurrentSet или kSecAccessControlTouchIDAny), также защищены Secure Enclave: Keychain хранит только токен, но не сам ключ. Ключ хранится в Secure Enclave.

Начиная с iOS 9, вы можете осуществлять операции подписи, основанные на ECC, в Secure Enclave. В таком случае закрытый ключ, ровно как и операции шифрования, находятся в Secure Enclave. Прочитайте раздел статический анализ для получения подробной информации о создании ECC ключей.

iOS 9 поддерживает только 256-битный ECC. Более того, вам необходимо хранить открытый ключ в Keychain, так как он не может быть сохранен в Secure Enclave. Вы можете использовать kSecAttrKeyType, чтобы просигнализировать с каким типом алгоритма вы хотите использовать ключ, до его создания.

Устойчивость(сохранность) данных Keychain

Когда приложение удаляется в iOS, данные Keychain, использованные во время функционирования приложения, сохраняются на устройстве, в отличии от данных в песочнице приложения, которые удаляются. В случае если пользователь продает свое устройство без отката к заводским настройкам(без вайпа), человек, купивший устройство может получить доступ к аккаунтам и данным предыдушего владельца, если переустановит те приложения, что удалил предыдуший хозяин. Для этого не потребуется никаких технических навыков.

Во время проверки приложения, обязательно нужно проверить сохранность(устойчивость) данных Keychain, обычно для этого в приложение сохраняют данные, которые могут быть записаны в Keychain, после чего переустанавливают приложение и проверяют сохранились ли данные. Это можно проверить с помощью библиотеки проверки безопасности - Needle, чтобы прочитать данные Keychain таким образом как это продемонстрировано ниже:

python needle.py
[needle] > use storage/data/Keychain_dump
[needle] > run
  {
   "Creation Time" : "Jan 15, 2018, 10:20:02 GMT",
   "Account" : "username",
   "Service" : "",
   "Access Group" : "ABCD.com.test.passwordmngr-test",
   "Protection" : "kSecAttrAccessibleWhenUnlocked",
   "Modification Time" : "Jan 15, 2018, 10:28:02 GMT",
   "Data" : "testUser",
   "AccessControl" : "Not Applicable"
 },
 {
   "Creation Time" : "Jan 15, 2018, 10:20:02 GMT",
   "Account" : "password",
   "Service" : "",
   "Access Group" : "ABCD.com.test.passwordmngr-test,
   "Protection" : "kSecAttrAccessibleWhenUnlocked",
   "Modification Time" : "Jan 15, 2018, 10:28:02 GMT",
   "Data" : "rosebud",
   "AccessControl" : "Not Applicable"
 }

Не существует iOS API, которые может использовать разработчик, чтобы принудительно стереть все данные приложения после его удаления с устройства. Вместо этого рекомендуется воспользоваться следующими шагами, чтобы защититься от сохранения данных в Keychain, между переустановками приложения:

  • Во время первого запуска после установки, рекомендуется стирать все данные в Keychain, ассоциированные с данным приложением. Это не даст второму владельцу устройства случайно получить доступ к аккаунту первого владельца. Базовый пример такой реализации на Swift можно посмотреть ниже:
let userDefaults = UserDefaults.standard

if userDefaults.bool(forKey: "hasRunBefore") == false {
     // Remove Keychain items here

     // Update the flag indicator
     userDefaults.set(true, forKey: "hasRunBefore")
     userDefaults.synchronize() // Forces the app to update UserDefaults
}
  • Во время разработки функции выхода из приложения - убедитесь, что при ее использовании все данные из Keychain также удаляются. Это сделает возможным удаление информации о своем аккаунте до удаления приложения.

Статический анализ

Когда у вас есть доступ к исходному коду, попробуйте найти чувствительные данные, которые передаются в приложении. Сюда входят общие пароли, секретные ключи и персональная идентификационная информация(PII), но также может быть и другая информация, классифицирующаяся как чувствительная из-за регуляторов индустрии, законов или же политики компании. Посмотрите где хранится информация, сохраненная используя любой из API для локального хранения данных, перечисленные ниже. Убедитесь, что чувствительная информация никогда не хранится без использования защиты. Например, токены аутентификации никогда не должны хранится в NSUserDefaults без использования дополнительного шифрования.

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

Общие примеры хранения, обновления или удаления элементов Keychain можете найти в официальной документации Apple, также там можно найти пример использования TouchID and passcode protected keys.

Вот пример на Swift, где создают ключи (обратите внимание kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave: здесь вы задаете инструкцию, что хотите использовать Secure Enclave напрямую):

 // private key parameters
    let privateKeyParams: [String: AnyObject] = [
        kSecAttrLabel as String: "privateLabel",
        kSecAttrIsPermanent as String: true,
        kSecAttrApplicationTag as String: "applicationTag"
    ]        
    // public key parameters
    let publicKeyParams: [String: AnyObject] = [
        kSecAttrLabel as String: "publicLabel",
        kSecAttrIsPermanent as String: false,
        kSecAttrApplicationTag as String: "applicationTag"
    ]

    // global parameters
    let parameters: [String: AnyObject] = [
        kSecAttrKeyType as String: kSecAttrKeyTypeEC,
        kSecAttrKeySizeInBits as String: 256,
        kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
        kSecPublicKeyAttrs as String: publicKeyParams,
        kSecPrivateKeyAttrs as String: privateKeyParams
    ]        

    var pubKey, privKey: SecKeyRef?
    let status = SecKeyGeneratePair(parameters, &pubKey, &privKey)

Когда ищите места небезопасного хранения данных в iOS, вам стоит рассмотреть следующие возможные варианты, так как все они не используют шифрование совсем, по умолчанию.

NSUserDefaults

Класс NSUserDefaults предоставляет программный интерфейс для взаимодействия со стандартной системой(Default system). Стандартная система позволяет приложению настраивать свое поведение, чтобы соответствовать предпочтениям пользователя. Данные, сохраненные в этом хранилище можно посмотреть в пакете приложения. NSUserDefaults также хранит данные в виде .plist файла, но предназначен для хранения меньших объемов данных.

Файловая система
  • NSData - создает статические(неизменяемые) объекты данных, а NSMutableData- изменяемые(динамические) объекты данных. Они обычно используются для хранения данных и еще очень полезны для приложений с распределенными объектами, где данные, хранищиеся в объектах данных могут быть скопированы или перемещены между приложениями. Методы для записи объектов NSData:

    • NSDataWritingWithoutOverwriting
    • NSDataWritingFileProtectionNone
    • NSDataWritingFileProtectionComplete
    • NSDataWritingFileProtectionCompleteUnlessOpen
    • NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
  • writeToFile - сохраняет данные как часть класса NSData

  • NSSearchPathForDirectoriesInDomains, NSTemporaryDirectory - используется для управления путей файлов.

  • NSFileManager - позволяет посмотреть содержимое файловой системы и совершить изменения. Для создания и записи файла можно использовать createFileAtPath.

Пример ниже показывает как создать безопасно зашифрованный файл, используя метод createFileAtPath:

[[NSFileManager defaultManager] createFileAtPath:[self filePath]
  contents:[@"secret text" dataUsingEncoding:NSUTF8StringEncoding]
  attributes:[NSDictionary dictionaryWithObject:NSFileProtectionComplete
  forKey:NSFileProtectionKey]];
CoreData

Core Data - это библиотека для управления уровнем моделей объектов в вашем приложении. Она предоставляет обобщенные и автоматизированные решения для обычных задач, связанных с жизненным циклом объекта и управлением объектным графом(object graph management), включая уcтойчивость(persistance). Core Data может использовать SQLite как свое хранилище, но библиотека сама по себе не является базой данных.

База данных SQLite

Необходимо добавить библиотеку SQLite3 в приложение, чтобы использовать SQLite. Она представляет собой обертку C++, которая предоставляет API для команд SQLite.

База данных Realm

Realm Objective-C и Realm Swift не поставляются Apple, но нуждаются в упоминании здесь. Данная БД ничего не шифрует, если не была включена настройка шифрования.

Данный пример демонстрирует как использовать шифрование в БД Realm.

// Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server
let config = Realm.Configuration(encryptionKey: getKey())
do {
  let realm = try Realm(configuration: config)
  // Use the Realm as normal
} catch let error as NSError {
  // If the encryption key is wrong, `error` will say that it's an invalid database
  fatalError("Error opening realm: \(error)")
}
База данных Couchbase Lite

Couchbase Lite - это встроенный, легковесный, документо- ориентированный(NoSQL), синхронизирующийся движок БД. Нативно компилируется на iOS и Mac OS.

Yap БД

YapDatabase - это хранилище ключ-значение, построенный поверх SQLite.

Динамический анализ

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

Следующие шаги могут быть выполнены на устройстве с jailbreak для определения как приложение хранит локальные данные на устройстве iOS.

  1. Вызовите функциональность, которая сохраняет потенциально чувствительную информацию.
  2. Подключитесь к устройству и перейдите в следующую директорию(это применимо к версии iOS 8.0 и выше): /var/mobile/Containers/Data/Application/$APP_ID/
  3. Выполните команду grep с данными, которые вы сохраняли, например: grep -iRn "USERID".
  4. Если данные сохранены как обычный текст, значит тест провален.

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

  1. Вызовите функциональность, которая сохраняет потенциально чувствительную информацию.
  2. Подключите устройство к вашему компьютеру и запустите iMazing.
  3. Выберите "Apps" и нажмите правой кнопкой на необходимое приложение, нажмите "Extract App".
  4. Переместитесь в папку с выходными файлами, найдите $APP_NAME.imazingapp. Переименуйте в $APP_NAME.zip.
  5. Распакуйте переименованный архив .zip, теперь можно приступать к анализу.

Обратите внимание, что инструменты, как iMazing, не копируют данные с устройства напрямую, но пытаются извлечить их из создаваемой резервной копии. Более того невозможно извлечь все данные из бекапа, так как не все папки приложения включаются в него. В идеале, следует использовать взломанное устройство или же переупаковать приложение, воспользовавшись Frida, после чего использовать objection для доступа ко всем данным и файлам в приложении.

Если вы переупаковали приложение, включив туда библиотеку Frida, как написано в разделе "Динамический анализ на не джейлбрейк устройствах" в главе "Базовое тестирование безопасности", можете использовать objection для прямого копирования данных из соответсвующей папки приложения или же read data directly in objection.

Важные местоположения:

  • AppName.app
    • Пакет приложения, содержит само приложение и его ресурсы
    • Видимая для пользователей, но без права записи
    • Содержимое данной директории не бекапится
  • Documents/
    • Используйте папку для данных, сгенерированных пользователем
    • Видна пользователям и они могут осуществлять запись
    • Данные папки бекапятся
    • Приложение может отключить пути(disable paths), выставив NSURLIsExcludedFromBackupKey
  • Library/
    • Директория верхнего уровня для любых файлов, которые не являются данными пользователя
    • Обычно приложения используют поддиректории Application Support и Caches, но вы можете создать и свои
  • Library/Caches/
    • Полупостоянные кэши файлов
    • Невидима для пользователей и они не могут сюда писать
    • Содержимое не бекапится
    • Система может удалить файлы автоматически, если приложение не запущено(например, не хватает места)
  • Library/Application Support/
    • Постоянные файлы, необходимые для работы приложения
    • Невидима для пользователей и они не могут сюда писать
    • Данные папки бекапятся
    • Приложение может отключить пути(disable paths), выстави NSURLIsExcludedFromBackupKey
  • Library/Preferences/
    • Используется для хранения свойств, объектов, которые могут сохранятся после перезапуска приложения
    • Информация сохраняется в незашифрованной форме внутри песочницы приложения в .plist файле c именем [BUNDLE_ID].plist.
    • Все пары ключ-значение, сохраненные в NSUserDefaults, можно найти тут.
  • tmp/
    • Используйте данную категорию для записи временных файлов, которые не надо сохранят между запусками приложения.
    • Непостоянные кэш-файлы
    • Невидима для пользователя
    • Содержимое не бекапится
    • Система может удалить файлы автоматически, если приложение не запущено(например, не хватает места).

При необходимости во время динамического анализа содержимое Keychain может быть скопировано. На джейлбрейк устройствах Keychain dumper может быть задействован как описано в главе "Базовое тестирование безопасноти в iOS".

Файлы Keychain находятся в:

/private/var/Keychains/Keychain-2.db

На обычных устройствах можно воспользоваться дампом записей Keychain, созданных и сохраняемых приложением.

Динамический анализ, используя Xcode и симулятор iOS

Данная проверка доступна только на OS X, так как требуется Xcode и симулятор iOS.

Для проверки(тестирования) локального хранилища и данных внутри него необязательно требуется реальное устройство. Имея доступ к исходному коду и Xcode, приложение может быть собрано и установлено на симулятор iOS. Файловая система текущего симулятора iOS может быть найдена в директории ~/Library/Developer/CoreSimulator/Devices.

Как только приложение запустилось, вы можете перейти в папку, используя команду:

$ cd ~/Library/Developer/CoreSimulator/Devices/$(
ls -alht ~/Library/Developer/CoreSimulator/Devices | head -n 2 |
awk '{print $9}' | sed -n '1!p')/data/Containers/Data/Application

Команда автоматически найдет UUID устройства, запушенного в последний раз. Теперь вам все равно необходимо найти/захватить(grep) имя вашего приложения или ключевое слово в нем. Данная команда покажет UUID приложения.

$ grep -iRn keyword .

После этого вы можете следить и проверять изменения в файловой системе приложение и узнать хранится ли чувствительная информация среди файлов, во время использования приложения.

Динамический анализ, используя needle

На джейлбрек устройствах можно использовать библиотеку Needle для нахождения уязвимостей хранения данных.

Чтение Keychain

Для чтения Keychain, используя Needle:

[needle] > use storage/data/Keychain_dump
[needle][Keychain_dump] > run

Поиск бинарных кукиc(cookies)

Приложения iOS часто хранят бинарные файлы кукис в песочнице приложения. В таких бинарных файлах обычно хранятся куки информация webView приложения. Можно использовать Needle для конвертации файлов в читаемый формат. Для поиска таких файлов в контейнере приложения, просмотра их атрибутов защиты данных и непосредственной их загрузки или просмотра используйте модуль Needle:

[needle] > use storage/data/files_binarycookies
[needle][files_binarycookies] > run

Поиск файлов .plist

Приложения обычно хранят данный в формате .plist(Property list) файла как внутри песочницы так и внутри IPA файла. Иногда в этих файлах хранится чувствительная информация(пароли, логины), следовательно данные файлы должны быть изучены во время проверки приложения.

Для поиска таких файлов в контейнере приложения, просмотра их атрибутов защиты данных и непосредственной их загрузки или просмотра воспользуйтесь модулем Needle:

[needle] > use storage/data/files_plist
[needle][files_plist] > run

Поиск кэширующих баз данных

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

[needle] > use storage/data/files_cachedb
[needle][files_cachedb] > run

Поиск SQLite БД

Приложения часто используют SQLite базы данных для хранения данных. Тестировщикам следует проверять значения защиты данных этих файлов также как их содержимое для обнаружения хранения чувствительной информации. Для поиска таких БД файлов в контейнере приложения, просмотра их атрибутов защиты данных и непосредственной их загрузки или просмотра воспользуйтесь модулем Needle:

[needle] > use storage/data/files_sql
[needle][files_sql] >

Проверка логов на наличие чувствительной информации

Существуют многие причины создания лог файлов на мобильном устройстве, например, для статистики использования или ведения истории крашей или ошибок, которые сначала сохраняются локально, когда у устройства нет сети, а потом отправляются на сервер при первом же ее появлении. Однако, логирование чувствительной информации(номера кредитных карт, информации о сессии) может раскрыть эту информацию для злоумышленника или же вредоносного приложения. Лог-файлы могут быть созданы разными способами. Список ниже показывает достпуные на iOS механизмы:

  • метод NSLog
  • функции как printf
  • функции как NSAssert
  • Macro

Статический анализ

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

  • Для предопределнных/встроенных функций:

    • NSLog
    • NSAssert
    • NSCAssert
    • fprintf
  • Для пользовательских функций:

    • Logging
    • Logfile

В целом для решения этой проблемы вы можете использоваять define для включения NSLog в целях разработки и отладки и выключать его перед распространением приложения. Это может быть сделано вставив следующий код в необходимый файл PREFIX_HEADER (*.pch) file:

#ifdef DEBUG
#   define NSLog (...) NSLog(__VA_ARGS__)
#else
#   define NSLog (...)
#endif

Динамический анализ

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

  • Подключитесь к устройству и выполните команду:

    tail -f /var/log/syslog
  • Подсоедините свое устройство через USB и запустите Xcode. Перейдите в Windows > Devices, выберете ваше устройство и соответствующее приложение.

Заполните все всплывающие поля ввода и если после выполнения команды сверху отображается чувствительная информация - значит тест провален.

Лог файлы также могут быть изучены, используя Needle, для захвата логов приложения iOS используйте команду:

[needle] > use dynamic/monitor/syslog
[needle][syslog] > run

Определение отправки чувствительной информации в сторонние организации

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

Минус заключается в том, что разработчик детально не знает какой код используется сторонней библиотекой. Следовательно необходимо убедиться в том, что больше необходимо количества информации не отправляется библиотеке и что чувствительная информация не раскрывается.

Сторонние сервисы в основном реализованы как:

  • Отдельная библиотека.
  • Полный SDK.

Статический анализ

Вызовы и/или функции сторонних библиотек должны быть проинспектированы на уровне исходного кода для того чтобы обнаружить используются ли они в соответствии с лучшими практиками.

Все передаваемые в стороннюю библиотеку данные должны быть обезличены, таким образом никакий личные данные(PII) не доступны, что делает идентификацию аккаунта пользователя невозможной. Также вся другая информация, такая как идентификаторы в приложении не должна отправляться стороннему сервису, чтобы было невозможно ассоциировать аккаунт пользователя или же его сессии по чувствительным данным, отправленным в стороннюю библиотеку.

Динамический анализ

Все запросы, сделанные в сторонние сервисы должны быть проанализированы на предмет нахождения чувствительной информации в них. Используя перехватывающий прокси можно проанализировать трафик от приложения к удаленных сторонним сервисам. Все исходящие запросы, которые не адресованы вашему серверу с основной функциональностью, должны быть проверены на предмет передачи чувствительной информации в стороннюю организацию. Например, это может быть персональная идентификационная информация(PII) в трекере или же сервисе рекламы.

Поиск чуствительной информации в кэше клавиатуры

Для упрощения ввода с клавиатуры пользователю предлагается несколько вариантов, например, автокоррекция ввода или же проверка написания. Большинство клавиатурного ввода кэшируется по умолчанию в /private/var/mobile/Library/Keyboard/dynamic-text.dat.

Кэширование клавиатуры достигается с помощью протокола UITextInputTraits, который реализован в UITextField, UITextView и UISearchBar и определяется следующими свойствами:

  • var autocorrectionType: UITextAutocorrectionType - определяет включена автокоррекция или нет во время печати. Когда автокоррекция включена, объект текста отслеживает неизвестные слова и предлагает более подходящие замены пользователю, заменяя напечатанный текст автоматически, если пользователь явно не отменяет действие. Значение по умолчанию для этого свойства UIText​Autocorrection​Type​Default, которое для большинства методов ввода включает автокоррекцию.
  • var secureTextEntry: BOOL - определяет где копирование и кэширование текста должно быть выключено и в случае UITextField скрывает вводимый текст. По умолчанию, значение свойства - NO.

Статический анализ

  • Поищите в предоставляемом исходном коде конструкции, похожие на:
  textObject.autocorrectionType = UITextAutocorrectionTypeNo;
  textObject.secureTextEntry = YES;
  • Откройте файлы xib и storyboard в Interface Builder Xcode и проверте состояние Secure Text Entry и Correction в Attributes Inspector для соответсвующих объектов.

В приложении любая чувствительная информация, вводимая в поля ввода, не должна кэшироваться. Этого можно достигнуть, отключив это свойство программно, воспользовавшись директивой textObject.autocorrectionType = UITextAutocorrectionTypeNo для необходимых UITextFields, UITextViews и UISearchBars. Для данных, таких как PIN или пароли, необходимо скрывать ввод - выставите textObject.secureTextEntry значение YES.

UITextField *textField = [ [ UITextField alloc ] initWithFrame: frame ];
textField.autocorrectionType = UITextAutocorrectionTypeNo;

Динамический анализ

Для джейлбрейк девайса можно осуществить действия:

  1. Сбросьте кэш клавиатуры: Settings > General > Reset > Reset Keyboard Dictionary

  2. Воспользуйтесь приложением и определите функции, которые позволяют пользователю произвести ввод чуствительной информации.

  3. Сделать дамп кэша клавиатуры, файл dynamic-text.dat, находящийся в(может отличаться на iOS ниже 8.0): /private/var/mobile/Library/Keyboard/

  4. Поищите чувствительную информацию: имена пользователей, пароли, почтовые адреса, номера кредитных карт и т.д. Если данную информацию можно найти через кэш клавиатуры, то тест провален.

UITextField *textField = [ [ UITextField alloc ] initWithFrame: frame ];
textField.autocorrectionType = UITextAutocorrectionTypeNo;

На обычном устройстве:

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

 Проверка на доступность чувствительной информации через механизмы IPC

Обзор

Inter Process Communication (IPC)- это метод обмена сообщениями и данными между процессами. В случае, если двум процессам необходимо общение друг с другом, то доступны различные методы реализации IPC на iOS:

  • XPC Services: XPC - это структутированная и асинхронная библиотека, предоставляющая базовую межпроцессную коммуникацию, а также управляемая launchd. Это самый безопасный и гибкий метод реализации IPC на iOS, он должен быть использован в первую очередь. Данный метод выполняется с максимально-возможной, строгой окружающей средой: минимальный доступ к файловой системе, сети, и нет эскалации привилегий до root. Существует два различных API:
    • NSXPCConnection API
    • XPC Services API
  • Mach Ports: вся коммуникация IPC очень сильно завязана на использование Mach Kernel API. Порты Mach разрешают только локальную коммуникацию(на одном устройстве). Они могут быть реализованы нативно или же используя обертки Core Foundation (CFMachPort) и Foundation (NSMachPort).
  • NSFileCoordinator: Класс NSFileCoordinator может быть использован для управления и обменом данных между приложениями, используя локальные файлы, которые доступны на локальной файловой системе различным процессам. Методы NSFileCoordinator выполняются синхронно, так что ваш код будет заблокирован до завершения их работы. Это удобно, потому что вам не придется ждать ответа от асинхронной функции, но, очевидно, что синхронный подход блокирует текущий поток.

Статический анализ

Данный раздел предоставляет различные ключевые слова, которые необходимо искать для нахождения реализаций IPC в исходном коде.

XPC Services

Некоторые классы могут быть использованы,во время реализации NSXPCConnection API:

  • NSXPCConnection
  • NSXPCInterface
  • NSXPCListener
  • NSXPCListenerEndpoint

Несколько атрибутов безопасности для подключения могут быть использованы, и их необходимо проверить.

Для XPC Services API, которые основаны на C, необходимо проверить наличие следующих двух файлов в проекте Xcode:

Mach Ports

Ключевые слова, которые необходимо искать для низкоуровневых реализаций:

  • mach_port_t
  • mach_msg_*

Ключевые слова, которые необходимо искать для высокоуровневых реализаций (обертки для Core Foundation и Foundation):

  • CFMachPort
  • CFMessagePort
  • NSMachPort
  • NSMessagePort
NSFileCoordinator

Ключевые слова для поиска:

  • NSFileCoordinator

Динамический анализ

Механизмы IPC должны быть проверены с использованием статического анализа исходного кода. На данный момент, нет доступного инструмента для проверки использования механизмов IPC.

Проверка наличия чувствительной информации в интерфейсе пользователя

Обзор

Важная часть многих приложений – это ввод чувствительной информации, например, процесс регистрации или же совершение платежа. Чувствительной информацией может быть финансовая информация(кредитные карты) или же пароль от аккаунта, и она может быть доступна, если приложение не маскирует ее правильным образом, во время ввода.

Маскировка чувствительной информации через символы звездочек или точек должна быть применена в приложении, чтобы предотвратить раскрытие информации и снизить риски, например, такой как подглядывание соседа через плечо.

Статический анализ

Текстовые поля, которые маскируют ввод могут быть настроены двумя способами:

Storyboard В storyboard проекта iOS, откройте настройку текстового поля, в которое будет произведен ввода чувствительной информации. Убедитесь что стоит галочка напротив поля "Secure Text Entry". Если данная опция активирована, то ввод будет замаскирован.

Source Code Если текстовое поле определеяется программно в исходном коде, то проверте что свойство isSecureTextEntry активировано. Это маскирует текст, показывая точки вместо него.

sensitiveTextField.isSecureTextEntry = true

Динамический анализ

Для определения утечек чувствительной информации, запустите приложение и определите компоненты, которые либо показывают такую информацию либо принимают ее.

Если информация замаскирована точками или звездочками, например, значит в приложении нет утечек чувствительной информации через графический интерфейс.

Проверка бэкапов на предмет наличия чувствительной информации

Обзор

iOS предлагает функцию автобэкапака, который создает копии данных на устройстве. В iOS, резервные копии(бэкапы) могут быть созданы либо через iTunes, либо используя облако, воспользовавшись свойством резервного копирования в iCloud. В обоих случаях в бэкап включаются почти все данные, хранящиеся на устройстве, исключая очень чувствительные вещи, такие как информация Apple Pay и настройки Touch ID.

iOS создает копии всех установленных приложений и их данных, поэтому стоит озаботится утекает ли, непреднамеренно, чувствительная информация через бэкап. Ответ да всплывает в первую очередь, если приложение небезопасно хранит чувствительную информацию.

Как осуществляется резервное копирование Keychain

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

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

Вывод: до тех пор пока данные хранятся рекомендованными ранее в этой главе методами(хранятся в Keychain или же защифрованы с ключом, храняшимся в Keychain) бэкапы не являются проблемой безопасности.

Статический анализ

Во время бэкапа устройства через iTunes, где конкретные мобильные приложения были установлены, в бэкап будут включены все поддиректории приложения (за исключением папки Library/Caches/) и все файлы, хранящиеся в приватной директории приложения на файловой системе устройства.

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

Так как все файлы в папках Documents/ и Library/Application Support/ всегда бэкапятся по умолчанию, есть возможность исключить файлы из бекапа, вызвав [NSURL setResourceValue:forKey:error:] с ключом NSURLIsExcludedFromBackupKey.

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

Любой из этих API является более предпочтительным по сравнению с более ранними, устаревшими(deprecated) способами прямого указания дополнительного аттрибута. Все приложения, исполняемые на iOS 5.1 и старше, должны использовать эти API для исключения данных из бэкапов.

Далее следует пример кода для исключения файлов из бекапа на iOS 5.1 и старше (Objective-C):

- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
{
    NSURL* URL= [NSURL fileURLWithPath: filePathString];
    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

    NSError *error = nil;
    BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                  forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
    }
    return success;
}

Далее следует пример кода для исключения файлов из бекапа на iOS 5.1 и старше (Swift):

 func addSkipBackupAttributeToItemAtURL(filePath:String) -> Bool
    {
        let URL:NSURL = NSURL.fileURLWithPath(filePath)

        assert(NSFileManager.defaultManager().fileExistsAtPath(filePath), "File \(filePath) does not exist")

        var success: Bool
        do {
            try URL.setResourceValue(true, forKey:NSURLIsExcludedFromBackupKey)
            success = true
        } catch let error as NSError {
            success = false
            print("Error excluding \(URL.lastPathComponent) from backup \(error)");
        }

        return success
    }

Динамический анализ

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

  • Documents/
  • Library/Preferences/
  • Library/Application Support/

Обращайтесь к секции обзора в данной главы для более глубокого понимания назначения этих папок и их содержимого.

Проверка чувствительной информации в автоматически генерируемых скриншотах.

Обзор

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

Статический анализ

Во время анализа исходного кода, посмотрите поля или экраны, где вовлечена чувствительная информация. Идентифицируйте санитизирует ли приложение экран, до перехода в фоновый режим, используя UIImageView.

Возможный способ обойти данную ситуацию, поставить скриншот по умолчанию:

@property (UIImageView *)backgroundImage;
 
- (void)applicationDidEnterBackground:(UIApplication *)application {
    UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
    self.backgroundImage = myBanner;
    [self.window addSubview:myBanner];
}

Данная манипуляция выставит файл "overlayImage.png" как фоновое изображение всегда, когда приложение переходит в фоновый режим. Данный подход защитит от утечки чувствительных данных, так как "overlayImage.png" всегда будет перезаписывать текущий экран(view).

Динамический анализ

Перейдите к экрану приложения, где показывается чувствительная информация, например логин, почта, данные аккаунта и т.п. Перейдите в фоновый режим, нажав на кнопку Home устройства. Подключитесь к устройству и перейдите в следующую директорию (может отличаться на iOS ниже 8.0):

/var/mobile/Containers/Data/Application/$APP_ID/Library/Caches/Snapshots/

Уязвимости по кэшированию скринштов могут быть обнаружены, с использованием Needle. Это демонстрируется ниже:

[needle] > use storage/caching/screenshot
[needle][screenshot] > run
[V] Creating timestamp file...
[*] Launching the app...
[*] Background the app by hitting the home button, then press enter:

[*] Checking for new screenshots...
[+] Screenshots found:
[+]   /private/var/mobile/Containers/Data/Application/APP_ID/Library/Caches/Snapshots/app_name/B75DD942-76D1-4B86-8466-B79F7A78B437@2x.png
[+]   /private/var/mobile/Containers/Data/Application/APP_ID/Library/Caches/Snapshots/app_name/downscaled/12B93BCB-610B-44DA-A171-AF205BA71269@2x.png
[+] Retrieving screenshots and saving them in: /home/user/.needle/output

Если приложение кэширует чувствительную информацию как скриншот, то тест провален.

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

Проверка памяти на наличие чувствительной информации

Обзор

Анализ памяти может помочь разработчикам определить причины различных проблем, таких как краши приложений. Однако, этот же метод может использоваться для получения чувствительных данных. В данном разделе будет описано как проверить происходит ли разглашение данных в памяти процесса.

Прежде всего вам необходимо понять какая чувствительная информация хранится в памяти. В основном если у вас имеется чувствительное вложение(asset), то скорее всего в какой-то момент времени он будет загружен в память. Наша цель убедится, что данная информация доступна минимально возможное время.

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

Следовательно вам лучше стоит начать со статического анализа.

Статический анализ

До того как обратится к исходному коду бывает очень полезно посмотреть документацию(если доступна) и определить компоненты приложения, для получения общей картины о том где конкретные данные могут быть доступны. Например, данные, полученные с веб-сервиса существуют не только в конечной модель объекта, но также могут быть найдены множественные копии в клиенте HTTP, в парсере XML и так далее. В идеале, нам необходимо, чтобы все эти копии удалялись из памяти так быстро, как только возможно.

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

Однако, если чувствительная информация должна находится в памяти, тогда вам следует убедится, что приложение было спроектировано таким образом, чтобы интервал нахождения в памяти и количество копий было минимально. Другими словами, вам необходима централизованная обработка чувствительных данных(минимально возможное количество компонент), основанная на примитивной и изменяемой структуре данных.

Причина последнего требования кроется в том, что оно позволяет разработчикам получить прямой доступ к памяти. Вам необходимо убедится, что данный доступ далее используется для перезаписи чувствительных данных пустыми данными(обычно нулями). Предпочтительными примеры структур данных будут: char [] и int [], но не NSString и не String. В тот момент, когда вы пытаетесь изменить неизменяемый(immutable) объект, такой как String, на самом деле вы создаете его копию и применяете изменения к ней.

Типы данных в Swift, кроме коллекций, должны строго избегаться, кроме тех случаев, когда известно изменяемые они или нет. Многие типы данных в Swift хранят свои данные по значению, а не по ссылке. В то время как для простых типов как char или int мы имеем возможность изменять их действительную память, то для сложных типов как String хранение по значению ведет к скрытым уровням объектов, структур или же примитивных массивов, к чьей памяти можно получить прямой доступ и изменить ее. Конкретное использование возникает и даже может быть задокументировано в получении изменяемого объекта данных, но на самом деле получается изменяемый идентификатор(переменная) как противоположность неизменяемому идентификатору(константе). Например, многие считают что результатом следующего будет неизменяемый String в Swift, но на самом деле это пример переменной, чьё сложное значение может быть изменено(заменено, не изменено в том же месте):

var str1 = "Goodbye"              // "Goodbye", base address:            0x0001039e8dd0
str1.append(" ")                 // "Goodbye ", base address:            0x608000064ae0
str1.append("cruel world!")      // "Goodbye cruel world", base address: 0x6080000338a0
str1.removeAll()                 // "", base address                    0x00010bd66180

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

Использование коллекций в Swift (Array, Set и Dictionary), с другой стороны, может быть допустимым, так как они собирают примитивные типы данных char или int и определены как изменямые(переменные вместо констант), в таком случае их поведение более или менее эквивалентно поведению примитивных массивов(как char []). Но данные коллекции используют безопасное управление памятью, которое может результировать в неидентифицированные копии чувствительных данных в памяти, в случае необходимости копирования лежащего в основе буфера в другое место для его расширения.

Использование изменяемых типов данных в Objective-C, таких как NSMutableString также может быть приемлимо, но также страдает от той же самой проблемы "безопасной памяти" в коллекциях Swift. В добавок обратите пристальное внимание на использование коллекций в Objective-C, так как они хранят данные как ссылки и только Objective-C типы данных разрешены. Следовательно мы не ишем изменяемую коллекцию, но ишем коллекцию, ссылающуюся на изменяемые объекты.

Как мы уже посмотрели на использование типов данных в Swift или Objective-C становится понятно, что необходимо глубокое понимание реализации языка. Более того, мы стали свидетелями рефакторинга ядра между мажорными версиями Swift, которые вылелись в несоответсвующее поведение многих типов данных. Для того чтобы избежать данные проблемы, мы рекомендуем использовать примитивные типы данных, когда необходимо стирать чувствительные данные из памяти.

К сожалению, немногие библиотеки спроектированы с возможностью перезаписи чувствительной информации. Даже Apple не считает это проблемой в официальной документации API iOS SDK. Например, многие API для трансформации данных(парсеры, сериализаторы) оперируют с непримитивными типами данных. Очень похоже, когда вы выставляете флаг Secure Text Entry в UITextField или же не делаете этого, возвращение значения всегда происходит как String или NSString.

Подводя итоги, во время проведения статического анализа на определние доступности чувствительной информации в памяти, вы должны:

  • Попробовать определить компоненты приложения, составить карту, где используются чувствительные данные..
  • Убедиться что чувствительная информация обрабатывается в минимально возможном числе компонентнов.
  • Убедиться что ссылки на объект удаляются надлежашим образом, когда объект, содержащий чувствительную информацию, больше не нужен.
  • Для очень чуствительной информации, убедитесь, что данные перезаписываются как только они больше не нужны.
  • Такие данные не должны передаваться как неизменяемые типы данных такие как String или NSString.
  • Непримитивные типы данных могут оставить данные доступными и в последствии должны избегаться.
  • Перезапись данных должна быть осуществлена, до удаления ссылок.
  • Обратите пристальное внимание на стронние библиотеки. Хорошим признаком будет то, что они осмыслили проблему и в их API данные обрабатываются так, как было рекомендовано выше.

Динамический анализ

Для того, чтобы сделать дамп памяти приложения iOS, несколько различных подходов и инструментов доступно, они перечислены ниже.

Есть возможность сделать дамп памяти процесса приложения, воспользовавшись objection и Fridump на обычном телефоне. Для того, чтобы воспользоваться этой опцией, приложение должно быть переупаковано с FridaGadget.dylib и заново подписано. Детальное объяснение этого процесса можно найти в разделе "Динамический анализ на не джейлбрейк устройствах" в главе "Базовое тестирование безопасности".

Objection (без джейлбрейка)

Objection дает возможность произвести дамп всей памяти запущенного на айфоне процесса.

(virtual-python3) ➜ objection explore

     _     _         _   _
 ___| |_  |_|___ ___| |_|_|___ ___
| . | . | | | -_|  _|  _| | . |   |
|___|___|_| |___|___|_| |_|___|_|_|
        |___|(object)inject(ion) v0.1.0

     Runtime Mobile Exploration
        by: @leonjza from @sensepost

[tab] for command suggestions
iPhone on (iPhone: 10.3.1) [usb] # memory dump all /Users/foo/memory_iOS/memory
Dumping 768.0 KiB from base: 0x1ad200000  [####################################]  100%
Memory dumped to file: /Users/foo/memory_iOS/memory

После этого команда strings может быть выполнена для извлечения строк.

$ strings memory > strings.txt

Откройте strings.txt в вашем любимом редакторе и исследуйте его для поиска чувствительной информации.

Загруженные модули данного процесса также могут быть просмотрены.

iPhone on (iPhone: 10.3.1) [usb] # memory list modules
Name                              Base         Size                 Path
--------------------------------  -----------  -------------------  ---------------------------------------------------------------------------------
foobar                            0x1000d0000  11010048 (10.5 MiB)  /var/containers/Bundle/Application/D1FDA1C6-D161-44D0-BA5D-60F73BB18B75/...
FridaGadget.dylib                 0x100ec8000  3883008 (3.7 MiB)    /var/containers/Bundle/Application/D1FDA1C6-D161-44D0-BA5D-60F73BB18B75/...
libsqlite3.dylib                  0x187290000  1118208 (1.1 MiB)    /usr/lib/libsqlite3.dylib
libSystem.B.dylib                 0x18577c000  8192 (8.0 KiB)       /usr/lib/libSystem.B.dylib
libcache.dylib                    0x185bd2000  20480 (20.0 KiB)     /usr/lib/system/libcache.dylib
libsystem_pthread.dylib           0x185e5a000  40960 (40.0 KiB)     /usr/lib/system/libsystem_pthread.dylib
libsystem_kernel.dylib            0x185d76000  151552 (148.0 KiB)   /usr/lib/system/libsystem_kernel.dylib
libsystem_platform.dylib          0x185e53000  28672 (28.0 KiB)     /usr/lib/system/libsystem_platform.dylib
libdyld.dylib                     0x185c81000  20480 (20.0 KiB)     /usr/lib/system/libdyld.dylib
Fridump (без джейлбрейка)

Оригинальная версия Fridump не поддерживается больше и работает только на Pyhton2. Frida в данный момент времени советует использовать последнюю версию Python 3.x, и как результат Fridump не работает из коробки.

Если вы видете следующие сообщения ошибок, даже если ваше устройство подключено через USB, вам следует посмотреть Fridump с фиксом для Python 3.

➜  fridump_orig git:(master) ✗ python fridump.py -u Gadget

        ______    _     _
        |  ___|  (_)   | |
        | |_ _ __ _  __| |_   _ _ __ ___  _ __
        |  _| '__| |/ _` | | | | '_ ` _ \| '_ \
        | | | |  | | (_| | |_| | | | | | | |_) |
        \_| |_|  |_|\__,_|\__,_|_| |_| |_| .__/
                                         | |
                                         |_|

Can't connect to App. Have you connected the device?

Когда Fridump заработает, вам нужно получить имя приложения, которое вы хотите задампить, что может быть сделано, выполнив frida-ps. После чего просто указываете имя в fridump.

➜  fridump git:(master) ✗ frida-ps -U
 PID  Name
----  ------
1026  Gadget

➜  fridump git:(master) python3 fridump.py -u Gadget -s

        ______    _     _
        |  ___|  (_)   | |
        | |_ _ __ _  __| |_   _ _ __ ___  _ __
        |  _| '__| |/ _` | | | | '_ ` _ \| '_ \
        | | | |  | | (_| | |_| | | | | | | |_) |
        \_| |_|  |_|\__,_|\__,_|_| |_| |_| .__/
                                         | |
                                         |_|

Current Directory: /Users/foo/PentestTools/iOS/fridump
Output directory is set to: /Users/foo/PentestTools/iOS/fridump/dump
Creating directory...
Starting Memory dump...
Progress: [##################################################] 100.0% Complete

Running strings on all files:
Progress: [##################################################] 100.0% Complete

Finished! Press Ctrl+C

Когда вы добавляете флаг -s, все извлеченные из сырой памяти строки записываются в файл strings.txt и хранятся в директории dump Fridump.

Ссылки

OWASP Mobile Top 10 2016

  • M1 - Неправильное использование платформы
  • M2 - Небезопасное хранение данных

OWASP MASVS

  • V2.1: "Системные хранилиша данных используются надлежащим образом для хранения конфиденциальных данных, таких как учетные данные пользователя или криптографические ключи."
  • V2.2: "Чувствительная информация должна храниться либо внутри контейнера приложения либо же в системном хранилище."
  • V2.3: "Чувствительная информация не записывается в лог приложения."
  • V2.4: "Никакие конфиденциальные данные не передаются третьей стороне, если это не является необходимой частью архитектуры."
  • V2.5: "Кэш клавиатуры выключен в полях ввода чувствительной информации. "
  • V2.6: "Чувствительные данных недоступны для механизмов межпроцессного взаимодействия(IPC)."
  • V2.7: "Никакие конфиденциальные данные, такие как пароли или контакты не видны через пользовательский интерфейс."
  • V2.8: "Никакие конфиденциальные данные не включены в резервные копии, созданные мобильной операционной системой."
  • V2.9: "Приложение убирает конфиденциальные данные с экрана(views), когда находится в фоновом режиме."
  • V2.10: "Приложение не хранит конфиденциальные данные в памяти дольше, чем необходимо, и память очищается явно после использования."

CWE

  • CWE-117 - Improper Output Neutralization for Logs
  • CWE-200 - Information Exposure
  • CWE-311 - Missing Encryption of Sensitive Data
  • CWE-312 - Cleartext Storage of Sensitive Information
  • CWE-359 - "Exposure of Private Information ('Privacy Violation')"
  • CWE-522 - Insufficiently Protected Credentials
  • CWE-524 - Information Exposure Through Caching
  • CWE-532 - Information Exposure Through Log Files
  • CWE-534 - Information Exposure Through Debug Log Files
  • CWE-538 - File and Directory Information Exposure
  • CWE-634 - Weaknesses that Affect System Processes
  • CWE-922 - Insecure Storage of Sensitive Information

Tools