📜 ⬆️ ⬇️

Leakage of confidential data when caching network requests on the iOS platform

A critical aspect in the context of information security of user data is the confidentiality of the transmitted data in the process of interaction of the protected application with web services. For example, loss of confidentiality in applications that manipulate a bank card number and CVV2 / CVC2 authentication code seems to be a vulnerability of critical importance. One of the common mistakes when developing secure applications for the iOS mobile platform, leading to partial or total loss of privacy of transmitted data, is the excessive caching of inter-network requests.

In the context of developing applications for mobile platforms, internetwork query caching can be categorized as recommended and most frequently used practices, since it allows developers to significantly improve application performance. Development toolkits for modern mobile platforms usually include packages that automate the processing and caching of internetwork requests, in particular HTTP requests.

Like caching of dynamic memory requests or conditional jumps in microprocessors, the interfaces of classes that cache HTTP requests are transparent to the developer and perform caching against the background. Continuing the analogy with the functional block caching in the processor, it can be noted that the lack of understanding of the internal structure of the caching mechanism often leads to gross programming errors. In the context of mobile applications, improper use of the HTTP request cache leads to a drop in application performance and partial or complete loss of privacy. An example of a common mistake that leads to a drop in performance is re-caching of requests by an application (Double caching).
')

Challenge Test


Consider an example of misuse of the interrogation cache. As a result of the study of Annex B in the context of security analysis, it was established that the application caches HTTP requests made as part of interaction with the main web service. Internet queries are stored in the local SQLite database in the home directory of the application at the relative Library / Caches / <application.c> /Cache.db address. The database schema is given below.
Database schema
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); 


The request_key column of the database cfurl_cache_response table stores network resource identifiers (Uniform Resource Identifier, URIs) that the application has requested access to, including requests via the HTTPS protocol. Such requests may include sensitive user data, including user authentication data. For example, application B uses a quasi-RESTful interface to interact with the web service and issues a GET request to authorize the user.

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

The database receiver_data column in the database cfurl_cache_receiver_data table stores server responses that were received by the application, including requests using the HTTPS protocol. Thus, Appendix B uses a web form of payment for services using a bank card.

 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"> ... 

Thus, confidential user data is stored on the storage device of the mobile device in an unencrypted form. There may be several attack vectors for a vulnerable application: from virus software running on a user's desktop PC to malicious applications targeting jailbroken devices. You can read more about this, as well as typical mistakes in storing confidential data in our previous article .

How was this possible?


For caching inter-network requests within the mobile application, implemented by objects of the NSURLConnection class, the object of the NSURLCache class, accessible through the + sharedURLCache method, is responsible. Objects of the NSURLCache class contain two parameters that regulate the volume of the container in dynamic memory (In-Memory Cache) and on the storage device (On-Disk Cache). More information about the class NSURLCache can be read in the official documentation .

On iOS operating systems v4.x and below, internetwork requests were not cached on the storage device, and the diskCapacity class parameter was ignored. Starting with iOS 5 and above, the application creates a default cache of HTTP requests on the hard disk of a mobile device, limited to 20 MB in capacity. And starting with the 6th version of iOS, support for caching requests via the HTTPS protocol has been implemented.

It seems appropriate to mention that all mobile applications for the iOS platform are exposed to vulnerabilities that explicitly or implicitly perform inter-network requests using NSURLConnection. In particular, the internetwork request classes of the popular AFNetworking library are wrappers over NSURLConnection. Thus, mobile applications using AFNetworking are also potentially vulnerable.

How to protect the application?


The simplest method to protect against caching requests that include confidential information is to set the value of the diskCapacity of the sharedURLCache object to 0.

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

With the use of delegates this can be done like this.

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

Tweaking with Cache-Control


The solutions mentioned above are unlikely to be called graceful by anyone (rather the opposite). They are suitable for quickly correcting the logic of the application, but to fine-tune the interaction of the client application with the web service, we can resort to changes in the query caching policy on the server side. The caching policy is set in the Cache-Control HTTP header ( RFC 2616 ).

To demonstrate the behavior of NSURLCache depending on the caching policy of web resources, we have compiled a simple application for the iOS mobile platform. The iOS SDK v7.0 package was used, and the application was launched on the device simulator.


Fig. 1. Work test application

The results of our small study are shown in Table 1. Notice that, contrary to popular belief, the application caches internetwork requests even without the Cache-Control header value set.

ResourceCache-controlCached
/ htbin / mrmust-revalidateYes
/ htbin / nocacheno-cacheYes
/ htbin / nostoreno-storeNot
/ htbin / privateprivateYes
/ htbin / publicpublicYes
/ htbin / woheaderNot specifiedYes
/ htbin / implicitmax-age = 604800Yes

Tab. 1. Caching disk requests depending on Cache-Control

Thus, the most sensible solution to eliminate the identified vulnerability is to set the Cache-Control value to no-store for queries containing confidential information. Given the semantics of the no-store value, it is safe to say that most client applications will not cache such requests.

RFC 2616, paragraph 14.9.2
14.9.2 What May be Stored by Caches

no-store
For example, on backup tapes. MAY NOT BE DIRECTED. If sent, please send a message. If sent in response, it should be noted. This directive applies to both non-shared and shared caches. "MUST NOT store", it is clear how to store it.
This would be the case with the caching system (eg, with a "Save As" dialog). History buffers MAY store
This is a list of the requirements of the authors. In the case of a directive, it would be necessary to ensure that privacy policy exists. In particular, it’s not possible to recognize or obey this directive.


Conclusion


This article showed that since version 5 of the iOS operating system, when using the NSURLConnection class with the default settings, caching of web requests on the disk is allowed. In particular, the disk cache can contain confidential data such as logins, passwords, credit card numbers, etc. In other words, confidential data is stored on the disk without the knowledge of the application or user. Virtually all applications that interact over the network and transmit sensitive data are potentially vulnerable.

Malicious applications running on personal computers can extract data from the disk cache when connecting a device running iOS to a personal computer. This may be a Trojan program on the victim’s computer, or a special program on the attacker's computer, provided that the latter receives physical access to the device for a short time.

At the application level, this potential vulnerability is closed by explicitly denying local caching when creating an NSURLConnection. At the server level, this potential vulnerability should be closed by indicating that caching in the HTTP headers of server responses for all requests containing confidential data is prohibited.

Source: https://habr.com/ru/post/219615/


All Articles