# OWASP iOS Exercise ###### By Robihamanto Source: [OWASP/iGoat-swift](https://github.com/OWASP/iGoat-Swift) Useful link: [OWASP Mobile Application Security | iOS Platform Overview](https://mas.owasp.org/MASTG/iOS/0x06a-Platform-Overview/) ## Summary of exercise #### πŸ”‘ Data Protection (Rest) - Core Data Storage βœ… - Couchbase Storage βœ… - Yap Storage βœ… - Plist Storage βœ… - NSUserDefaults Storage βœ… - Realm Storage βœ… - Keychain Usage | 🚨 Need real device - Local Data Storage (SQLite) | 🚨 TBD - Cookie Storage | βœ… - Webkit Cache | βœ… #### πŸ”‘ Side Channel Data Leaks - Backgrounding βœ… - Cut and Paste βœ… #### πŸ”‘ Reverse Engineering - String Analysis βœ… #### πŸ”‘ Key Management - Random Key Generation βœ… - Hardcoded Keys βœ… - Key Storage Server Side | 🚨 TBD - Secure NSUserDefault | 🚨 TBD #### πŸ”‘ Cloud Misconfiguration - Cloud Misconfiguration | 🚨 TBD βœ… Complete exercise 🚨 TBD from OWASP # πŸ” Data Protection (Rest) ## Core Data Storage In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data in Core Data format. Your task is to locate the CoreData file and find the sensitive data that it contains. 1. Find the core data storage and open it <img src="https://i.imgur.com/8kZNgKt.png" width="500"/> Core data can easily found in app sandbox and shown with sqlite. >Although Core Data is easy to use and fast, it should never be used to store sensitive information. **Notes:** ❌ Should avoid - Never store sensitive data to core data - `fatalError()` causes the application to generate a crash log and terminate. Avoid using this function in a shipping application. βœ… Good to implement - Using the [encrypted-core-data](https://github.com/project-imas/encrypted-core-data) is better solution when using the core data rather than plain text. - Handle error with `fatalError()` only for debug application. Try to handle the error appropriately. --- ## Couchbase Storage In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data using a CouchBase file. Your task is to locate the CouchBase file and find the sensitive data that it contains. 1. Find the couchbase storage and open it <img src="https://i.imgur.com/jPYfAkV.png" width="500"/> Couchbase storage can easily found in app sandbox and shown with sqlite. **Notes:** ❌ Should avoid - Never store sensitive data to couchbase storage βœ… Good to implement - Using the [encrypted-core-data](https://github.com/project-imas/encrypted-core-data) is better solution when using the core data rather than plain text. --- ## Yap Storage In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data using a YAP Storage file. Your task is to locate the YAP Storage file and find the sensitive data that it contains. 1. Find the Yap storage and open it <img src="https://i.imgur.com/0TozkgB.png" width="500"/> Yap storage can easily found in app sandbox and shown with sqlite. **Notes:** ❌ Should avoid - Never store sensitive data to couchbase storage βœ… Good to implement - Using the [encrypted-core-data](https://github.com/project-imas/encrypted-core-data) is better solution when using the core data rather than plain text. --- ## Plist Storage In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data using a Plist file. Your task is to locate the plist file and find the sensitive data that it contains. <img src="https://i.imgur.com/Kn187se.png" width="500"/> Anything saved on `.plist` files will easily found in sandbox. > The data stored in the plist file is neither encrypted nor protected. An attacker having access to the device can easily access the plist file and look for sensitive data in plain text format. So the developers should never store any sensitive information in the plist file as this is not a secured format. **Notes:** ❌ Should avoid - Never save any token including (password, api_key, etc) on `.plist` file. It's easily find on app sandbox. βœ… Good to implement - If we want to store any config for app, it's recommend to store it on server. --- ## NSUserDefaults Storage In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data using a NSUserDefaults file. Your task is to locate the NSUserDefaults file and find the sensitive data that it contains. 1. Find .plist file for user default ``` $ open Containers/Data/Application/EF8143C5-2CB9-48E1-8BB2-03FC666A7552/Library/Preferences/OWASP.iGoat-Swifth.plist ``` 2. Plist found and secret seen <img src="https://i.imgur.com/Dbtqcia.png" width="500"/> Anything saved on `UserDefault` files will easily found in sandbox within .plist file. > The data stored in `NSUserDefaults` is not secured and should not be used to store sensitive information. **Notes:** ❌ Should avoid - Never store any token or user credentials on user default βœ… Good to implement - Try to save token in safe place eg. keychain --- ## Realm Storage In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data using a Realm Storage file. Your task is to locate the Realm Storage file and find the sensitive data that it contains. 1. Locate realm storage location ``` $ sudo find * | grep "realm" ``` 2. Found the files: ``` $ 9AD3A044-2622-46AF-B29F-349237DA507E/Documents/default.realm ``` 3. Open with Realm Studio: <img src="https://i.imgur.com/id5mONZ.png" width="500"/> Anything saved on `Realm` will saved plain without any encrypt > The data stored in `Realm` is not secured and should not be used to store sensitive information. **Notes:** ❌ Should avoid - Never unencrypted info to realm database - all .realm database will easy to open with [Realm Studio](https://github.com/realm/realm-studio) βœ… Good to implement - Encrypt sensitive data with [Realm Encrypt Swift](https://www.mongodb.com/docs/realm/sdk/swift/#encryption) Example encrypt code: ``` // Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server let config = Realm.Configuration(encryptionKey: getKey()) do { let realm = try Realm(configuration: config) // Use the Realm as normal } catch let error as NSError { // If the encryption key is wrong, `error` will say that it's an invalid database fatalError("Error opening realm: \(error)") } ``` ## Webkit Cache In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data using a web cache. Your task is to locate the cache file and find the sensitive data that it contains. > The server for this exercise is error, explained below. <img src="" width="500"/> 1. Running server log with docker: <img src="https://i.imgur.com/d1bOiuJ.png" width="500"/> 2. Try to get the page from the server but Not Found shown: <img src="https://i.imgur.com/AKcBGhU.png" width="300"/> 3. Try to post from the iOS app also showing error: <img src="https://i.imgur.com/mNu3V4t.png" width="300"/> 4. Showing webcache on `Cache.db` but Not Found shown rather than the website. <img src="https://i.imgur.com/5C2zX6S.png" width="800"/> By default NSURLSession stores data, such as HTTP requests and responses in the Cache.db database. This database can contain sensitive data, if tokens, usernames or any other sensitive information has been cached. To find the cached information open the data directory of the app `(/var/mobile/Containers/Data/Application/<UUID>)` and go to `/Library/Caches/<Bundle Identifier>`. The WebKit cache is also being stored in the Cache.db file. Objection can open and interact with the database with the command sqlite connect Cache.db, as it is a normal SQLite database. **Notes:** ❌ Should avoid - Keeping the sensitive on Cache response βœ… Good to implement - Recommended to disable Caching this data - Recommended to remove Cached responses after logout - If you don't need to use the advantage of cookies it would be recommended to just use the .ephemeral configuration property of URLSession, which will disable saving cookies and Caches - Cache can be also disabled by setting the Cache Policy to .notAllowed. It will disable storing Cache in any fashion, either in memory or on disk. ## Cookie Storage In this exercise, you'll exploit an app that unsafely stores sensitive data locally on the iOS device. In the lesson, the app stores data using a binary cookies file. Your task is to locate the binary cookies file and find the sensitive data that it contains. 1. Finding binary cookies inside app sandbox ``` $ find * | grep ".binarycookies" ``` 2. Binary cookies found in this directory ``` $ cd data/Containers/Data/Application/<application-id>/Library/Cookies/ ``` 3. Open the binary cookie with BinaryCookieReader.py ``` $ python BinaryCookieReader/BinaryCookieReader.py com.swaroop.iGoat.binarycookies ``` All sensitive data could be accessed inside the cookie binary in the app, We can use the [BinaryCookieReader](https://github.com/as0ler/BinaryCookieReader/) to decode them in a readable form. Even the cookie file can be accessed in backups. <img src="" width="500"/> **Notes:** ❌ Should avoid - Saving sensitive data to cookie βœ… Good to implement - Use secure cookie provided by apple [apple.com/secure_cookie](https://developer.apple.com/documentation/foundation/nshttpcookie/1393025-secure) ## Keychain Usage 🚨 This exercise can only run within jailbroken iOS device, not simulator. --- # πŸ” Side Channel Data Leaks ## Backgrounding A default behavior in iOS is to capture a JPG image of any application screen as it is shut down or backgrounded. Unfortunately, the JPG file is placed on the device without any form of access control or encryption. In this exercise, you'll first exploit the weakness by finding some data in the app's screen shot. 1. Find snapshot: ``` find * | grep "Snapshot" ``` 2. Found snapshot: <img src="https://i.imgur.com/xS7jeLy.png" width="500"/> 3. Open it: ``` open Containers/Data/Application/E9EE64E5-62D4-4010-9A7B-63AAC086F971/Library/SplashBoard/Snapshots/sceneID:OWASP.iGoat-Swifth-default/downscaled/57DD229D-C2FA-4F32-B069-DF1F9147A943@3x.ktx ``` <p float=left> <img src="https://i.imgur.com/muCH7En.png" width="40%"/> <img src="https://i.imgur.com/luDy0nR.png" width="50%"/> <p> Backgrounding A default behavior in iOS is to capture a JPG image of any application screen as it is shut down or backgrounded. Unfortunately, the JPG file is placed on the device without any form of access control or encryption. **Notes:** ❌ Should avoid - Attacker can access the sensitive data by seeing the snapshot βœ… Good to implement - Once way to prevent this bad behaviour is to put a blank screen or remove the sensitive data before taking the snapshot using the ApplicationDidEnterBackground() function. This is the remediation method that will set a default screenshot. ``` private var backgroundImage: UIImageView? func applicationDidEnterBackground(_ application: UIApplication) { let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage")) myBanner.frame = UIScreen.main.bounds backgroundImage = myBanner window?.addSubview(myBanner) } func applicationWillEnterForeground(_ application: UIApplication) { backgroundImage?.removeFromSuperview() } ``` --- ## Cut and Paste The cut and paste feature in iOS is enormously useful to the end user, of course. Unfortunately, it can also lead to leakage of sensitive user information. Once the data is in the buffer, any application (or user) can paste that data inside other applications. In this exercise, you'll first exploit the weakness by finding some sensitive data inside the cut and paste buffer. 1. Copy something from the app <img src="https://i.imgur.com/iGCiJXd.png" width="400"/> 2. Open the pasteboard directory inside sandbox <img src="https://i.imgur.com/fLFf1bI.png" width="400"/> 3. Paste content found: <img src="https://i.imgur.com/6bi4NJw.png" width="500"/> **Notes:** The UIPasteboard enables sharing data within an app, and from an app to other apps. There are two kinds of pasteboards: - systemwide general pasteboard: for sharing data with any app. Persistent by default across device restarts and app uninstalls (since iOS 10). - custom / named pasteboards: for sharing data with another app (having the same team ID as the app to share from) or with the app itself (they are only available in the process that creates them). Non-persistent by default (since iOS 10), that is, they exist only until the owning (creating) app quits. ❌ Should avoid - Avoid allowing all copy and paste function in sensitive screen (eg. banking app). βœ… Good to implement - It's recommended to prevent its users to copy sensitive data to the clipboard. --- # πŸ” Reverse Engineering ## String Analysis In this exercise, we are trying to extract a secret piece of information embedded within a string located within the app's binary. 1. Decompile .ipa file using [Hopper](https://www.hopperapp.com/) <img src="https://i.imgur.com/AdOncuy.png" width="500"/> 2. Submit with empty textfield <img src="https://i.imgur.com/CYdjV7w.png" width="200"/> 3. Try to find `Empty entry!!` String <img src="https://i.imgur.com/dBVxMps.png" width="500"/> 4. Found the answer for the riddle <img src="https://i.imgur.com/fHVYuUk.png" width="500"/> Developers usually hide secrets in the application source code’s business logic. **Notes:** ❌ Should avoid - Never store any secrets, token, key, and etc inside the code. βœ… Good to implement - Recommended for using server config or pre-build secret # πŸ” Key Management ## Random Key Generation In this exercise, you will study one of the way to generate random key to store sensitive locally. 1. All log to the device are shown in the Console app ``` Open Console app preinstalled in macOS ``` 2. Open the device console log <img src="https://i.imgur.com/78fuf2v.png" width="500"/> 3. The log from device should shown in the console ``` encryption key is AE57C232-7DD6-47CD-A776-5DB2A4794911 ``` We can inspect the application logs to identify leaked debug strings that might help us to infer the application business logic. **Notes:** ❌ Should avoid - Never log any encrypted data or key to the console βœ… Good to implement - Use the log only for debug app, but never to log for sensitive data --- ## Hardcoded Keys In this exercise, you're going to idenfiy insecure mechanism for storing sensitive data locally. You will observe encryption key hard coded in code using which you can decrypt sensitive data into plain text. Because the source code isn’t always available, we’ll examine the binary by reversing the assembly code. For this purpose, we could use an open source tool like Radare2 (https://rada.re/n/). 1. Finding the executabla iOS app from the `.ipa` file ``` $ unzip iGoat-Swift.ipa $ cd Payload/iGoat-Swift.app/ ``` 2. Thinning the binary only isolates a specific architecture’s executable code. ``` $ rabin2 -x iGoat iGoat-Swift.fat/iGoat-Swift.fat.arm_32.0 created (23729776) iGoat-Swift.fat/iGoat-Swift.fat.arm_64.1 created (24685984) ``` 3. Perofming initial analysis on the binary file ``` $ r2 -A iGoat-Swift.fat/iGoat.arm_64.1 [x] Analyze all flags starting with sym. and entry0 (aa) [x] Analyze function calls (aac) ``` 4. Find the broken crypto exercise possible file ``` [0x003115c0]> fs; f | grep Broken Output: 0x1000c99b4 104 method.iGoat_Swift.BrokenCryptographyExerciseVC.showItemPressed 0x1000c9e64 44 method.iGoat_Swift.BrokenCryptographyExerciseVC.viewDidLoad 0x1000c9fa4 96 method.iGoat_Swift.BrokenCryptographyExerciseVC.initWithNibName:bundle: ``` 5. Use the pdc command to generate pseudocode and decompile the specific function. ``` [0x1000c8adc]> pdc @method.iGoat_Swift.BrokenCryptographyExerciseVC.viewDidLoad Output: int method.iGoat_Swift.BrokenCryptographyExerciseVC.viewDidLoad (int esi, int edx) { loc_0x1000c9e64: [var_20h]! = (x20, 2) ``` 6. We can see the hardcoded value from the code ``` x8 = x8 + 0xca8 //0x1003c1ca8 ; str.cstr.b_nkP_ssword123 ; (cstr 0x10036a5da) "b@nkP@ssword123" ``` We can inspect the application logs to identify leaked debug strings that might help us to infer the application business logic. **Notes:** ❌ Should avoid - Never store any sensitive data to the code βœ… Good to implement - Use build some configuration library when we need to use any key inside the app ## Title Desc <img src="" width="500"/> **Notes:** ❌ Should avoid - a list βœ… Good to implement - a list # Other Notes Example how to open iPhone 14 Pro Sandbox (each device has different deviceID) ``` cd ~/Library/Developer/CoreSimulator/Devices/B03EA848-0077-4426-BBF4-DD3C71756966/data/ ``` #### Useful Penentration test link https://book.hacktricks.xyz/mobile-pentesting/ios-pentesting #### Related video https://www.youtube.com/watch?v=U3wabqTTXSE #### Finding file with terminal ``` find ./ -name "*.sqlite" -or -name "*.db" ``` #### How to run the server ``` brew install docker brew install docker-compose brew install docker-machine brew install virtualbox (restart macOS) docker-machine create --driver virtualbox default https://stackoverflow.com/questions/21069908/vboxmanage-error-failed-to-create-the-host-only-adapter eval "$(docker-machine env default)" docker-compose up (in server/docker_packaging) ``` ``` // Purging All Unused or Dangling Images, Containers, Volumes, and Networks docker system prune / docker system prune -a // Removing Container docker ps -a docker rm ID_or_Name ID_or_Name // Removing Image docker images -a docker rmi ImageName/ImageID ``` #### Useful sqlite3 command ``` Aruns-sqlite3 CoreData.sqlite SQLite version 3.24.0 2018-06-04 19:24:41 Enter ".help" for usage hints. sqlite> .headers ON sqlite> .tables ZUSER Z_METADATA Z_MODELCACHE Z_PRIMARYKEY sqlite> select * from ZUSER; Z_PK|Z_ENT|Z_OPT|ZEMAIL|ZPASSWORD 1|1|1|john@test.com|coredbpassword sqlite> ``` #### Installing Python 2.7 on macOS ``` $ brew install pyenv $ pyenv install 2.7.18 // If you want to set to global use $ pyenv global 2.7.18 $ PATH=$(pyenv root)/shims:$PATH ``` ## Templates: ## Title Desc <img src="" width="500"/> **Notes:** ❌ Should avoid - a list βœ… Good to implement - a list