Today I want to share a simple way to retrieve user data from a native iOS cache image, automatically generated when your app goes in background.
You can retrieve this kind of informations if your phone was lost or Jailbreaked or connecting it to your pc and open an old backup. You can use tools like iBackup Viewer and more…
Let’s see how it works!
Example
Imagine that your app allow the user to write some reserved informations like personal informations, credit cards, whatever sensitive, like this:
Nothing strange until now… but let’s see what happens in the system:
- Run your app in Simulator
- Write something in the textfields
- Put your app in background
- Reopen the app and kill it
Every app launched, write a Snaphot locally in the file system with the latest status. This is used to “simulate” the app to open fast, loading before of all the latest status as image and next showing real app on screen.
You can go in the Snapshot folder of your app, to do this, add in your viewDidLoad the path of the app:
NSLog("••• PATH: %@", NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!);
This will print on screen the path of your app, go in this folder.
You should see something like this:
Pay attention and you see the latest screenshot of your app before entering in background state, contains all ours data:
We have now the user data stored locally. Totally unsecure.
Precautions
I suggest two simple methods to avoid this kind of data leakage.
- Hide the user data or blur the view before entering in background
- Disable completely the snapshot caching of your app
Of course depends of the scope of your app.
Blurring user app
I’ll show how to add a simple blur effect on your app like this:
Automatically the app BLUR itself and save in the Snapshot folder the blurred one instead of the clear screenshot:
Code:
Inside your SceneDelegate or your AppDelegate (depends of the iOS version of your project), add the didBecomeActive and the willResignActive methods:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func sceneDidBecomeActive(_ scene: UIScene) {
enteringIntoActiveMode()
}
func sceneWillResignActive(_ scene: UIScene) {
enteringIntoBackgroundMode()
}
}
Prepare an extension and implements the two methods above:
extension SceneDelegate {
private func enteringIntoBackgroundMode() {
let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = window!.frame
blurEffectView.tag = 123
self.window?.addSubview(blurEffectView)
}
private func enteringIntoActiveMode() {
self.window?.viewWithTag(123)?.removeFromSuperview()
}
}
Now when your app try to enter in background, a blurred view was added on top of all.
You can also add something different from blur, like your logo or a black screen, what you like.
Your data is now safely locally stored, or better is now hidden!
Disable caching and snapshot
Another simple way is to completely disable the background execution of your app. No snapshots are saved and the app state is restored every launch.
Open your Info.plist file and add this row:
Application does not run in background -> YES
This settings avoid snapshot creation, you can check by yourself (remember to clean the old cached files in the Snaphost folder).
Enjoy.