overview.md (66895B)
1 --- 2 title: "iOS Pentesting" 3 section: "Mobile" 4 sectionSlug: "mobile-pentesting" 5 sourcePath: "src/mobile-pentesting/ios-pentesting/README.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/mobile-pentesting/ios-pentesting/README.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: true 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # iOS Pentesting 14 15 ## iOS Basics 16 17 18 [Ios Basics](/hacktricks/mobile-pentesting/ios-pentesting/ios-basics) 19 20 ## Testing Environment 21 22 In this page you can find information about the **iOS simulator**, **emulators** and **jailbreaking:** 23 24 25 [Ios Testing Environment](/hacktricks/mobile-pentesting/ios-pentesting/ios-testing-environment) 26 27 For structured practice, useful training material includes the INE iOS course, RE:iOS Apps, the *iPwn Apps* paper, and an introductory iOS application-security course.<sup>[[3]](#references)[[17]](#references)[[19]](#references)[[20]](#references)</sup> Deliberately vulnerable targets include DVIA/DVIA-v2, the OWASP MSTG Hacking Playground, iGoat, and WheresMyBrowser.iOS; they provide concrete binaries and source code for reproducing the techniques described below.<sup>[[21]](#references)[[22]](#references)[[23]](#references)[[24]](#references)[[26]](#references)</sup> 28 29 ## Initial Analysis 30 31 ### Basic iOS Testing Operations 32 33 During the testing **several operations are going to be suggested** (connect to the device, read/write/upload/download files, use some tools...). Therefore, if you don't know how to perform any of these actions please, **start reading the page**: 34 35 36 [Basic Ios Testing Operations](/hacktricks/mobile-pentesting/ios-pentesting/basic-ios-testing-operations) 37 38 > [!TIP] 39 > For the following steps **the app should be installed** in the device and should have already obtained the **IPA file** of the application.\ 40 > Read the [Basic iOS Testing Operations](/hacktricks/mobile-pentesting/ios-pentesting/basic-ios-testing-operations) page to learn how to do this. 41 42 ### Basic Static Analysis 43 44 Some interesting iOS - IPA files decompilers: 45 46 - [https://github.com/LaurieWired/Malimite](https://github.com/LaurieWired/Malimite) 47 - [https://ghidra-sre.org/](https://ghidra-sre.org/) 48 49 It's recommended to use the tool [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) to perform an automatic Static Analysis to the IPA file. 50 51 Identification of **protections are present in the binary**: 52 53 - **PIE (Position Independent Executable)**: When enabled, the application loads into a random memory address every-time it launches, making it harder to predict its initial memory address. 54 55 ```bash 56 otool -hv <app-binary> | grep PIE # It should include the PIE flag 57 ``` 58 59 - **Stack Canaries**: To validate the integrity of the stack, a ‘canary’ value is placed on the stack before calling a function and is validated again once the function ends. 60 61 ```bash 62 otool -I -v <app-binary> | grep stack_chk # It should include the symbols: stack_chk_guard and stack_chk_fail 63 ``` 64 65 - **ARC (Automatic Reference Counting)**: To prevent common memory corruption flaws 66 67 ```bash 68 otool -I -v <app-binary> | grep objc_release # It should include the _objc_release symbol 69 ``` 70 71 - **Encrypted Binary**: The binary should be encrypted 72 73 ```bash 74 otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # The cryptid should be 1 75 ``` 76 77 **Identification of Sensitive/Insecure Funcions** 78 79 - **Weak Hashing Algorithms** 80 81 ```bash 82 # On the iOS device 83 otool -Iv <app> | grep -w "_CC_MD5" 84 otool -Iv <app> | grep -w "_CC_SHA1" 85 86 # On linux 87 grep -iER "_CC_MD5" 88 grep -iER "_CC_SHA1" 89 ``` 90 91 - **Insecure Random Functions** 92 93 ```bash 94 # On the iOS device 95 otool -Iv <app> | grep -w "_random" 96 otool -Iv <app> | grep -w "_srand" 97 otool -Iv <app> | grep -w "_rand" 98 99 # On linux 100 grep -iER "_random" 101 grep -iER "_srand" 102 grep -iER "_rand" 103 ``` 104 105 - **Insecure ‘Malloc’ Function** 106 107 ```bash 108 # On the iOS device 109 otool -Iv <app> | grep -w "_malloc" 110 111 # On linux 112 grep -iER "_malloc" 113 ``` 114 115 - **Insecure and Vulnerable Functions** 116 117 ```bash 118 # On the iOS device 119 otool -Iv <app> | grep -w "_gets" 120 otool -Iv <app> | grep -w "_memcpy" 121 otool -Iv <app> | grep -w "_strncpy" 122 otool -Iv <app> | grep -w "_strlen" 123 otool -Iv <app> | grep -w "_vsnprintf" 124 otool -Iv <app> | grep -w "_sscanf" 125 otool -Iv <app> | grep -w "_strtok" 126 otool -Iv <app> | grep -w "_alloca" 127 otool -Iv <app> | grep -w "_sprintf" 128 otool -Iv <app> | grep -w "_printf" 129 otool -Iv <app> | grep -w "_vsprintf" 130 131 # On linux 132 grep -R "_gets" 133 grep -iER "_memcpy" 134 grep -iER "_strncpy" 135 grep -iER "_strlen" 136 grep -iER "_vsnprintf" 137 grep -iER "_sscanf" 138 grep -iER "_strtok" 139 grep -iER "_alloca" 140 grep -iER "_sprintf" 141 grep -iER "_printf" 142 grep -iER "_vsprintf" 143 ``` 144 145 #### Common Jailbreak detection methods 146 147 - **File System Checks**: Look for the presence of common jailbreak files and directories, such as `/Applications/Cydia.app` or `/Library/MobileSubstrate/MobileSubstrate.dylib`.<sup>[[18]](#references)[[30]](#references)</sup> 148 - **Sandbox Violations**: Attempt to access restricted areas of the file system, which should be blocked on non-jailbroken devices. 149 - **API Checks**: Check if it's possible to use forbidden calls like `fork()` to create a child process or `system()` to see if /bin/sh exists. 150 - **Process Checks**: Monitor for the presence of known jailbreak-related processes, such as `Cydia`, `Substrate`, or `ssh`. 151 - **Kernel Exploits**: Check for the presence of kernel exploits that are commonly used in jailbreaks. 152 - **Environment Variables**: Inspect environment variables for signs of a jailbreak, such as `DYLD_INSERT_LIBRARIES`. 153 - **Libraries Check**: Check the libs that are loaded into the app process. 154 - **Check schemes**: Like `canOpenURL(URL(string: "cydia://"))`. 155 156 #### Common Anti-Debugging detection methods 157 158 - **Check for Debugger Presence**: Use `sysctl` or other methods to check if a debugger is attached. 159 - **Anti-Debugging APIs**: Look for calls to anti-debugging APIs like `ptrace` or `SIGSTOP` like `ptrace(PT_DENY_ATTACH, 0, 0, 0)`. 160 - **Timing Checks**: Measure the time taken for certain operations and look for discrepancies that may indicate debugging. 161 - **Memory Checks**: Inspect memory for known debugger artifacts or modifications. 162 - **Environment Variables**: Check for environment variables that may indicate a debugging session. 163 - **Mach Ports**: Detect if mach exception ports are being used by debuggers. 164 165 166 #### Anti-Debugging & Anti-Tamper Techniques (Layered Checks) 167 168 Real-world apps often layer pre-exec, on-attach, and continuous checks. Common patterns to look for (and how to neutralize them during testing):<sup>[[1]](#references)</sup> 169 170 - **Private API side-channel fingerprinting**: private launch APIs (e.g., `SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions`) are abused to probe for installed bundle IDs (`com.opa334.TrollStore`, `org.coolstar.SileoStore`, `com.tigisoftware.Filza`, etc.) based on return codes/logging. Hook the call and sanitize arguments/return values to emulate a clean device. 171 - **Self-attestation via code-signing state**: `csops()` with `CS_OPS_ENTITLEMENTS_BLOB` reads entitlements; unexpected values trigger exit. Pair this with integrity checks (CRC32/MD5 of resources, certificate validation, Mach-O metadata like `LC_ENCRYPTION_INFO_64`) to detect re-signing or patching. Instrument these routines and force "expected" results during analysis. 172 - **Kill-on-attach**: `ptrace(PT_DENY_ATTACH)` combined with `abort()`/`exit()` on attach. Bypass by neutralizing the termination path or hooking `ptrace` to succeed without enforcing denial. 173 - **Crash forensics sabotage**: overwrite CPU registers before crashing to destroy backtraces. Prefer breakpoints/hooks earlier in the detection path instead of relying on crash logs. 174 - **Jetsam-based termination**: deliberate memory pressure to trigger jetsam, which yields no normal crash log. Look for large allocations around detection logic and cap/short-circuit them to keep logs. 175 - **Continuous checks with delayed enforcement**: heartbeat timers re-run detection and enforce later. Trace timers/dispatch sources and keep the process alive by bypassing the delayed kill path. 176 177 ### Basic Dynamic Analysis 178 179 Check out the dynamic analysis that [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) perform. You will need to navigate through the different views and interact with them but it will be hooking several classes on doing other things and will prepare a report once you are done. 180 181 ### Listing Installed Apps 182 183 Use the command `frida-ps -Uai` to determine the **bundle identifier** of the installed apps:<sup>[[4]](#references)</sup> 184 185 ```bash 186 $ frida-ps -Uai 187 PID Name Identifier 188 ---- ------------------- ----------------------------------------- 189 6847 Calendar com.apple.mobilecal 190 6815 Mail com.apple.mobilemail 191 - App Store com.apple.AppStore 192 - Apple Store com.apple.store.Jolly 193 - Calculator com.apple.calculator 194 - Camera com.apple.camera 195 - iGoat-Swift OWASP.iGoat-Swift 196 ``` 197 198 ### Basic Enumeration & Hooking 199 200 Learn how to **enumerate the components of the application** and how to easily **hook methods and classes** with objection: 201 202 203 [Ios Hooking With Objection](/hacktricks/mobile-pentesting/ios-pentesting/ios-hooking-with-objection) 204 205 ### IPA Structure 206 207 The structure of an **IPA file** is essentially that of a **zipped package**. By renaming its extension to `.zip`, it can be **decompressed** to reveal its contents. Within this structure, a **Bundle** represents a fully packaged application ready for installation. Inside, you will find a directory named `<NAME>.app`, which encapsulates the application's resources.<sup>[[5]](#references)</sup> 208 209 - **`Info.plist`**: This file holds specific configuration details of the application. 210 - **`_CodeSignature/`**: This directory includes a plist file that contains a signature, ensuring the integrity of all files in the bundle. 211 - **`Assets.car`**: A compressed archive that stores asset files like icons. 212 - **`Frameworks/`**: This folder houses the application's native libraries, which may be in the form of `.dylib` or `.framework` files. 213 - **`PlugIns/`**: This may include extensions to the application, known as `.appex` files, although they are not always present. \* [**`Core Data`**](https://developer.apple.com/documentation/coredata): It is used to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device. To sync data across multiple devices in a single iCloud account, Core Data automatically mirrors your schema to a CloudKit container. 214 - [**`PkgInfo`**](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html): The `PkgInfo` file is an alternate way to specify the type and creator codes of your application or bundle. 215 - **en.lproj, fr.proj, Base.lproj**: Are the language packs that contains resources for those specific languages, and a default resource in case a language isn' t supported. 216 - **Security**: The `_CodeSignature/` directory plays a critical role in the app's security by verifying the integrity of all bundled files through digital signatures. 217 - **Asset Management**: The `Assets.car` file uses compression to efficiently manage graphical assets, crucial for optimizing application performance and reducing its overall size. 218 - **Frameworks and PlugIns**: These directories underscore the modularity of iOS applications, allowing developers to include reusable code libraries (`Frameworks/`) and extend app functionality (`PlugIns/`). 219 - **Localization**: The structure supports multiple languages, facilitating global application reach by including resources for specific language packs. 220 221 **Info.plist** 222 223 The **Info.plist** serves as a cornerstone for iOS applications, encapsulating key configuration data in the form of **key-value** pairs. This file is a requisite for not only applications but also for app extensions and frameworks bundled within. It's structured in either XML or a binary format and holds critical information ranging from app permissions to security configurations. For a detailed exploration of available keys, one can refer to the [**Apple Developer Documentation**](https://developer.apple.com/documentation/bundleresources/information_property_list?language=objc). 224 225 For those looking to work with this file in a more accessible format, the XML conversion can be achieved effortlessly through the use of `plutil` on macOS (available natively on versions 10.2 and later) or `plistutil` on Linux. The commands for conversion are as follows: 226 227 - **For macOS**: 228 229 ```bash 230 $ plutil -convert xml1 Info.plist 231 ``` 232 233 - **For Linux**: 234 235 ```bash 236 $ apt install libplist-utils 237 $ plistutil -i Info.plist -o Info_xml.plist 238 ``` 239 240 Among the myriad of information that the **Info.plist** file can divulge, notable entries include app permission strings (`UsageDescription`), custom URL schemes (`CFBundleURLTypes`), and configurations for App Transport Security (`NSAppTransportSecurity`). These entries, along with others like exported/imported custom document types (`UTExportedTypeDeclarations` / `UTImportedTypeDeclarations`), can be effortlessly located by inspecting the file or employing a simple `grep` command: 241 242 ```bash 243 $ grep -i <keyword> Info.plist 244 ``` 245 246 **Data Paths** 247 248 In the iOS environment, directories are designated specifically for **system applications** and **user-installed applications**. System applications reside in the `/Applications` directory, while user-installed apps are placed under `/var/mobile/containers/Data/Application/`. These applications are assigned a unique identifier known as a **128-bit UUID**, making the task of manually locating an app's folder challenging due to the randomness of the directory names.<sup>[[6]](#references)</sup> 249 250 > [!WARNING] 251 > As applications in iOS must be sandboxed, each app will have also a folder inside **`$HOME/Library/Containers`** with app's **`CFBundleIdentifier`** as the folder name. 252 > 253 > However, both folders (data & container folders) have the file **`.com.apple.mobile_container_manager.metadata.plist`** that links both files in the key `MCMetadataIdentifier`). 254 255 To facilitate the discovery of a user-installed app's installation directory, the **objection tool** provides a useful command, `env`. This command reveals detailed directory information for the app in question. Below is an example of how to use this command: 256 257 ```bash 258 OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env 259 260 Name Path 261 ----------------- ------------------------------------------------------------------------------------------- 262 BundlePath /var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app 263 CachesDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library/Caches 264 DocumentDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Documents 265 LibraryDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library 266 ``` 267 268 Alternatively, the app name can be searched within the `/private/var/containers` using the `find` command: 269 270 ```bash 271 find /private/var/containers -name "Progname*" 272 ``` 273 274 Commands such as `ps` and `lsof` can also be utilized to identify the app's process and list open files, respectively, providing insights into the application's active directory paths: 275 276 ```bash 277 ps -ef | grep -i <app-name> 278 lsof -p <pid> | grep -i "/containers" | head -n 1 279 ``` 280 281 **Bundle directory:** 282 283 - **AppName.app** 284 - This is the Application Bundle as seen before in the IPA, it contains essential application data, static content as well as the application's compiled binary. 285 - This directory is visible to users, but **users can't write to it**. 286 - Content in this directory is **not backed up**. 287 - The contents of this folder are used to **validate the code signature**. 288 289 **Data directory:** 290 291 - **Documents/** 292 - Contains all the user-generated data. The application end user initiates the creation of this data. 293 - Visible to users and **users can write to it**. 294 - Content in this directory is **backed up**. 295 - The app can disable paths by setting `NSURLIsExcludedFromBackupKey`. 296 - **Library/** 297 - Contains all **files that aren't user-specific**, such as **caches**, **preferences**, **cookies**, and property list (plist) configuration files. 298 - iOS apps usually use the `Application Support` and `Caches` subdirectories, but the app can create custom subdirectories. 299 - **Library/Caches/** 300 - Contains **semi-persistent cached files.** 301 - Invisible to users and **users can't write to it**. 302 - Content in this directory is **not backed up**. 303 - The OS may delete this directory's files automatically when the app is not running and storage space is running low. 304 - **Library/Application Support/** 305 - Contains **persistent** **files** necessary for running the app. 306 - **Invisible** **to** **users** and users can't write to it. 307 - Content in this directory is **backed** **up**. 308 - The app can disable paths by setting `NSURLIsExcludedFromBackupKey`. 309 - **Library/Preferences/** 310 - Used for storing properties that can **persist even after an application is restarted**. 311 - Information is saved, unencrypted, inside the application sandbox in a plist file called \[BUNDLE_ID].plist. 312 - All the key/value pairs stored using `NSUserDefaults` can be found in this file. 313 - **tmp/** 314 - Use this directory to write **temporary files** that do not need to persist between app launches. 315 - Contains non-persistent cached files. 316 - **Invisible** to users. 317 - Content in this directory is not backed up. 318 - The OS may delete this directory's files automatically when the app is not running and storage space is running low. 319 320 Let's take a closer look at iGoat-Swift's Application Bundle (.app) directory inside the Bundle directory (`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`):<sup>[[25]](#references)</sup> 321 322 ```bash 323 OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls 324 NSFileType Perms NSFileProtection ... Name 325 ------------ ------- ------------------ ... -------------------------------------- 326 Regular 420 None ... rutger.html 327 Regular 420 None ... mansi.html 328 Regular 420 None ... splash.html 329 Regular 420 None ... about.html 330 331 Regular 420 None ... LICENSE.txt 332 Regular 420 None ... Sentinel.txt 333 Regular 420 None ... README.txt 334 ``` 335 336 ### Binary Reversing 337 338 Inside the `<application-name>.app` folder you will find a binary file called `<application-name>`. This is the file that will be **executed**. You can perform a basic inspection of the binary with the tool **`otool`**: 339 340 ```bash 341 otool -Vh DVIA-v2 #Check some compilation attributes 342 magic cputype cpusubtype caps filetype ncmds sizeofcmds flags 343 MH_MAGIC_64 ARM64 ALL 0x00 EXECUTE 65 7112 NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE 344 345 otool -L DVIA-v2 #Get third party libraries 346 DVIA-v2: 347 /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1) 348 /usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.6.0) 349 /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11) 350 @rpath/Bolts.framework/Bolts (compatibility version 1.0.0, current version 1.0.0) 351 [...] 352 ``` 353 354 **Check if the app is encrypted** 355 356 See if there is any output for: 357 358 ```bash 359 otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO 360 ``` 361 362 **Disassembling the binary** 363 364 Disassemble the text section: 365 366 ```bash 367 otool -tV DVIA-v2 368 DVIA-v2: 369 (__TEXT,__text) section 370 +[DDLog initialize]: 371 0000000100004ab8 sub sp, sp, #0x60 372 0000000100004abc stp x29, x30, [sp, #0x50] ; Latency: 6 373 0000000100004ac0 add x29, sp, #0x50 374 0000000100004ac4 sub x8, x29, #0x10 375 0000000100004ac8 mov x9, #0x0 376 0000000100004acc adrp x10, 1098 ; 0x10044e000 377 0000000100004ad0 add x10, x10, #0x268 378 ``` 379 380 To print the **Objective-C segment** of the sample application one can use: 381 382 ```bash 383 otool -oV DVIA-v2 384 DVIA-v2: 385 Contents of (__DATA,__objc_classlist) section 386 00000001003dd5b8 0x1004423d0 _OBJC_CLASS_$_DDLog 387 isa 0x1004423a8 _OBJC_METACLASS_$_DDLog 388 superclass 0x0 _OBJC_CLASS_$_NSObject 389 cache 0x0 __objc_empty_cache 390 vtable 0x0 391 data 0x1003de748 392 flags 0x80 393 instanceStart 8 394 ``` 395 396 In order to obtain a more compact Objective-C code you can use [**class-dump**](http://stevenygard.com/projects/class-dump/): 397 398 ```bash 399 class-dump some-app 400 // 401 // Generated by class-dump 3.5 (64 bit). 402 // 403 // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 404 // 405 406 #pragma mark Named Structures 407 408 struct CGPoint { 409 double _field1; 410 double _field2; 411 }; 412 413 struct CGRect { 414 struct CGPoint _field1; 415 struct CGSize _field2; 416 }; 417 418 struct CGSize { 419 double _field1; 420 double _field2; 421 }; 422 ``` 423 424 However, the best options to disassemble the binary are: [**Hopper**](https://www.hopperapp.com/download.html?) and [**IDA**](https://www.hex-rays.com/products/ida/support/download_freeware/). 425 426 ## Data Storage 427 428 To learn about how iOS stores data in the device read this page: 429 430 431 [Ios Basics](/hacktricks/mobile-pentesting/ios-pentesting/ios-basics) 432 433 > [!WARNING] 434 > The following places to store information should be checked **right after installing the application**, **after checking all the functionalities** of the application and even after **login out from one user and login into a different one**.\ 435 > The goal is to find **unprotected sensitive information** of the application (passwords, tokens), of the current user and of previously logged users. 436 437 ### Plist 438 439 **plist** files are structured XML files that **contains key-value pairs**. It's a way to store persistent data, so sometimes you may find **sensitive information in these files**. It's recommended to check these files after installing the app and after using intensively it to see if new data is written. 440 441 The most common way to persist data in plist files is through the usage of **NSUserDefaults**. This plist file is saved inside the app sandbox in **`Library/Preferences/<appBundleID>.plist`** 442 443 The [`NSUserDefaults`](https://developer.apple.com/documentation/foundation/nsuserdefaults) class provides a programmatic interface for interacting with the default system. The default system allows an application to customize its behaviour according to **user preferences**. Data saved by `NSUserDefaults` can be viewed in the application bundle. This class stores **data** in a **plist** **file**, but it's meant to be used with small amounts of data.<sup>[[7]](#references)</sup> 444 445 This data cannot be longer accessed directly via a trusted computer, but can be accessed performing a **backup**. 446 447 You can **dump** the information saved using **`NSUserDefaults`** using objection's `ios nsuserdefaults get` 448 449 To find all the plist of used by the application you can access to `/private/var/mobile/Containers/Data/Application/{APPID}` and run: 450 451 ```bash 452 find ./ -name "*.plist" 453 ``` 454 455 To convert files from **XML or binary (bplist)** format to XML, various methods depending on your operating system are available: 456 457 **For macOS Users:** Utilize the `plutil` command. It's a built-in tool in macOS (10.2+), designed for this purpose: 458 459 ```bash 460 $ plutil -convert xml1 Info.plist 461 ``` 462 463 **For Linux Users:** Install `libplist-utils` first, then use `plistutil` to convert your file: 464 465 ```bash 466 $ apt install libplist-utils 467 $ plistutil -i Info.plist -o Info_xml.plist 468 ``` 469 470 **Within an Objection Session:** For analyzing mobile applications, a specific command allows you to convert plist files directly: 471 472 ```bash 473 ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist 474 ``` 475 476 ### Core Data 477 478 [`Core Data`](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple_ref/doc/uid/TP40001075-CH8-SW1) is a framework for managing the model layer of objects in your application. [Core Data can use SQLite as its persistent store](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/), but the framework itself is not a database.\ 479 Core Data does not encrypt its data by default. However, an additional encryption layer can be added. See the [encrypted-core-data repository](https://github.com/project-imas/encrypted-core-data) for an example. 480 481 You can find the SQLite Core Data information of an application in the path `/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support` 482 483 **If you can open the SQLite and access sensitive information, then you found a miss-configuration.** 484 485 ```text 486 -(void)storeDetails { 487 AppDelegate * appDelegate = (AppDelegate *)(UIApplication.sharedApplication.delegate); 488 489 NSManagedObjectContext *context =[appDelegate managedObjectContext]; 490 491 User *user = [self fetchUser]; 492 if (user) { 493 return; 494 } 495 user = [NSEntityDescription insertNewObjectForEntityForName:@"User" 496 inManagedObjectContext:context]; 497 user.email = CoreDataEmail; 498 user.password = CoreDataPassword; 499 NSError *error; 500 if (![context save:&error]) { 501 NSLog(@"Error in saving data: %@", [error localizedDescription]); 502 503 }else{ 504 NSLog(@"data stored in core data"); 505 } 506 } 507 ``` 508 509 ### YapDatabase 510 511 [YapDatabase](https://github.com/yapstudios/YapDatabase) is a key/value store built on top of SQLite.\ 512 As the Yap databases are sqlite databases you can find them using the purposed commend in the previous section. 513 514 ### Other SQLite Databases 515 516 It's common for applications to create their own sqlite database. They may be **storing** **sensitive** **data** on them and leaving it unencrypted. Therefore, it's always interesting to check every database inside the applications directory. Therefore go to the application directory where the data is saved (`/private/var/mobile/Containers/Data/Application/{APPID}`) 517 518 ```bash 519 find ./ -name "*.sqlite" -or -name "*.db" 520 ``` 521 522 ### Firebase Real-Time Databases 523 524 Developers are enabled to **store and sync data** within a **NoSQL cloud-hosted database** through Firebase Real-Time Databases. Stored in JSON format, the data gets synchronized to all connected clients in real time. 525 526 You can find how to check for misconfigured Firebase databases here: 527 528 529 [Firebase Database](/hacktricks/network-services-pentesting/pentesting-web/buckets/firebase-database) 530 531 ### Realm databases 532 533 [Realm Objective-C](https://realm.io/docs/objc/latest/) and [Realm Swift](https://realm.io/docs/swift/latest/) offer a powerful alternative for data storage, not provided by Apple. By default, they **store data unencrypted**, with encryption available through specific configuration. 534 535 The databases are located at: `/private/var/mobile/Containers/Data/Application/{APPID}`. To explore these files, one can utilize commands like: 536 537 ```bash 538 iPhone:/private/var/mobile/Containers/Data/Application/A079DF84-726C-4AEA-A194-805B97B3684A/Documents root# ls 539 default.realm default.realm.lock default.realm.management/ default.realm.note| 540 541 $ find ./ -name "*.realm*" 542 ``` 543 544 For viewing these database files, the [**Realm Studio**](https://github.com/realm/realm-studio) tool is recommended. 545 546 To implement encryption within a Realm database, the following code snippet can be used: 547 548 ```swift 549 // Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server 550 let config = Realm.Configuration(encryptionKey: getKey()) 551 do { 552 let realm = try Realm(configuration: config) 553 // Use the Realm as normal 554 } catch let error as NSError { 555 // If the encryption key is wrong, `error` will say that it's an invalid database 556 fatalError("Error opening realm: \(error)") 557 } 558 ``` 559 560 ### Couchbase Lite Databases 561 562 [Couchbase Lite](https://github.com/couchbase/couchbase-lite-ios) is described as a **lightweight** and **embedded** database engine that follows the **document-oriented** (NoSQL) approach. Designed to be native to **iOS** and **macOS**, it offers the capability to sync data seamlessly. 563 564 To identify potential Couchbase databases on a device, the following directory should be inspected: 565 566 ```bash 567 ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/ 568 ``` 569 570 ### Cookies 571 572 iOS store the cookies of the apps in the **`Library/Cookies/cookies.binarycookies`** inside each apps folder. However, developers sometimes decide to save them in the **keychain** as the mentioned **cookie file can be accessed in backups**. 573 574 To inspect the cookies file you can use [**this python script**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) or use objection's **`ios cookies get`.**\ 575 **You can also use objection to** convert these files to a JSON format and inspect the data. 576 577 ```bash 578 ...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json 579 [ 580 { 581 "domain": "highaltitudehacks.com", 582 "expiresDate": "2051-09-15 07:46:43 +0000", 583 "isHTTPOnly": "false", 584 "isSecure": "false", 585 "name": "username", 586 "path": "/", 587 "value": "admin123", 588 "version": "0" 589 } 590 ] 591 ``` 592 593 ### Cache 594 595 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 n**ormal SQLite database**. 596 597 It is **recommended to disable Caching this data**, as it may contain sensitive information in the request or response. The following list below shows different ways of achieving this: 598 599 1. It is recommended to remove Cached responses after logout. This can be done with the provided method by Apple called [`removeAllCachedResponses`](https://developer.apple.com/documentation/foundation/urlcache/1417802-removeallcachedresponses) You can call this method as follows: 600 601 `URLCache.shared.removeAllCachedResponses()` 602 603 This method will remove all cached requests and responses from Cache.db file. 604 605 2. If you don't need to use the advantage of cookies it would be recommended to just use the [.ephemeral](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral) configuration property of URLSession, which will disable saving cookies and Caches. 606 607 [Apple documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral): 608 609 `An ephemeral session configuration object is similar to a default session configuration (see default), except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM. The only time an ephemeral session writes data to disk is when you tell it to write the contents of a URL to a file.` 610 611 3. Cache can be also disabled by setting the Cache Policy to [.notAllowed](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/notallowed). It will disable storing Cache in any fashion, either in memory or on disk. 612 613 ### Snapshots 614 615 Whenever you press the home button, iOS **takes a snapshot of the current screen** to be able to do the transition to the application on a much smoother way. However, if **sensitive** **data** is present in the current screen, it will be **saved** in the **image** (which **persists** **across** **reboots**). These are the snapshots that you can also access double tapping the home screen to switch between apps. 616 617 Unless the iPhone is jailbroken, the **attacker** needs to have **access** to the **device** **unblocked** to see these screenshots. By default the last snapshot is stored in the application's sandbox in `Library/Caches/Snapshots/` or `Library/SplashBoard/Snapshots` folder (the trusted computers can' t access the filesystem from iOX 7.0). 618 619 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. 620 621 The following is a sample remediation method that will set a default screenshot. 622 623 Swift: 624 625 ```swift 626 private var backgroundImage: UIImageView? 627 628 func applicationDidEnterBackground(_ application: UIApplication) { 629 let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage")) 630 myBanner.frame = UIScreen.main.bounds 631 backgroundImage = myBanner 632 window?.addSubview(myBanner) 633 } 634 635 func applicationWillEnterForeground(_ application: UIApplication) { 636 backgroundImage?.removeFromSuperview() 637 } 638 ``` 639 640 Objective-C: 641 642 ```text 643 @property (UIImageView *)backgroundImage; 644 645 - (void)applicationDidEnterBackground:(UIApplication *)application { 646 UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"]; 647 self.backgroundImage = myBanner; 648 self.backgroundImage.bounds = UIScreen.mainScreen.bounds; 649 [self.window addSubview:myBanner]; 650 } 651 652 - (void)applicationWillEnterForeground:(UIApplication *)application { 653 [self.backgroundImage removeFromSuperview]; 654 } 655 ``` 656 657 This sets the background image to `overlayImage.png` whenever the application is backgrounded. It prevents sensitive data leaks because `overlayImage.png` will always override the current view. 658 659 ### Keychain 660 661 For accessing and managing the iOS keychain, tools like [**Keychain-Dumper**](https://github.com/ptoomey3/Keychain-Dumper) are available, suitable for jailbroken devices. Additionally, [**Objection**](https://github.com/sensepost/objection) provides the command `ios keychain dump` for similar purposes.<sup>[[2]](#references)</sup> 662 663 #### **Storing Credentials** 664 665 The **NSURLCredential** class is ideal for saving sensitive information directly in the keychain, bypassing the need for NSUserDefaults or other wrappers. To store credentials after login, the following Swift code is used:<sup>[[8]](#references)</sup> 666 667 ```swift 668 NSURLCredential *credential; 669 credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent]; 670 [[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace]; 671 ``` 672 673 To extract these stored credentials, Objection's command `ios nsurlcredentialstorage dump` is utilized. 674 675 ## **Custom Keyboards and Keyboard Cache** 676 677 With iOS 8.0 onwards, users can install custom keyboard extensions, which are manageable under **Settings > General > Keyboard > Keyboards**. While these keyboards offer extended functionality, they pose a risk of keystroke logging and transmitting data to external servers, though users are notified about keyboards requiring network access. Apps can, and should, restrict the use of custom keyboards for sensitive information entry.<sup>[[9]](#references)</sup> 678 679 **Security Recommendations:** 680 681 - It's advised to disable third-party keyboards for enhanced security. 682 - Be aware of the autocorrect and auto-suggestions features of the default iOS keyboard, which could store sensitive information in cache files located in `Library/Keyboard/{locale}-dynamic-text.dat` or `/private/var/mobile/Library/Keyboard/dynamic-text.dat`. These cache files should be regularly checked for sensitive data. Resetting the keyboard dictionary via **Settings > General > Reset > Reset Keyboard Dictionary** is recommended for clearing cached data. 683 - Intercepting network traffic can reveal whether a custom keyboard is transmitting keystrokes remotely. 684 685 ### **Preventing Text Field Caching** 686 687 The [UITextInputTraits protocol](https://developer.apple.com/reference/uikit/uitextinputtraits) offers properties to manage autocorrection and secure text entry, essential for preventing sensitive information caching. For example, disabling autocorrection and enabling secure text entry can be achieved with: 688 689 ```text 690 textObject.autocorrectionType = UITextAutocorrectionTypeNo; 691 textObject.secureTextEntry = YES; 692 ``` 693 694 Additionally, developers should ensure that text fields, especially those for entering sensitive information like passwords and PINs, disable caching by setting `autocorrectionType` to `UITextAutocorrectionTypeNo` and `secureTextEntry` to `YES`. 695 696 ```text 697 UITextField *textField = [[UITextField alloc] initWithFrame:frame]; 698 textField.autocorrectionType = UITextAutocorrectionTypeNo; 699 ``` 700 701 ## **Logs** 702 703 Debugging code often involves the use of **logging**. There's a risk involved as **logs may contain sensitive information**. Previously, in iOS 6 and earlier versions, logs were accessible to all apps, posing a risk of sensitive data leakage. **Now, applications are restricted to accessing only their logs**.<sup>[[10]](#references)</sup> 704 705 Despite these restrictions, an **attacker with physical access** to an unlocked device can still exploit this by connecting the device to a computer and **reading the logs**. It is important to note that logs remain on the disk even after the app's uninstallation. 706 707 To mitigate risks, it is advised to **thoroughly interact with the app**, exploring all its functionalities and inputs to ensure no sensitive information is being logged inadvertently. 708 709 When reviewing the app's source code for potential leaks, look for both **predefined** and **custom logging statements** using keywords such as `NSLog`, `NSAssert`, `NSCAssert`, `fprintf` for built-in functions, and any mentions of `Logging` or `Logfile` for custom implementations. 710 711 ### **Monitoring System Logs** 712 713 Apps log various pieces of information which can be sensitive.<sup>[[11]](#references)</sup> To monitor these logs, tools and commands like: 714 715 ```bash 716 idevice_id --list # To find the device ID 717 idevicesyslog -u <id> (| grep <app>) # To capture the device logs 718 ``` 719 720 are useful. Additionally, **Xcode** provides a way to collect console logs: 721 722 1. Open Xcode. 723 2. Connect the iOS device. 724 3. Navigate to **Window** -> **Devices and Simulators**. 725 4. Select your device. 726 5. Trigger the issue you're investigating. 727 6. Use the **Open Console** button to view logs in a new window. 728 729 For more advanced logging, connecting to the device shell and using **socat** can provide real-time log monitoring: 730 731 ```bash 732 iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock 733 ``` 734 735 Followed by commands to observe log activities, which can be invaluable for diagnosing issues or identifying potential data leakage in logs. 736 737 ## Backups 738 739 **Auto-backup features** are integrated into iOS, facilitating the creation of device data copies through iTunes (up to macOS Catalina), Finder (from macOS Catalina onward), or iCloud. These backups encompass almost all device data, excluding highly sensitive elements like Apple Pay details and Touch ID configurations.<sup>[[12]](#references)</sup> 740 741 ### Security Risks 742 743 The inclusion of **installed apps and their data** in backups raises the issue of potential **data leakage** and the risk that **backup modifications could alter app functionality**. It's advised to **not store sensitive information in plaintext** within any app's directory or its subdirectories to mitigate these risks. 744 745 ### Excluding Files from Backups 746 747 Files in `Documents/` and `Library/Application Support/` are backed up by default. Developers can exclude specific files or directories from backups using `NSURL setResourceValue:forKey:error:` with the `NSURLIsExcludedFromBackupKey`. This practice is crucial for protecting sensitive data from being included in backups. 748 749 ### Testing for Vulnerabilities 750 751 To assess an app's backup security, start by **creating a backup** using Finder, then locate it using guidance from [Apple's official documentation](https://support.apple.com/en-us/HT204215). Analyze the backup for sensitive data or configurations that could be altered to affect app behavior. 752 753 Sensitive information can be sought out using command-line tools or applications like [iMazing](https://imazing.com). For encrypted backups, the presence of encryption can be confirmed by checking the "IsEncrypted" key in the "Manifest.plist" file at the backup's root. 754 755 ```xml 756 <?xml version="1.0" encoding="UTF-8"?> 757 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 758 <plist version="1.0"> 759 ... 760 <key>Date</key> 761 <date>2021-03-12T17:43:33Z</date> 762 <key>IsEncrypted</key> 763 <true/> 764 ... 765 </plist> 766 ``` 767 768 For dealing with encrypted backups, Python scripts available in [DinoSec's GitHub repo](https://github.com/dinosec/iphone-dataprotection/tree/master/python_scripts), like **backup_tool.py** and **backup_passwd.py**, may be useful, albeit potentially requiring adjustments for compatibility with the latest iTunes/Finder versions. The [**iOSbackup** tool](https://pypi.org/project/iOSbackup/) is another option for accessing files within password-protected backups. 769 770 ### Modifying App Behavior 771 772 An example of altering app behavior through backup modifications is demonstrated in the [Bither bitcoin wallet app](https://github.com/bither/bither-ios), where the UI lock PIN is stored within `net.bither.plist` under the **pin_code** key. Removing this key from the plist and restoring the backup removes the PIN requirement, providing unrestricted access. 773 774 ## Summary on Memory Testing for Sensitive Data 775 776 When dealing with sensitive information stored in an application's memory, it is crucial to limit the exposure time of this data. There are two primary approaches to investigate memory content: **creating a memory dump** and **analyzing the memory in real time**. Both methods have their challenges, including the potential to miss critical data during the dump process or analysis.<sup>[[13]](#references)</sup> 777 778 ## **Retrieving and Analyzing a Memory Dump** 779 780 For both jailbroken and non-jailbroken devices, tools like [objection](https://github.com/sensepost/objection) and [Fridump](https://github.com/Nightbringer21/fridump) allow for the dumping of an app's process memory. Once dumped, analyzing this data requires various tools, depending on the nature of the information you're searching for. 781 782 To extract strings from a memory dump, commands such as `strings` or `rabin2 -zz` can be used: 783 784 ```bash 785 # Extracting strings using strings command 786 $ strings memory > strings.txt 787 788 # Extracting strings using rabin2 789 $ rabin2 -ZZ memory > strings.txt 790 ``` 791 792 For more detailed analysis, including searching for specific data types or patterns, **radare2** offers extensive search capabilities: 793 794 ```bash 795 $ r2 <name_of_your_dump_file> 796 [0x00000000]> /? 797 ... 798 ``` 799 800 ## **Runtime Memory Analysis** 801 802 **r2frida** provides a powerful alternative for inspecting an app's memory in real time, without needing a memory dump. This tool enables the execution of search commands directly on the running application's memory: 803 804 ```bash 805 $ r2 frida://usb//<name_of_your_app> 806 [0x00000000]> /\ <search_command> 807 ``` 808 809 ## Broken Cryptography 810 811 ### Poor Key Management Processes 812 813 Some developers save sensitive data in the local storage and encrypt it with a key hardcoded/predictable in the code. This shouldn't be done as some reversing could allow attackers to extract the confidential information. 814 815 ### Use of Insecure and/or Deprecated Algorithms 816 817 During an iOS review, flag RC4, MD4, MD5, and SHA-1 when they are used for authorization or to protect stored or transmitted data. Password storage should use a unique salt and a deliberately expensive password KDF rather than a fast general-purpose digest. 818 819 ### Check 820 821 The main checks are whether the code contains **hardcoded** or **predictable** passwords and secrets, and whether it uses **weak cryptographic algorithms**. 822 823 It's interesting to know that you can **monitor** some **crypto** **libraries** automatically using **objection** with: 824 825 ```swift 826 ios monitor crypt 827 ``` 828 829 For **more information** about iOS cryptographic APIs and libraries, see the [OWASP iOS cryptography testing guide](https://mas.owasp.org/MASTG/0x06e-Testing-Cryptography/).<sup>[[29]](#references)</sup> 830 831 ## Local Authentication 832 833 **Local authentication** plays a crucial role, especially when it concerns safeguarding access at a remote endpoint through cryptographic methods. The essence here is that without proper implementation, local authentication mechanisms can be circumvented.<sup>[[14]](#references)</sup> 834 835 Apple's [**Local Authentication framework**](https://developer.apple.com/documentation/localauthentication) and the [**keychain**](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html) provide robust APIs for developers to facilitate user authentication dialogs and securely handle secret data, respectively. The Secure Enclave secures fingerprint ID for Touch ID, whereas Face ID relies on facial recognition without compromising biometric data. 836 837 To integrate Touch ID/Face ID, developers have two API choices: 838 839 - **`LocalAuthentication.framework`** for high-level user authentication without access to biometric data. 840 - **`Security.framework`** for lower-level keychain services access, securing secret data with biometric authentication. Various [open-source wrappers](https://www.raywenderlich.com/147308/secure-ios-user-data-keychain-touch-id) make keychain access simpler. 841 842 > [!CAUTION] 843 > However, both `LocalAuthentication.framework` and `Security.framework` present vulnerabilities, as they primarily return boolean values without transmitting data for authentication processes, making them susceptible to bypassing (refer to [Don't touch me that way, by David Lindner et al](https://www.youtube.com/watch?v=XhXIHVGCFFM)). 844 845 ### Implementing Local Authentication 846 847 To prompt users for authentication, developers should utilize the **`evaluatePolicy`** method within the **`LAContext`** class, choosing between: 848 849 - **`deviceOwnerAuthentication`**: Prompts for Touch ID or device passcode, failing if neither is enabled. 850 - **`deviceOwnerAuthenticationWithBiometrics`**: Exclusively prompts for Touch ID. 851 852 A successful authentication is indicated by a boolean return value from **`evaluatePolicy`**, highlighting a potential security flaw. 853 854 ### Local Authentication using Keychain 855 856 Implementing **local authentication** in iOS apps involves the use of **keychain APIs** to securely store secret data such as authentication tokens. This process ensures that the data can only be accessed by the user, using their device passcode or biometric authentication like Touch ID. 857 858 The keychain offers the capability to set items with the `SecAccessControl` attribute, which restricts access to the item until the user successfully authenticates via Touch ID or device passcode. This feature is crucial for enhancing security. 859 860 Below are code examples in Swift and Objective-C demonstrating how to save and retrieve a string to/from the keychain, leveraging these security features. The examples specifically show how to set up access control to require Touch ID authentication and ensure the data is accessible only on the device it was set up on, under the condition that a device passcode is configured. 861 862 ### Swift 863 ```swift 864 // From https://github.com/mufambisi/owasp-mstg/blob/master/Document/0x06f-Testing-Local-Authentication.md 865 866 // 1. create AccessControl object that will represent authentication settings 867 868 var error: Unmanaged<CFError>? 869 870 guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, 871 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, 872 SecAccessControlCreateFlags.biometryCurrentSet, 873 &error) else { 874 // failed to create AccessControl object 875 876 return 877 } 878 879 // 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute 880 881 var query: [String: Any] = [:] 882 883 query[kSecClass as String] = kSecClassGenericPassword 884 query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString 885 query[kSecAttrAccount as String] = "OWASP Account" as CFString 886 query[kSecValueData as String] = "test_strong_password".data(using: .utf8)! as CFData 887 query[kSecAttrAccessControl as String] = accessControl 888 889 // 3. save item 890 891 let status = SecItemAdd(query as CFDictionary, nil) 892 893 if status == noErr { 894 // successfully saved 895 } else { 896 // error while saving 897 } 898 ``` 899 900 ### Objective-C 901 ```text 902 // 1. create AccessControl object that will represent authentication settings 903 CFErrorRef *err = nil; 904 905 SecAccessControlRef sacRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, 906 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, 907 kSecAccessControlUserPresence, 908 err); 909 910 // 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute 911 NSDictionary* query = @{ 912 (_ _bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, 913 (__bridge id)kSecAttrLabel: @"com.me.myapp.password", 914 (__bridge id)kSecAttrAccount: @"OWASP Account", 915 (__bridge id)kSecValueData: [@"test_strong_password" dataUsingEncoding:NSUTF8StringEncoding], 916 (__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacRef 917 }; 918 919 // 3. save item 920 OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, nil); 921 922 if (status == noErr) { 923 // successfully saved 924 } else { 925 // error while saving 926 } 927 ``` 928 929 930 Now we can request the saved item from the keychain. Keychain services will present the authentication dialog to the user and return data or nil depending on whether a suitable fingerprint was provided or not. 931 932 ### Swift 933 ```swift 934 // 1. define query 935 var query = [String: Any]() 936 query[kSecClass as String] = kSecClassGenericPassword 937 query[kSecReturnData as String] = kCFBooleanTrue 938 query[kSecAttrAccount as String] = "My Name" as CFString 939 query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString 940 query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString 941 942 // 2. get item 943 var queryResult: AnyObject? 944 let status = withUnsafeMutablePointer(to: &queryResult) { 945 SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) 946 } 947 948 if status == noErr { 949 let password = String(data: queryResult as! Data, encoding: .utf8)! 950 // successfully received password 951 } else { 952 // authorization not passed 953 } 954 ``` 955 956 ### Objective-C 957 ```text 958 // 1. define query 959 NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, 960 (__bridge id)kSecReturnData: @YES, 961 (__bridge id)kSecAttrAccount: @"My Name1", 962 (__bridge id)kSecAttrLabel: @"com.me.myapp.password", 963 (__bridge id)kSecUseOperationPrompt: @"Please, pass authorisation to enter this area" }; 964 965 // 2. get item 966 CFTypeRef queryResult = NULL; 967 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &queryResult); 968 969 if (status == noErr){ 970 NSData* resultData = ( __bridge_transfer NSData* )queryResult; 971 NSString* password = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding]; 972 NSLog(@"%@", password); 973 } else { 974 NSLog(@"Something went wrong"); 975 } 976 ``` 977 978 979 ### Detection 980 981 Usage of frameworks in an app can also be detected by analyzing the app binary's list of shared dynamic libraries. This can be done by using `otool`: 982 983 ```bash 984 $ otool -L <AppName>.app/<AppName> 985 ``` 986 987 If `LocalAuthentication.framework` is used in an app, the output will contain both of the following lines (remember that `LocalAuthentication.framework` uses `Security.framework` under the hood): 988 989 ```bash 990 /System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication 991 /System/Library/Frameworks/Security.framework/Security 992 ``` 993 994 If `Security.framework` is used, only the second one will be shown. 995 996 ### Local Authentication Framework Bypass 997 998 #### **Objection** 999 1000 Through the **Objection Biometrics Bypass**, located at [this GitHub page](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass), a technique is available for overcoming the **LocalAuthentication** mechanism. The core of this approach involves leveraging **Frida** to manipulate the `evaluatePolicy` function, ensuring it consistently yields a `True` outcome, irrespective of the actual authentication success. This is particularly useful for circumventing flawed biometric authentication processes. 1001 1002 To activate this bypass, the following command is employed: 1003 1004 ```bash 1005 ...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios ui biometrics_bypass 1006 (agent) Registering job 3mhtws9x47q. Type: ios-biometrics-disable 1007 ...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # (agent) [3mhtws9x47q] Localized Reason for auth requirement: Please authenticate yourself 1008 (agent) [3mhtws9x47q] OS authentication response: false 1009 (agent) [3mhtws9x47q] Marking OS response as True instead 1010 (agent) [3mhtws9x47q] Biometrics bypass hook complete 1011 ``` 1012 1013 This command sets off a sequence where Objection registers a task that effectively alters the outcome of the `evaluatePolicy` check to `True`. 1014 1015 #### Frida 1016 1017 An example of a use of **`evaluatePolicy`** from [DVIA-v2 application](https://github.com/prateek147/DVIA-v2):<sup>[[22]](#references)</sup> 1018 1019 ```swift 1020 +(void)authenticateWithTouchID { 1021 LAContext *myContext = [[LAContext alloc] init]; 1022 NSError *authError = nil; 1023 NSString *myLocalizedReasonString = @"Please authenticate yourself"; 1024 1025 if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) { 1026 [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics 1027 localizedReason:myLocalizedReasonString 1028 reply:^(BOOL success, NSError *error) { 1029 if (success) { 1030 dispatch_async(dispatch_get_main_queue(), ^{ 1031 [TouchIDAuthentication showAlert:@"Authentication Successful" withTitle:@"Success"]; 1032 }); 1033 } else { 1034 dispatch_async(dispatch_get_main_queue(), ^{ 1035 [TouchIDAuthentication showAlert:@"Authentication Failed !" withTitle:@"Error"]; 1036 }); 1037 } 1038 }]; 1039 } else { 1040 dispatch_async(dispatch_get_main_queue(), ^{ 1041 [TouchIDAuthentication showAlert:@"Your device doesn't support Touch ID or you haven't configured Touch ID authentication on your device" withTitle:@"Error"]; 1042 }); 1043 } 1044 } 1045 ``` 1046 1047 To achieve the **bypass** of Local Authentication, a Frida script is written. This script targets the **evaluatePolicy** check, intercepting its callback to ensure it returns **success=1**. By altering the callback's behavior, the authentication check is effectively bypassed.<sup>[[15]](#references)</sup> 1048 1049 The script below is injected to modify the result of the **evaluatePolicy** method. It changes the callback's result to always indicate success.<sup>[[28]](#references)</sup> 1050 1051 ```swift 1052 // from https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/ 1053 if(ObjC.available) { 1054 console.log("Injecting..."); 1055 var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"]; 1056 Interceptor.attach(hook.implementation, { 1057 onEnter: function(args) { 1058 var block = new ObjC.Block(args[4]); 1059 const callback = block.implementation; 1060 block.implementation = function (error, value) { 1061 1062 console.log("Changing the result value to true") 1063 const result = callback(1, null); 1064 return result; 1065 }; 1066 }, 1067 }); 1068 } else { 1069 console.log("Objective-C Runtime is not available!"); 1070 } 1071 ``` 1072 1073 To inject the Frida script and bypass the biometric authentication, the following command is used: 1074 1075 ```bash 1076 frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js 1077 ``` 1078 1079 ## Sensitive Functionality Exposure Through IPC 1080 1081 ### Custom URI Handlers / Deeplinks / Custom Schemes 1082 1083 1084 [Ios Custom Uri Handlers Deeplinks Custom Schemes](/hacktricks/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes) 1085 1086 ### Universal Links 1087 1088 1089 [Ios Universal Links](/hacktricks/mobile-pentesting/ios-pentesting/ios-universal-links) 1090 1091 ### UIActivity Sharing 1092 1093 1094 [Ios Uiactivity Sharing](/hacktricks/mobile-pentesting/ios-pentesting/ios-uiactivity-sharing) 1095 1096 ### UIPasteboard 1097 1098 1099 [Ios Uipasteboard](/hacktricks/mobile-pentesting/ios-pentesting/ios-uipasteboard) 1100 1101 ### App Extensions 1102 1103 1104 [Ios App Extensions](/hacktricks/mobile-pentesting/ios-pentesting/ios-app-extensions) 1105 1106 ### WebViews 1107 1108 1109 [Ios Webviews](/hacktricks/mobile-pentesting/ios-pentesting/ios-webviews) 1110 1111 ### Serialisation and Encoding 1112 1113 1114 [Ios Serialisation And Encoding](/hacktricks/mobile-pentesting/ios-pentesting/ios-serialisation-and-encoding) 1115 1116 ## Network Communication 1117 1118 ### BLE application protocols 1119 1120 For iOS applications using BLE mesh transports, see the application-protocol cache-poisoning methodology: 1121 1122 [Pentesting Ble Bluetooth Low Energy.Md#Ble Mesh And Gossip Protocol Cache Poisoning](../../todo/radio-hacking/pentesting-ble-bluetooth-low-energy.md%23ble-mesh-and-gossip-protocol-cache-poisoning) 1123 1124 It's important to check that no communication is occurring **without encryption** and also that the application is correctly **validating the TLS certificate** of the server.\ 1125 To check these kind of issues you can use a proxy like **Burp**: 1126 1127 1128 [Burp Configuration For Ios](/hacktricks/mobile-pentesting/ios-pentesting/burp-configuration-for-ios) 1129 1130 ### Hostname check 1131 1132 One common issue validating the TLS certificate is to check that the certificate was signed by a **trusted** **CA**, but **not check** if **the hostname** of the certificate is the hostname being accessed.\ 1133 In order to check this issue using Burp, after trusting Burp CA in the iPhone, you can **create a new certificate with Burp for a different hostname** and use it. If the application still works, then, something it's vulnerable. 1134 1135 ### Certificate Pinning 1136 1137 If an application is correctly using SSL Pinning, then the application will only works if the certificate is the once expected to be. When testing an application **this might be a problem as Burp will serve it's own certificate.**\ 1138 In order to bypass this protection inside a jailbroken device, you can install the application [**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2) or install [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)<sup>[[27]](#references)</sup> 1139 1140 You can also use **objection's** `ios sslpinning disable` 1141 1142 ## Misc 1143 1144 - In **`/System/Library`** you can find the frameworks installed in the phone used by system applications 1145 - The applications installed by the user from the App Store are located inside **`/User/Applications`** 1146 - And the **`/User/Library`** contains data saved by the user level applications 1147 - You can access **`/User/Library/Notes/notes.sqlite`** to read the notes saved inside the application. 1148 - Inside the folder of an installed application (**`/User/Applications/<APP ID>/`**) you can find some interesting files: 1149 - **`iTunesArtwork`**: The icon used by the app 1150 - **`iTunesMetadata.plist`**: Info of the app used in the App Store 1151 - **`/Library/*`**: Contains the preferences and cache. In **`/Library/Cache/Snapshots/*`** you can find the snapshot performed to the application before sending it to the background. 1152 1153 ### Hot Patching/Enforced Updating 1154 1155 Frameworks such as [**JSPatch**](https://github.com/bang590/JSPatch) have been used to deliver script-based patches to deployed installations without waiting for another App Store review. Update-enforcement libraries such as [Siren](https://github.com/ArtSabintsev/Siren) and [react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker) serve a different purpose: they detect or require a newer App Store version rather than hot-patching code.\ 1156 **A remote patch channel can change behavior across many installations quickly and can be abused by a malicious or compromised third-party SDK or update service. Identify each remote-update mechanism, test transport authenticity, payload integrity, signing and rollback behavior, and compare it with an older app version when possible.** 1157 1158 ### Third Parties 1159 1160 A significant challenge with **3rd party SDKs** is the **lack of granular control** over their functionalities. Developers are faced with a choice: either integrate the SDK and accept all its features, including potential security vulnerabilities and privacy concerns, or forego its benefits entirely. Often, developers are unable to patch vulnerabilities within these SDKs themselves. Furthermore, as SDKs gain trust within the community, some may start to contain malware. 1161 1162 The services provided by third-party SDKs may include user behavior tracking, advertisement displays, or user experience enhancements. However, this introduces a risk as developers may not be fully aware of the code executed by these libraries, leading to potential privacy and security risks. It's crucial to limit the information shared with third-party services to what is necessary and ensure that no sensitive data is exposed.<sup>[[16]](#references)</sup> 1163 1164 Implementation of third-party services usually comes in two forms: a standalone library or a full SDK. To protect user privacy, any data shared with these services should be **anonymized** to prevent the disclosure of Personal Identifiable Information (PII). 1165 1166 To identify the libraries an application uses, the **`otool`** command can be employed. This tool should be run against the application and each shared library it uses to discover additional libraries. 1167 1168 ```bash 1169 otool -L <application_path> 1170 ``` 1171 1172 ## Interesting Vulnerabilities & Case Studies 1173 1174 1175 [Air Keyboard Remote Input Injection](/hacktricks/mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection) 1176 1177 [Itunesstored Bookassetd Sandbox Escape](/hacktricks/mobile-pentesting/ios-pentesting/itunesstored-bookassetd-sandbox-escape) 1178 1179 [Zero Click Messaging Image Parser Chains](/hacktricks/mobile-pentesting/ios-pentesting/zero-click-messaging-image-parser-chains) 1180 1181 ## References 1182 1183 - [1] [Taking Apart iOS Apps: Anti-Debugging and Anti-Tampering in the Wild](https://blog.calif.io/p/taking-apart-ios-apps-anti-debugging) 1184 - [2] [OWASP MASTG – iOS Security Testing](https://mas.owasp.org/MASTG/0x06b-iOS-Security-Testing/) 1185 - [3] [iOS & Mobile App Pentesting - INE](https://my.ine.com/CyberSecurity/courses/089d060b/ios-mobile-app-pentesting) 1186 - [4] [OWASP MASTG-TECH-0057: Listing Installed Apps](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/) 1187 - [5] [OWASP MASTG-TECH-0058: Exploring the App Package](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0058/) 1188 - [6] [OWASP MASTG-TECH-0059: Accessing App Data Directories](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/) 1189 - [7] [OWASP MASTG – iOS Testing Data Storage](https://mas.owasp.org/MASTG/0x06d-Testing-Data-Storage/) 1190 - [8] [Storing password in keychain the smart way](https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way) 1191 - [9] [OWASP MASTG-TEST-0055: Finding Sensitive Data in the Keyboard Cache](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/) 1192 - [10] [OWASP MASTG-TEST-0053: Checking Logs for Sensitive Data](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053) 1193 - [11] [OWASP MASTG-TECH-0060: Monitoring System Logs](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/) 1194 - [12] [OWASP MASTG-TEST-0058: Testing Backups for Sensitive Data](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058) 1195 - [13] [OWASP MASTG-TEST-0060: Testing Memory for Sensitive Data](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060) 1196 - [14] [OWASP MASTG-TEST-0064: Testing Biometric Authentication](https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064) 1197 - [15] [Bypassing your apps' biometric checks on iOS](https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc) 1198 - [16] [OWASP MASTG-TEST-0054: Determining Whether Sensitive Data Is Shared with Third Parties](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054) 1199 - [17] [RE:iOS Apps – reverse engineering iOS applications course](https://github.com/ivRodriguezCA/RE-iOS-Apps/) 1200 - [18] [OWASP MASTG-TECH-0152 – Bypassing Jailbreak Detection](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0152/) 1201 - [19] [iPwn Apps: Pentesting iOS Applications](https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577) 1202 - [20] [iOS Application Penetration Testing for Beginners](https://www.slideshare.net/RyanISI/ios-appsecurityminicourse) 1203 - [21] [prateek147/DVIA – Damn Vulnerable iOS App (GitHub)](https://github.com/prateek147/DVIA) 1204 - [22] [prateek147/DVIA-v2 – Damn Vulnerable iOS App v2 (GitHub)](https://github.com/prateek147/DVIA-v2) 1205 - [23] [OWASP MSTG Hacking Playground (GitHub)](https://github.com/OWASP/MSTG-Hacking-Playground) 1206 - [24] [OWASP iGoat – Objective-C version (GitHub)](https://github.com/OWASP/igoat) 1207 - [25] [OWASP iGoat-Swift – Swift version (GitHub)](https://github.com/OWASP/iGoat-Swift) 1208 - [26] [WheresMyBrowser.iOS (GitHub)](https://github.com/authenticationfailure/WheresMyBrowser.iOS) 1209 - [27] [SSL Kill Switch 2 (GitHub)](https://github.com/nabla-c0d3/ssl-kill-switch2) 1210 - [28] [Mobile Pentesting 101 – Bypassing Biometric Authentication](https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/) 1211 - [29] [OWASP MASTG – iOS Testing Cryptography](https://mas.owasp.org/MASTG/0x06e-Testing-Cryptography/) 1212 - [30] [iOS (Swift) Anti-Jailbreak Bypass Using Frida – syrion (Internet Archive)](https://web.archive.org/web/20200514192843/https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/)