preface

Recently, the project App was delivered to a third-party security institution for security detection, which exposed a security vulnerability. Specifically, the transaction login account and password in plain text (HTTPS interface) were detected in the sandbox. If the mobile phone is stolen and lost, it is possible to be cracked and obtained (although the probability of the mobile phone being stolen and lost is very small plus password cracking, jailbreaking and a series of operations are also very difficult, but as a program ape we still have to avoid it from the theory). When I first saw the report, I was a little surprised at first, because I never took the initiative to save the password, but later I found that it was NSURLCache that caused it.

NSURLCache

NSURLCache maps NSURLRequest to NSCachedURLResponse. With NSURLRequestCachePolicy, iOS provides you with a complete HTTP caching mechanism. NSURLRequestCachePolicy is pretty familiar, so I won’t go into that. NSURLCache provides both memory and disk caches. We can customize the size of the cache. The default disk Cache path is sandbox Library/Caches/{bundle ID}/ cache.db, although we can also customize the Cache path.

Store database

NSURLCache ultimately stores data as a database. Let’s open cache.db to find out. Let’s just focus on the three tables below:

  • Cfurl_cache_response, which contains the request_key field, the URL we requested, as shown below:

See that my login interface in the test environment is http://***/login(https), which also contains a primary key entry_ID.

  • Cfurl_cache_receiver_data, which contains the data returned by the server, is as follows:

  • Cfurl_cache_blob_data, which contains request and response data in bloB format, as shown below:

We save it as text, and then the command line cat can check that it contains the parameters of the request, as shown in the picture below:We also see that the file content starts with bplist00, which is actually a plist file.

Delete the cache

Ok, so now we have located the cache of the account and password, which must be removed for security reasons. If you look at the API documentation, NSURLCache provides the following two interfaces for removing the cache for a specific request. Wouldn’t it be logical to call them and remove the cache? Unfortunately, the call test found that both interfaces were invalid and the corresponding cache could not be removed until the apple dad fixed it in a later version:

- removeCachedResponseForRequest:
    Removes the cached URL response for a specified URL request.
- removeCachedResponseForDataTask:
    Removes the cached URL response for a specified data task.
Copy the code

In addition, there are two interfaces that can remove the cache, but they are not request-specific, so they do not meet our requirements.

- removeCachedResponsesSinceDate: Go down the given cache of any cached responses since the provided date. - removeAllCachedResponses go down the receiver's  cache, removing all stored cached URL responses.Copy the code

Failed to delete the cache. Procedure

Cache-Control

Instead, the HTTP header has a cache-control field. Why not use it to manage the Cache’s storage scheme? Cache-control has different values for request and response, including the following:

  • Request instructions:
field instructions
max-age=<seconds> Sets the maximum period for which the cache is stored, after which the cache is considered expired in seconds. In contrast to Expires, time is the time relative to the request
max-stale[=<seconds>] Indicates that the client is willing to accept an expired resource. Optionally set a time (in seconds) that indicates the elapsed time that the response cannot exceed.
min-fresh=<seconds> Indicates that the client wants to get the latest response within the specified time.
no-cache Forces the cache to submit the request to the original server for validation before releasing the cache copy.
no-store The cache should not store anything about client requests or server responses.
no-transform Resources may not be converted or converted. HTTP headers such as content-encoding, content-range, and content-Type cannot be modified by the proxy. For example, an opaque proxy can convert image formats to save cache space or reduce traffic on slow links. The no-transform directive does not allow this.
only-if-cached Indicates that the client accepts only cached responses and does not check with the original server for newer copies
  • Response instruction:
field instructions
must-revalidate The cache must verify the state of the old resource before using it, and it must not use expired resources.
no-cache Forces the cache to submit the request to the original server for validation before releasing the cache copy.
no-store The cache should not store anything about client requests or server responses.
no-transform
public Indicates that the response can be cached by any object, including the client that sent the request, the proxy server, and so on.
private Indicates that the response can only be cached by a single user, not as a shared cache (that is, the proxy server cannot cache it), and that the response content can be cached.
proxy-revalidate It has the same effect as must-revalidate, but applies only to shared caches (such as proxies) and is ignored by private caches.
max-age=<seconds> Sets the maximum period for which the cache is stored, after which the cache is considered expired in seconds. In contrast to Expires, time is the time relative to the request
s-maxage=<seconds> Overrides max-age or Expires headers, but only for shared caches (such as individual agents) and is ignored in private caches.

Here we simply set the no-store value for the request or server response, and the client NSURLCache will not cache it, and the problem is solved perfectly.

summary

Security issues still need to be dealt with carefully. The security vulnerability caused by NSURLCache is relatively hidden, because it is not our active behavior. If there are any mistakes in the above content, welcome to correct.