Удаленная эксплуатация iPhone Часть 0: Поиск векторов

  • Автор темы Admin

Admin

#1
Администратор
Регистрация
31.12.2019
Сообщения
6,642
Реакции
23
Цикл статей:


  1. Удаленная эксплуатация iPhone Часть 0: Поиск векторов;
    xttps://googleprojectzero.blogspot.com/2019/08/the-fully-remote-attack-surface-of.html
  2. Удаленная эксплуатация iPhone Часть 1: Получаем доступ к памяти с помощью iMessage и CVE-2019-8641;
    xttps://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-1.html
  3. Удаленная эксплуатация iPhone Часть 2: Развееваем тьму — Обход ASLR;
    xttps://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-2.html
  4. Удаленная эксплуатация iPhone Часть 3: От повреждения памяти к Javascript и обратно — Исполняем свой код;
    xttps://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-3.html


В этой части мы рассмотрим все возможные векторы удаленной атаки на iOS, а так же опишем уязвимости, найденные в процессе анализа данных векторов:

  • CVE-2019-8613; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1801)
  • CVE-2019-8624; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1828)
  • CVE-2019-8626;
  • CVE-2019-8641; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1881)
  • CVE-2019-8646; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1858)
  • CVE-2019-8647; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1873&can=1&q=label%3AFinder-natasgenka&colspec=ID Status Restrict Reported Vendor Product Finder Summary&start=100)
  • CVE-2019-8660; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1884)
  • CVE-2019-8661; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1856)
  • CVE-2019-8662; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1874)
  • CVE-2019-8663; (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1883)


SMS


SMS Packet Data Units (PDUs) обрабатываются сервисом CommCenter, используя метод sms::Controller::parseRawBytes, который в свою очередь создает экземпляр класса sms::Model, содержащий данные о сообщении. Данный класс обрабатывается sms::Controller::processReceivedSms_sync, и далее рассылается в другие процессы, ответственные за обработку SMS. Проанализировав данные методы - уязвимостей не было выявлено.


Из интересного можно отметить то, что CommCenter содержит SMS симулятор (xttps://github.com/googleprojectzero/iOS-messaging-tools/tree/master/SmsSimulator), который может быть вызван через XPC. Это позволяет обрабатывать сгенерированные SMS PDUs, так же как если бы они пришли по сети, а так же открывает возможность для фаззинга. Профаззив SMS - уязвимостей не было выявлено.


MMS


MMS так же обрабатываются сервисом CommCenter, и большинство обработки происходит в MmsOperation::decodeMessage. Проанализировав логику в IDA, а так же профаззив данный метод - уязвимостей не было выявлено.


Visual Voicemail


VVM получает голосовые сообщения через IMAP сервер ОПСОСа. URL сервера, а так же данные для входа приходят через SMS. В отличие от описанного формата (xttp://www.omtp.org/OMTP_VVM_Specification_v1_3_Final.pdf), iPhone использует свой. Пример входящего сообщения:

Код:
STATE?state=Active;server=vvm.att.com;port=143;pw=asdf;name=555[email protected]

С помощью Android девайса, специально собранного для отправки сырых PDUs и, собственно, их отправки - логи показали дополнительный запрос к серверу. После нескольких попыток - удалось отправить сообщение, изменяющее IMAP сервер целевого устройства, с некоторыми оговорками:

  • VVM должен быть настроен на девайсе;
  • Поле PID в SMS должно быть выставлено в VVM значение ОПСОСа целевого девайса;
  • Некоторые ОПСОСы блокируют VVM IMAP запросы к внешним серверам, поэтому удаленная эксплуатация в этом случае невозможна; (Атакующий все еще может развернуть вблизи устройства свою базовую станцию, но данная атака не рассматривалась)


Просмотр IMAP библиотеки в IDA не дал никаких результатов, после чего был запущен фаззинг. Был развернут IMAP сервер (xttps://github.com/googleprojectzero/iOS-messaging-tools/tree/master/imapiness), возвращающий на каждый запрос специально сформированный ответ, а так же использующий SMS симулятор для отправки VVM SMS, заставляющий устройство вновь совершать запрос к серверу. Таким образом была найдена уязвимость CVE-2019-8613 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1801) в IMAP клиенте. Данная уязвимость возникает, если ответ на команду NAMESPACE содержит namespace, который не может быть правильно обработан. Это приводит к освобождению разделителя почтового ящика, но замены на валидный объект не происходит. Все это приводит к тому что вызывается метод, применяемый к невалидному объекту (use-after-free).


EMAIL


Метод [MFMimePart_contents:toOffset:resultOffset:downloadIfNecessary:asHTML:isComplete:] обрабатывает входящее MIME сообщения, и направляет их в специальный декодер, соответствующий типу MIME. Это делалось добавлением строки типа MIME входящего сообщения к строке 'decode', и вызывая получившийся метод. Таким образом может быть вызван произвольный селектор, что приводит к повреждению памяти.


Данная уязвимость была найдена в iOS 11.3.1, но уже в iOS 12 ее невозможно эксплуатировать из-за изменения логики в вызове произвольных селекторов. Данные изменения не были направлены на решение проблем безопасности. Эта уязвимость была отмечена как CVE-2019-8626, и до сих пор может привести к крэшу.


iMessage


Для анализа iMessage были созданы утилиты (xttps://github.com/googleprojectzero/iOS-messaging-tools/tree/master/iMessage), позволяющие отправлять и логгировать сообщения. Данные утилиты перехватывают функции отправки и получения сообщений в iMessage с помощью Frida (xttps://frida.re), и логгируют сообщение в консоль в случае дампинга или изменяют его в случае отправки. Ниже приведен пример лога сообщения:

Код:
to: mailto:[email protected]
from: tel:+15556667777
{
	gid = "FAA29682-27A6-498D-8170-CC92F2077441";
	gv = 8;
	p = (
		"tel:+15556667777",
		"mailto:[email protected]"
	);
	pv = 0;
	r = "68DF1E20-9ABB-4413-B86B-02E6E6EB9DCF";
	t = "Hello World";
	v = 1;
}

Это бинарный plist, содержащий несколько полей. Ниже представлены наиболее интересные поля:

Код:
t	- Plain text message content;
x	- XML messsage content;
bid	- "Balloon identifier" for plugin;
bp	- Plugin data;
ati	- Attribution info;
p	- Participants;

Некоторые из этих полей содержат бинарные данные, которые впоследствии десериализуются классом NSKeyedUnarchiver. (Поля так же могут быть опционально сжаты в gzip) Особенно интересно поле bp, десериализующееся в SpringBoard (не имеет никакой песочницы) для оповещений, что делает десериализацию вектором для удаленной атаки. Это поле так же десериализуется процессом MobileSMS, но это требует одного клика. Поле ati так же декодируется без участия пользователя в imagent процессе.


NSKeyedArchiver сериализует NSObject в plist формат. Ниже приведена часть сериализованного объекта NSURL:

Код:
<dict>
  <key>$class</key>
  <dict>
    <key>CF$UID</key>
    <integer>7</integer>
  </dict>
  <key>NS.base</key>
  <dict>
    <key>CF$UID</key>
    <integer>0</integer>
  </dict>
  <key>NS.relative</key>
  <dict>
    <key>CF$UID</key>
    <integer>6</integer>
  </dict>
</dict>
<string>http://www.google.com</string>
<dict>
  <key>$classes</key>
  <array>
    <string>NSURL</string>
    <string>NSObject</string>
  </array>
  <key>$classname</key>
  <string>NSURL</string>
</dict>

Поля NS.base и NS.relative - объекты, которые будут использованы для создания класса NSURL. NS.relative указывает на строку 'http://google.com', которая представляет URL. Представленный ниже dict с $classes и $classname полями - описывает экземпляр класса, на который указывает поле $class из первого dict. Когда данный экземпляр десериализуется - декодер вызовет [NSURL initWithCoder:], который в последствие инициализирует класс NSURL.


NSKeyedArchiver может сериализовывать или десериализовывать любой Objective-C класс, реализовывающий initWithCoder:, так же он имеет протокол NSSecurityCoding, позволяющий разработчикам ограничить то что будет декодировано. Классы, реализовывающие initWithCoder: так же должны реализовывать requiresSecureCoding для возможности десериализации когда NSSecureCoding включен. Так же NSSecureCoding требует списка всех разрешенных классов для десериализации. Следует отметить, что список разрешенных классов является не полным списком того, что initWithCoder: может вызывать во время сериализации. Ниже представлен упрощенный псевдокод [NSURL initWithCoder:]:
[NSURL initWithCoder:]

Код:
[NSURL initWithCoder:](NSURL *u, id decoder) {
  NSDATA* book = [decoder decodeObjectOfClass:[NSDATA class] forKey:@"NS:minimalBookmarkData"];
  if (book)
    return [URLByResolvingBookmarkData:data];
  
  NSString* base = [decoder decodeObjectOfClass:[NSString class] forKey:@"NS.base"];
  NSString* relative = [decoder decodeObjectOfClass:[NSString class] forKey:@"NS.relative"];
  
  return [NSURL initWithString:base relativeToURL:relative];
}

Для URL'ов, не являющимися закладками (bookmark) - данному методу потребуется десериализовать класс NSString для полей NS.relative и NS.base, и NSString будет разрешен для десериализации. Также если бы сериализованные данные содержали поле NS.minimalBookmarkData - это бы привело к десериализации NSData. При десериализации классы ограничивают класс возвращаемого значения, но не ограничивают весь спектр атаки на возвращаемом классе.


Существует несколько методов для создания класса NSKeyedUnarchiver, и не во всех по умолчанию включен NSSecureCoding.
NSSecureCoding включен:

  • initForReadingFromData:
  • unarchivedObjectOfClasses:fromData:error:
NSSecureCoding не включен:

  • initWithData:
  • unarchiveObjectWithData:error:
  • initForReadingWithData:


Проанализировав логику iMessage не удалось найти ни одного места десериализации без NSSecureCoding.


Далее были проанализированы расширения. Расширения могут поддерживать предпросмотр, в этом случае SpringBoard вызовет previewSummary в расширении без участия пользователя.


Был найден один баг в расширении Digital Touch - CVE-2019-8624 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1828). Это расширение позволяет слать сообщения, содержащие рисунки и другие визуальные элементы. У расширений есть возможность использования кастомных алгоритмов кодирования информации, но они должны оповещать об этом SpringBoard, чтобы он не декодировал поле bp. Digital Touch использует protobuf, декодируя несколько массивов, и в одном случае некорректно проверяя длину массива перед копированием. Это приводит к out-of-bounds чтению памяти.


Следующим был проанализирован метод initWithCoder: классов, разрешенных для десериализации в SpringBoard при генерации превью сообщения. Ian Beer, в прошлом, нашел несколько LPE уязвимостей (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1172 / xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1168 / xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1175). Разрешенные классы в SpringBoard при декодировании поля bp: NSDictionary, NSString, NSData, NSNumber, NSURL, NSUUID и NSValue. Подклассы этих классов, с любым уровнем наследования также разрешены. Найдено три уязвимости.


CVE-2019-8663 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1883) - уязвимость в десериализации класса SGBigUTF8String, являющимся подклассом NSString. Реализация initWithCoder: десериализует массив байт в последствии представляемый как UTF-8 строка с нулл терминатором, даже если его нет. Это может привести к созданию out-of-bounds памяти.


CVE-2019-8661 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1856) - уязвимость в [NSURL initWithCoder:], затрагивающая только Mac. Обычно, при десериализации URL, декодируется экземпляр класса NSString, но также возможна десериализация NSData, в последствии обрабатываемая как закладка (bookmark). На Mac'e закладка может быть в 'alis' алиас формате (xttps://developer.apple.com/documentation/coreservices/carbon_core/alias_manager), что устарело еще в 2012. Данный формат обрабатывается библиотекой CarbonCore, который использует множество небезопасных строковых функций. Небезопасный вызов strcat приводит к повреждению кучи. Данный формат никогда не используется в iMessage. Он существует только потому что десериализация NSURL универсальна, так что реализация initWithCoder должна поддерживать все возможные варианты.


CVE-2019-8646 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1858) - уязвимость в десериализации класса _NSDataFileBackedFuture (подкласс NSData). Данный класс создает буфер, при доступе к которому подгружается контент файла. Размер буфера и имя файла десериализуются одинаковым образом - в реализации не проверяется соответствие размера буфера и размера файла. Это нарушает гарантии того что length проперти будет соответствовать размеру bytes проперти в NSData, что может привести к различного рода проблемам, включая повреждение памяти.


В процессе анализа выяснилось то, что некоторые подклассы не реализуют initWithCoder, наследуя данный метод у родителя. Для последующего анализа был загружен dyld_shared_cache в IDA и написан скрипт (xttps://bugs.chromium.org/p/project-zero/issues/attachment?aid=394697&signed_aid=5uFIpHlPCfZIwX_Or7gX0w==), исследующий метаданные.


В следствие была найдена уязвимость CVE-2019-8647 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1873&can=1&q=label%3AFinder-natashenka&colspec=ID%20Status%20Restrict%20Reported%20Vendor%20Product%20Finder%20Summary&start=100). Данная уязвимость возникает при десериализации класса _PFArray, расширяющий NSArray и реализующий [_PFArray initWithObject:count:] метод, вызывающийся [NSArray initWithCoder:]. Данный метод предполагает что на все объекты массива что-то ссылается. Это означает что освобожденный массив может быть вновь создан и использован. Похоже что разработчиками не предполагалась десериализация данного класса.


Еще одна похожая уязвимость CVE-2019-8662 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1874).


Еще один интересный вопрос о реализации сериализации в NSKeyedArchiver - что произойдет если в сериализованном объекте будут находится циклы? Фундаментально формат NSKeyedArchiver это plist, содержащий числовые ссылки, так что объект может ссылаться сам на себя или могут быть циклы содержащие несколько объектов. Грубо говоря десериализация объекта выглядит следующим образом:

Код:
if (temp_dict[key])
  return [temp_dict[key] copy];
if (obj_dict[key])
  return [obj_dict[key] copy];

NSObject* a = [NSSomeClass alloc];
temp_dict[key] = a; // No references!!!
NSObject* obj = [a initWithCoder:];
temp_dict[key] = NIL;
obj_dict[key] = obj;

return obj;

Когда объект десериализуется - вызывается alloc, и созданный объект помещается во временный массив, не удерживая на него ссылку. Далее вызывается initWithCoder на созданном объекте, после чего он убирается из временного массива и добавляется уже в постоянный массив объектов, добавляющий ссылку на объект.


В этой реализации есть несколько проблем. Нет никаких гарантий того, что initWithCoder вернет этот же объект, для которого он был вызван. Более того, initWithCoder освобождает объект, если он не был возвращен. Так что теоретически реализация initWithCoder может освободить объект, возвращенный alloc и уже потом десериализовать поле, которое ссылается на этот же объект. Проведя анализ SpringBoard - не было найдено ни одного initWithCoder имеющего данную проблему, однако это может встретится в других приложениях.


Еще одна проблема в том, что реализация initWithCoder заканчивается десериализацией себя же после чего используется данный объект, что может привести к тому что объект будет использован перед тем как вызов будет завершен.


Исследуя уязвимости с циклами было найдено две уязвимости. Первая CVE-2019-8641 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1881) подробно будет разобрана в следующей части.


Вторая уязвимость затрагивающая циклы в сериализации - CVE-2019-8660 (xttps://bugs.chromium.org/p/project-zero/issues/detail?id=1884). Эта уязвимость находилась в NSKnownKeysDictionary1 (подкласс NSDictionary). В этом случае ключи предоставляются как экземпляр класса NSKnownKeysMappingStrategy1, десериализующий количество ключей отдельно от массива содержащего ключи. Десериализованное количество ключей проверяется на соответствие размеру массива содержащего ключи, после того как ключи были десериализованы. Таким образом, если ключ является NSKnownKeysDictionary1 он может использовать NSKnownKeysMappingStrategy1 перед проверкой количества ключей. Это является integer overflow, приводящего к повреждению памяти в [NSKnownKeysDictionary1 initWithCoder:].


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

Код:
[NSKeyedUnarchiver unarchivedObjectOfClasses:@[NSURL] from:mydata error:NIL];

Очевидно, что в пример выше входит [NSURL initWithCoder:] так же как и все подклассы, реализованные в вызывающем приложении, к примеру [NSMyURLSubClass initWithCoder:].


Но и еще включает в себя любой подкласс NSURL в библиотеках, импортируемых приложением. К примеру, предположим что приложение импортирует фреймворк UserNotification. В таком случае, [UNSecurityScopedURL initWithCoder:], подкласс NSURL будет так же частью вектора атаки, даже если библиотека не используется в целях сериализации.


Давайте ближе ознакомимся с реализацией [NSURL initWithCoder:], описанной ранее.

Код:
[NSURL initWithCoder:](NSURL *u, id decoder) {
  NSData* book = [decoder decodeObjectOfClass:[NSData class] forKey:@"NS.minimalBookmarkData"];
  if (book)
    return [URLByResolvingBookmarkData:data];
  
  NSString* base = [decoder decodeObjectOfClass:[NSString class] forKey:@"NS.base"];
  NSString* relative = [decoder decodeObjectOfClass:[NSString class] forKey:@"NS.relative"];
  
  return [NSURL initWithString:base relativeToURL:relative];
}

Она содержит три вызова decodeObjectOfClass:forKey:, декодируя объекты классов NSString, NSData и NSURL. Теперь [NSString initWithCoder:] и [NSData initWithCoder:] являются векторами атаки. Реализация [NSURL initWithCoder:] будет обрабатывать объект NSData как закладку (bookmark) если есть, что так же является вектором атаки.


Вектора атаки так же включают в себя подклассы NSString и NSData. Предположим что приложение использует только UserNotification, Foundation и CoreFoundation, тогда подклассы [_NSDispatchData initWithCoder:], [__NSLocalizedString initWithCoder:], [NSLocalizableString initWithCoder:] и [UNLocalizedString initWithCoder:] так же являются векторами атаки.


Здесь так же есть два метода, включающие использование еще большего числа классов. [UNLocalizedString initWithCoder:] десериализует NSArray, тем временем как [__NSLocalizedString initWithCoder:] декодирует объект классов NSDictionary, NSNumber и NSDate. Не будем рассматривать эти классы, так как уже ясно что они будут включать в себя еще больше классов, что намного увеличит площадь атаки.


Это касается только метода initWithCoder. Учитывая то, что любой подкласс, благодаря наследованию, может быть частью десериализации площадь атаки еще больше увеличивается. Например, [NSString initWithCoder:] может вызвать [NSString initWithString:] или [NSString initWithBytes:length:encoding:] в зависимости от того какие поля будут десериализованы. Так что эти два метода подклассов являются частью вектора атаки. В таком случае это все включает в себя [NSBigMutableString initWithString:], [NSDebugString initWithString:], [NSPlaceholderMutableString initWithBytes:length:encoding] и [NSPlaceholderString initWithBytes:length:encoding]. Другие классы имеют такую же большую площадь атаки благодаря наследованию.


Заключение


Были проанализированы SMS, MMS, VVM, Email и iMessage, в которых были найдены 10 уязвимостей. Большинство уязвимостей было найдено в iMessage благодаря сложности перечисления векторов атаки.


Автор: Unkn
 

Members, viewing this thread

Сейчас на форуме нет ни одного пользователя.