I was thinking a couple of weeks ago about additional vulnerabilities in iOS Mobile Device Management, and noticed a couple of problems that I had not considered before.
It may be possible for a malicious individual, whether an outside attacker or inside troublemaker, to forge fake responses to the MDM server. They could, it seems:
- Send the server fake TokenUpdate commands
- Send the server fake responses to real commands
In both cases, the attacker would need to know the UDID of the device they’re trying to impersonate.
The first case, a fake TokenUpdate command, could be used to sever the link between the server and the targeted device. By sending the command with a bogus DeviceToken, the MDM server would no longer be associated with the device, as the Push Notification system wouldn’t know where to send messages. Thus, the device whose UDID was used in the attack would no longer be managed by MDM.
An attacker who manages to collect UDIDs for multiple devices could thus mount a denial-of-service attack against the organization’s MDM server. Each and every targeted device would have to be manually re-enrolled with the server in order to resume management. For a large number of devices, this could be a costly effort, especially if the attack is repeated multiple times.
The second case is a bit more sneaky. If a user reconfigures their managed device to point to an MDM server of their own, they could essentially proxy the MDM protocol and send fake responses to the real server. By doing this, they could essentially create a “Potemkin” that would appear, to the corporate MDM server, to be properly in compliance with all policies, when in fact the device would simply ignore all MDM commands.
This seemed a little extreme to me. There must, I reasoned, be some way to prevent this from happening. So I dug a little deeper, and remembered the “Sign Messages” flag in the MDM enrollment payload. I’d experimented with this before, but discovered it had no effect on whether the client trusted the commands from the server.
As it turns out, I had it backwards — this flag isn’t for the server to sign messages to the client, but for the client, the remote device, to sign its messages back to the server. Exactly what I was looking for.
The exact mechanics are pretty simple:
- The client includes an “Mdm-Signature:” header in the HTTP PUT messages it sends to the server
- This signature is a base-64 encoded, .DER format, SMIME signature
- The content which is signed is not included in the signature, but is instead the content of the PUT itself — the message being sent to the MDM server
- Finally, it’s signed using the private Identity key that was sent to the device at MDM enrollment
So to prevent both these attacks, you must:
- Ensure the “Sign Messages” flag is set by the MDM server when enrolling device, and
- Ensure the server itself actually checks the validity of the signed messages, and rejects them if the signature is invalid
Note that it may be possible to extract the identity certificate and key from a device and set up the fake MDM proxy even with message signature validation enabled at the server — but I haven’t investigated this yet.
I’ve updated my test server with code that performs this check. You can find it on Github.
(view Archived Comments)