Pull to refresh
149.6
Инфосистемы Джет
российская ИТ-компания

Утечка конфиденциальных данных при кешировании сетевых запросов на платформе iOS

Reading time 7 min
Views 6.4K
Критичным аспектом в контексте информационной защищенности пользовательских данных является конфиденциальность передаваемых данных в процессе взаимодействия защищаемого приложения с веб-сервисами. Например, утрата конфиденциальности в приложениях, манипулирующих номером банковской карты и кодом аутентификации CVV2/CVC2, представляется уязвимостью критичной степени важности. Одной из распространенных ошибок при разработке защищенных приложений для мобильной платформы iOS, приводящих к частичной или полной утрате конфиденциальности передаваемых данных, является чрезмерное кэширование межсетевых запросов.

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

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


Испытание боем


Рассмотрим пример неправильного использования кэша межсетевых запросов. В результате исследования Приложения В в контексте анализа защищенности было установлено, что приложением кэшируются HTTP-запросы, осуществляемые в рамках взаимодействия с основным веб-сервисом. Межсетевые запросы сохраняются в локальной базе данных SQLite в домашней директории приложения по относительному адресу Library/Caches/<application.c>/Cache.db. Схема базы данных приводится ниже.
Схема базы данных
CREATE TABLE cfurl_cache_schema_version(schema_version INTEGER);
CREATE TABLE cfurl_cache_response(entry_ID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, version INTEGER, hash_value INTEGER, storage_policy INTEGER, request_key TEXT UNIQUE, time_stamp NOT NULL DEFAULT CURRENT_TIMESTAMP);
CREATE TABLE cfurl_cache_blob_data(entry_ID INTEGER PRIMARY KEY, response_object BLOB, request_object BLOB, proto_props BLOB, user_info BLOB);
CREATE TABLE cfurl_cache_receiver_data(entry_ID INTEGER PRIMARY KEY, receiver_data BLOB);
CREATE INDEX request_key_index ON cfurl_cache_response(request_key);
CREATE INDEX time_stamp_index ON cfurl_cache_response(time_stamp);
CREATE INDEX proto_props_index ON cfurl_cache_blob_data(entry_ID);
CREATE INDEX receiver_data_index ON cfurl_cache_receiver_data(entry_ID);


Столбец request_key таблицы cfurl_cache_response базы данных хранит идентификаторы сетевых ресурсов (Uniform Resource Identifier, URI), доступ к которым был запрошен приложением, включая запросы по протоколу HTTPS. Такие запросы могут включать в себя конфиденциальные данные пользователя, в том числе аутентификационные данные пользователя. Так, например, приложение В использует квази-RESTful интерфейс для взаимодействия с веб-сервисом и осуществляет GET-запрос для авторизации пользователя.

sqlite> select request_key from cfurl_cache_response;
...
https://example.com/api/1.0/auth?login=Selma_Nagel&password=qwerty
...

Столбец receiver_data таблицы cfurl_cache_receiver_data базы данных хранит ответы сервера, которые были получены приложением, включая запросы по протоколу HTTPS. Так, в приложении В используется веб-форма оплаты услуг с использованием банковской карты.

sqlite> select receiver_data from cfurl_cache_receiver_data;
...
<input data-val="true" ...="" id="CardNumber" name="CardNumber" type="hidden" value="1231 1231 1231 1234">
<input data-val="true" ...="" id="CardCode" name="CardCode" type="hidden" value="321">
...

Таким образом, конфиденциальные данные пользователя хранятся на запоминающем устройстве мобильного устройства в незашифрованном виде. Векторов атаки на уязвимое приложение может быть несколько: от вирусного ПО, исполняющегося на стационарном ПК пользователя, до вредоносных приложений, нацеленных на jailbroken-устройствах. Подробнее об этом, а также о типичных ошибках хранения конфиденциальных данных Вы можете прочитать в нашей предыдущей статье.

Как такое стало возможно?


За кэширование межсетевых запросов в рамках мобильного приложения, осуществляемых объектами класса NSURLConnection, отвечает объект класса NSURLCache, доступный через метод +sharedURLCache. Объекты класса NSURLCache содержат два параметра, регулирующих объем контейнера в динамической памяти (In-Memory Cache) и на запоминающем устройстве (On-Disk Cache). Подробнее о классе NSURLCache можно почитать в официальной документации.

На операционных системах iOS v4.x и ниже кэширование межсетевых запросов на запоминающем устройстве не производилось, а параметр класса diskCapacity игнорировался. Начиная с iOS версий 5 и выше, приложение по умолчанию создает кэш HTTP-запросов на жестком диске мобильного устройства, ограниченный емкостью в 20 Мб. А начиная с 6-й версии iOS, реализована поддержка кэширования запросов по протоколу HTTPS.

Представляется целесообразным упомянуть, что уязвимости подвержены все мобильные приложения для платформы iOS, явным или неявным образом осуществляющие межсетевые запросы с помощью NSURLConnection. В частности, классы межсетевых запросов популярной библиотеки AFNetworking представляют собой обертки над NSURLConnection. Таким образом, мобильные приложения, использующие AFNetworking, также являются потенциально уязвимыми.

Как защитить приложение?


Наиболее простой метод защиты от кэширования запросов, включающих конфиденциальную информацию — установить значение diskCapacity объекта sharedURLCache равным 0.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    ...
}

С использование делегатов это можно сделать так.

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
    /* Implement cacheing logic here. */
    return nil; // HACK: just do not cache
}

Тонкая настройка с Cache-Control


Решения, указанные выше, вряд ли кто-нибудь назовет изящными (скорее наоборот). Они подойдут для быстрого исправления логики приложения, однако для более тонкой настройки взаимодействия клиентского приложения с веб-сервисом мы можем прибегнуть с изменениям политики кэширования запросов на серверной стороне. Политика кэширования устанавливается в HTTP-заголовке Cache-Control (RFC 2616).

Для демонстрации поведения NSURLCache в зависимости от политики кэширования веб-ресурсов мы собрали простое приложение для мобильной платформы iOS. Был использован пакет iOS SDK v7.0, а приложение было запущено на симуляторе устройства.


Рис. 1. Работа тестового приложения

Результаты нашего маленького исследования в приводятся в таблице 1. Обратите внимание на то, что вопреки распространенному мнению, приложением кэшируются межсетевые запросы даже без установленного значения заголовка Cache-Control.

Ресурс Cache-Control Кэшируется
/htbin/mr must-revalidate Да
/htbin/nocache no-cache Да
/htbin/nostore no-store Нет
/htbin/private private Да
/htbin/public public Да
/htbin/woheader Не указан Да
/htbin/implicit max-age=604800 Да

Табл. 1. Кэширование запросов на диске в зависимости от Cache-Control

Таким образом, наиболее разумным решением, направленным на устранение выявленной уязвимости представляется установка значения Cache-Control равным no-store для запросов, содержащих конфиденциальную информацию. Учитывая семантику значения no-store, можно с уверенностью утверждать, что большая часть клиентских приложений не будут кэшировать такие запросы.

RFC 2616, пункт 14.9.2
14.9.2 What May be Stored by Caches

no-store
The purpose of the no-store directive is to prevent the inadvertent release or retention of sensitive information (for example, on backup tapes). The no-store directive applies to the entire message, and MAY be sent either in a response or in a request. If sent in a request, a cache MUST NOT store any part of either this request or any response to it. If sent in a response, a cache MUST NOT store any part of either this response or the request that elicited it. This directive applies to both non- shared and shared caches. «MUST NOT store» in this context means that the cache MUST NOT intentionally store the information in non-volatile storage, and MUST make a best-effort attempt to remove the information from volatile storage as promptly as possible after forwarding it.
Even when this directive is associated with a response, users might explicitly store such a response outside of the caching system (e.g., with a «Save As» dialog). History buffers MAY store such responses as part of their normal operation.
The purpose of this directive is to meet the stated requirements of certain users and service authors who are concerned about accidental releases of information via unanticipated accesses to cache data structures. While the use of this directive might improve privacy in some cases, we caution that it is NOT in any way a reliable or sufficient mechanism for ensuring privacy. In particular, malicious or compromised caches might not recognize or obey this directive, and communications networks might be vulnerable to eavesdropping.


Заключение


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

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

На уровне приложения данная потенциальная уязвимость закрывается с помощью явного запрета локального кеширования при создании NSURLConnection. На уровне сервера данная потенциальная уязвимость должна закрываться указанием на запрет кеширования в HTTP-заголовках ответов сервера для всех запросов, содержащих конфиденциальные данные.
Tags:
Hubs:
+13
Comments 10
Comments Comments 10

Articles

Information

Website
jet.su
Registered
Founded
1991
Employees
1,001–5,000 employees
Location
Россия