hacktricks/ios-pentesting/README.md

280 lines
14 KiB
Markdown
Raw Normal View History

# iOS Pentesting
## Privilege Separation and Sandbox
Applications the user can access run as the **mobile** user while critical system processes run as **root**.
However, the sandbox allows better control over actions that processes and applications can perform.
For example, even if two processes run as the same user \(mobile\), they are **not allowed to access or modify each other's data**.
Each application is installed under **`private/var/mobile/Applications/{random ID}`**
Once installed, applications have limited read access to some system areas and functions \(SMS, phone call...\). If an application wants to access a **protected area,** a **pop-up requesting permission** appears.
## Jailbreaking
Apple strictly requires that the code running on the iPhone must be **signed by a certificate issued by Apple**. **Jailbreaking** is the process of actively **circumventing such restrictions** and other security controls put in places by the OS. Therefore, once the device is jailbroken, the **integrity check** which is responsible for checking apps being installed is patched so it is **bypassed**.
{% hint style="info" %}
Unlike Android, **you cannot switch to "Developer Mode"** in iOS to run unsigned/untrusted code on the device.
{% endhint %}
The most important side effect of Jailbreaking is that it **removes any sandboxing put in place by the OS**. Therefore, any **app on the device can read any file** on the filesystem, including other apps files, cookies and keychain.
A jailbroken device allows users to **install unapproved apps** and leverage **more APIs**, which otherwise aren't accessible.
There are 2 types of jailbreaks:
* **Tethered**: Temporary jailbreak that requires the device to be connected to a computer every-time the device needs a restart. The jailbreak is reversed otherwise.
* **Untethered**: Rebooting the device does not reset the jailbreak.
**For regular users it's not recommended to jailbreak the mobile.
Note also that updating the OS removes the effect of jailbreaking.**
## **Simulator**
All the tools required to build and support an iOS app are **only officially supported on Mac OS**.
Apple's de facto tool for creating/debugging/instrumenting iOS applications is **Xcode**. It can be used to download other components such as **simulators** and different **SDK** **versions** required to build and **test** your app.
It's highly recommended to **download** Xcode from the **official app store**. Other versions may be carrying malware.
The simulator files can be found in `/Users/<username>/Library/Developer/CoreSimulator/Devices`
To open the simulator, run Xcode, then press in the _Xcode tab_ --&gt; _Open Developer tools_ --&gt; _Simulator_
In the following image clicking in "iPod touch \[...\]" you can select other device to test in:
![](../.gitbook/assets/image%20%28459%29.png)
![](../.gitbook/assets/image%20%28460%29.png)
2021-05-04 07:56:08 +00:00
### Applications in the Simulator
Inside `/Users/<username>/Library/Developer/CoreSimulator/Devices` you may find all the **installed simulators**. If you want to access the files of an application created inside one of the emulators it might be difficult to know **in which one the app is installed**. A quick way to **find the correct UID** is to execute the app in the simulator and execute:
```bash
xcrun simctl list | grep Booted
iPhone 8 (BF5DA4F8-6BBE-4EA0-BA16-7E3AFD16C06C) (Booted)
```
Once you know the UID the apps installed within it can be found in `/Users/<username>/Library/Developer/CoreSimulator/Devices/{UID}/data/Containers/Data/Application`
However, surprisingly you won't find the application here. You need to access `/Users/<username>/Library/Developer/Xcode/DerivedData/{Application}/Build/Products/Debug-iphonesimulator/`
And in this folder you can **find the package of the application.**
2021-04-27 09:44:49 +00:00
## Apple Developer Program
A **provisioning identity** is a collection of public and private keys that are associated an Apple developer account. In order to **sign apps** you need to pay **99$/year** to register in the **Apple Developer Program** to get your provisioning identity. Without this you won't be able to run applications from the source code in a physical device. Another option to do this is to use a **jailbroken device**.
Starting in Xcode 7.2 Apple has provided an option to create a **free iOS development provisioning profile** that allows to write and test your application on a real iPhone. Go to _Xcode_ --&gt; _Preferences_ --&gt; _Accounts_ --&gt; _+_ \(Add new Appli ID you your credentials\) --&gt; _Click on the Apple ID created_ --&gt; _Manage Certificates_ --&gt; _+_ \(Apple Development\) --&gt; _Done_
Then, in order to run your application in your iPhone you need first to **indicate the iPhone to trust the computer.** Then, you can try to **run the application in the mobile from Xcode,** but and error will appear. So go to _Settings_ --&gt; _General_ --&gt; _Profiles and Device Management_ --&gt; Select the untrusted profile and click "**Trust**".
Note that **applications signed by the same signing certificate can share resources on a secure manner, like keychain items**.
2021-05-04 07:56:08 +00:00
## Objective-C and Swift Basics
**Objecttive-C** has a **dynamic runtime**, so when an Objective-C program is executed in iOS, it calls libraries whose **address are resolved at runtime** by comparing the name of the function sent in the message against a list of all the function names available.
At the beginning, only apps created by Apple run the iPhones, so they had **access to everything** as they were **trusted**. However, when Apple **allowed** **third party applications,** Apple just removed the headers files of the powerful functions to "hide" them to developers. However, developers found that "safe" functions needed a few of these undocumented functions and just creating a **custom header file with the names of the undocumented functions, it was possible to invoke this powerful hidden functions.** Actually, Apple, before allowing an app to be published, check if the app calls any of these prohibited functions.
Then, Swift appeared. As **Swift is statically bound** \(it doesn't resolve the address of the functions in runtime like Objective-C\), it can be checked more easily the calls a Swift program is going to make via static code analysis.
2021-04-27 09:44:49 +00:00
## Obfuscation
Unlike an Android Application, the binary of an iOS app **can only be disassembled** and not decompiled.
When an application is submitted to the app store, Apple first verifies the app conduct and before releasing it to the app-store, **Apple encrypts the binary using** [**FairPlay**](https://developer.apple.com/streaming/fps/). So the binary download from the app store is encrypted complicating ting the reverse-engineering tasks.
2021-04-27 09:44:49 +00:00
However, note that there are other **third party software that can be used to obfuscate** the resulting binaries.
### Removing App Store Encryption
In order to run the encrypted binary, the device needs to decrypt it in memory. Then, it's possible to **dump the decrypted binary from the memory**.
First, check if the binary is compiled with the PIE \(Position Independent Code\) flag:
```bash
otool -Vh Original_App #Check the last word of the last line of this code
Home:
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 X86_64 ALL 0x00 EXECUTE 47 6080 NOUNDEFS DYLDLINK TWOLEVEL PIE
```
If it's set you can use the script [`change_macho_flags.py`](https://chromium.googlesource.com/chromium/src/+/49.0.2623.110/build/mac/change_mach_o_flags.py) to remove it with python2:
```bash
python change_mach_o_flags.py --no-pie Original_App
otool -Vh Hello_World
Hello_World:
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC ARM V7 0x00 EXECUTE 22 2356 NOUNDEFS DYLDLINK TWOLEVEL MH_NO_HEAP_EXECUTION
```
Now that the PIE flag isn't set, the OS will load the program at a **fixed starting location** every-time. In order to find this **location** you can use:
```bash
otool -l Original_App | grep -A 3 LC_SEGMENT | grep -A 1 __TEXT
segname __TEXT
2021-04-30 12:35:49 +00:00
vmaddr 0x00004000
```
Then, it's necessary to extract the the memory range that needs to be dumped:
```bash
otool -l Original_App | grep -A 4 LC_ENCRYPTION_INFO
cmd LC_ENCRYPTION_INFO
cmdsize 20
2021-04-30 12:35:49 +00:00
cryptoff 16384
cryptsize 17416192
cryptid 0
```
The value of **`cryptoff`** indicated the starting address of the encrypted content and the **`cryptsize`** indicates the size of the encrypted content.
So, the `start address` to dump will be `vmaddr + cryptoff` and the `end address` will be the `start address + cryptsize`
2021-04-30 12:35:49 +00:00
In this case: `start_address = 0x4000 + 0x4000 = 0x8000` __and `end_address = 0x8000 + 0x109c000 = 0x10a4000`
With this information it's just necessary to run the application in the jailbroken device, attach to the process with gdb \(`gdb -p <pid>`\) and dump the memory:
```bash
2021-04-30 12:35:49 +00:00
dump memory dump.bin 0x8000 0x10a4000
```
Congrats! You have decrypted the encrypted section in dump.bin. Now **transfer this dump to your computer and overwrite the encrypted section with the decrypted** one:
```bash
dd bs=1 seek=<starting_address> conv=notrunc if=dump.bin of=Original_App
```
There is one more step to complete. The application is still **indicating** in its metadata that it's **encrypted**, but it **isn't**. Then, when executed, the device will try to decrypt the already decrypted section and it's going to fail.
However, you can use tools like [**MachOView**](https://sourceforge.net/projects/machoview/) to change this info. Just open the binary and set the **cryptid** to 0:
![](../.gitbook/assets/image%20%28458%29.png)
### Removing App Store Encryption Automatically
You can use tools like [**Clutch**](https://github.com/KJCracks/Clutch) to automatically remove the encryption and an app.
2021-04-27 12:21:50 +00:00
## IPA Reversing
2021-05-04 07:56:08 +00:00
`.ipa` files are **zipped** **packages**, so you can change the extension to `.zip` and **decompress** them. A **complete** **packaged** app ready to be installed is commonly referred to as a **Bundle**.
After decompressing them you should see `<NAME>.app` , a zipped archive that contains the rest of the resources.
* **Info.plist**: A file that contains some of the application specific configurations.
* **Assets.car**: Another zipped archive that contains assets \(icons\).
* \*\*\*\*[**Core Data**](https://developer.apple.com/documentation/coredata): It is used to save your applications 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.
* \*\*\*\*[**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.
* **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.
There are multiple ways to define the UI in an iOS application: _storyboard_, _nib_ or _xib_ files.
2021-04-27 12:21:50 +00:00
### Plist
**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.
### Binary
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`**:
```bash
otool -Vh DVIA-v2 #Check some compilation attributes
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 ARM64 ALL 0x00 EXECUTE 65 7112 NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE
otool -L DVIA-v2 #Get third party libraries
DVIA-v2:
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.6.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
@rpath/Bolts.framework/Bolts (compatibility version 1.0.0, current version 1.0.0)
[...]
```
#### Check if the app is encrypted
See if there is any output for:
```bash
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
```
#### Disassembling the binary
Disassemble the text section:
```bash
otool -tV DVIA-v2
DVIA-v2:
(__TEXT,__text) section
+[DDLog initialize]:
0000000100004ab8 sub sp, sp, #0x60
0000000100004abc stp x29, x30, [sp, #0x50] ; Latency: 6
0000000100004ac0 add x29, sp, #0x50
0000000100004ac4 sub x8, x29, #0x10
0000000100004ac8 mov x9, #0x0
0000000100004acc adrp x10, 1098 ; 0x10044e000
0000000100004ad0 add x10, x10, #0x268
```
To print the **Objective-C segment** of the sample application one can use:
```bash
otool -oV DVIA-v2
DVIA-v2:
Contents of (__DATA,__objc_classlist) section
00000001003dd5b8 0x1004423d0 _OBJC_CLASS_$_DDLog
isa 0x1004423a8 _OBJC_METACLASS_$_DDLog
superclass 0x0 _OBJC_CLASS_$_NSObject
cache 0x0 __objc_empty_cache
vtable 0x0
data 0x1003de748
flags 0x80
instanceStart 8
```
In order to obtain a more compact Objective-C code you can use [**class-dump**](http://stevenygard.com/projects/class-dump/):
```bash
class-dump some-app
//
// Generated by class-dump 3.5 (64 bit).
//
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//
#pragma mark Named Structures
struct CGPoint {
double _field1;
double _field2;
};
struct CGRect {
struct CGPoint _field1;
struct CGSize _field2;
};
struct CGSize {
double _field1;
double _field2;
};
```
2021-04-27 12:21:50 +00:00
2021-05-04 07:56:08 +00:00
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/).
2021-04-27 12:21:50 +00:00
## Testing
2021-04-26 13:45:04 +00:00
### Storage Access
You can use [**iFunBox**](https://www.i-funbox.com/en/page-download.html) to access the all the storage inside an application sandbox/folder
{% hint style="info" %}
2021-04-26 13:45:04 +00:00
Starting in iOS version 8.4, Apple has **restricted the third-party managers to access to the application sandbox**, so tools like iFunbox and iExplorer no longer display/retrieve files from apps installed on the device if the device isn't jailbroken.
{% endhint %}
2021-04-26 12:11:14 +00:00
### Burp Proxy Configuration
{% page-ref page="burp-configuration-for-ios.md" %}
2021-04-27 12:21:50 +00:00
###
2021-04-26 12:11:14 +00:00