Mobile devices are becoming more common in corporate environments. As a result, mobile device management solutions (MDM) have cropped up so that employers can remotely manage and wipe devices if necessary along with setting certain requirements that employees must comply with, such as setting a passcode, encrypting the device, and not jailbreaking or rooting the device. It’s certainly not a bad idea to enforce restrictions on devices that may contain sensitive information. However, bypassing some of the restrictions that an employer may put in place it not difficult. This is especially true if someone wants to keep their device rooted. There are many contenders in the sphere of MDM software. For this blog I will be looking at AirWatch for Android. The device I will be using is a rooted Nexus 4 running Android 4.2.2.
[Note Update at End of Post - 09.13.13]
Here is the default web interface for an AirWatch enrolled device. As you can see, my Nexus 4 is enrolled, is encrypted, and requires a passcode. However, it is still not compliant because my device has been “compromised,” i.e. rooted by myself. A poor word choice in my opinion. The same can be seen on the AirWatch agent.
If we navigate to the compliance section, we can see why we are not compliant.
Again, the agent shows that we are encrypted, but our device is “compromised.”
I decided to shelve looking for how AirWatch was detecting root for another day and instead I started focusing on the HTTP request and responses that the agent was sending and receiving. I started burp and setup a proxy on my Nexus 4. There is a fair amount of traffic that goes between the AirWatch agent and the server it’s talking to. One request in particular caught my eye.
This AirWatchBeacon checkin request. I omitted some of the more sensitive information in the request. As you can see there is an “IsCompromised” field in the request that is set as true. So I change that to false and sent the request off. After refreshing the web interface, my device is no longer compromised.
The agent also shows that my device is no longer compromised.
So now we know how the agent is checking into the server and whether or not your device is compromised. By changing a simple flag, we now control that. Furthermore, there doesn't seem to be any type of session information related with the request. We can replay the same request hours, even days later, and the server will accept it. The only downside now is that the agent will periodically do a check-in request with the server and report that the device is compromised. It’s a hassle to send a non-compromised request every time we want to be compliant. The first step I took in resolving this issue was to look at the AirWatch configuration options in its SQLite database.
Using the SQLite Editor app from the Android market, I open up the AirWatch database with root access.
Selecting the AirWatch database reveals a number of interesting tables.
The profileGroupSetting table is where most of the AirWatch configurations are stored.
There are a few rows that look interesting. The ones that contain interval in the name seem to set how often the AirWatch requests are sent. I tried changing the BeaconInterval to large values to see if it would take longer for the check in requests to be sent. That didn't seem to work. Neither did setting the value to zero or a negative value. For the most part, setting the interval values do not seem to do anything in my testing.
There is, however, another way to stop AirWatch from sending out request. Modifying the Android hosts file to block the host that the requests are being sent to. The Android hosts file is located in /system/etc/. Again, you have to be root to be able to modify the hosts file. I modified the hosts file to redirect the requested host to my localhost. The requested host is going to be different for every company, so I won’t be showing that. It’s been well over a week and my device has still not checked in and still shows that I’m compliant.
The only downside to not checking in often is that your device will show as not being seen for sometime. You employer may have a policy in place to remove devices that AirWatch shows as being inactive. One way to mitigate this is to periodically send out the checkin request yourself. Simply setting up a cronjob with curl to send out the checkin request work very well.
Here is the json POST request data the curl command uses for –d @request:
Finally add the bash script to your crontab by running “crontab –e” to edit the crontab and add the following at the end of the file:
This will cause the script to run every two hours. Conclusion
MDM solutions are great for employers to manage mobile devices. However, they are not without their problems. Not only was I able to bypass compliance for having a rooted device, but I was also able to bypass the need to encrypt my device from the profileGroupSetting table. Bypassing compliance restrictions for AirWatch is relatively trivial after a few hours and I’m sure it is probably similar with many others MDM solutions.
[Note Update at End of Post - 09.13.13]
Background
AirWatch is an MDM solution that provides employers with the ability to manage mobile devices and enforce policies. An agent is installed on the device and monitors whether the device is compliant or not for specific policies. If a device is found to be non-compliant, the agent phones home to a server, notifying the employer of a non-compliant device.Here is the default web interface for an AirWatch enrolled device. As you can see, my Nexus 4 is enrolled, is encrypted, and requires a passcode. However, it is still not compliant because my device has been “compromised,” i.e. rooted by myself. A poor word choice in my opinion. The same can be seen on the AirWatch agent.
If we navigate to the compliance section, we can see why we are not compliant.
Again, the agent shows that we are encrypted, but our device is “compromised.”
Digging Deeper
At this point I want to know how AirWatch is detecting that my phone is rooted. I tried removing the su binary and any superuser applications, but that didn’t seem to work. As a rooted phone, we can certainly grab the apk of the agent and tear it apart. That only revealed obfuscated java classes that would take a while to decipher. Next, I tried running strace against the agent process to get an idea of the calls that it is making, hoping that there would be something there that reveals what it is doing to detect root. Again, there weren’t any answers that I could find.I decided to shelve looking for how AirWatch was detecting root for another day and instead I started focusing on the HTTP request and responses that the agent was sending and receiving. I started burp and setup a proxy on my Nexus 4. There is a fair amount of traffic that goes between the AirWatch agent and the server it’s talking to. One request in particular caught my eye.
This AirWatchBeacon checkin request. I omitted some of the more sensitive information in the request. As you can see there is an “IsCompromised” field in the request that is set as true. So I change that to false and sent the request off. After refreshing the web interface, my device is no longer compromised.
The agent also shows that my device is no longer compromised.
So now we know how the agent is checking into the server and whether or not your device is compromised. By changing a simple flag, we now control that. Furthermore, there doesn't seem to be any type of session information related with the request. We can replay the same request hours, even days later, and the server will accept it. The only downside now is that the agent will periodically do a check-in request with the server and report that the device is compromised. It’s a hassle to send a non-compromised request every time we want to be compliant. The first step I took in resolving this issue was to look at the AirWatch configuration options in its SQLite database.
Using the SQLite Editor app from the Android market, I open up the AirWatch database with root access.
Selecting the AirWatch database reveals a number of interesting tables.
The profileGroupSetting table is where most of the AirWatch configurations are stored.
There are a few rows that look interesting. The ones that contain interval in the name seem to set how often the AirWatch requests are sent. I tried changing the BeaconInterval to large values to see if it would take longer for the check in requests to be sent. That didn't seem to work. Neither did setting the value to zero or a negative value. For the most part, setting the interval values do not seem to do anything in my testing.
There is, however, another way to stop AirWatch from sending out request. Modifying the Android hosts file to block the host that the requests are being sent to. The Android hosts file is located in /system/etc/. Again, you have to be root to be able to modify the hosts file. I modified the hosts file to redirect the requested host to my localhost. The requested host is going to be different for every company, so I won’t be showing that. It’s been well over a week and my device has still not checked in and still shows that I’m compliant.
The only downside to not checking in often is that your device will show as not being seen for sometime. You employer may have a policy in place to remove devices that AirWatch shows as being inactive. One way to mitigate this is to periodically send out the checkin request yourself. Simply setting up a cronjob with curl to send out the checkin request work very well.
#!/bin/bash
curl -X POST -d @request https:
//host/DeviceServices/AirWatchBeacon.svc/checkin -H "Content-Type: application/json" -H "User-Agent: AirWatch Agent/4.0.401/Android/4.2.2" -H "Host: host"
Here is the json POST request data the curl command uses for –d @request:
{
"payLoad"
:{
"FriendlyName"
:
"Android_sdNexus 4_353918050698915"
,
"Model"
:
"Nexus 4"
,
"CustomerLocationGroupRef"
:
"YourGroup"
,
"PhoneNumber"
:
"1111111111"
,
"DeviceType"
:5,
"C2dmToken"
:
"APA91bHcoJnegJy23fPaa2Fg2miP0vJEuC9aVcAw9iuwKb8AQcnzr7OyiXShrJSGD_AajBPUwuSm4Y_gcuz3ibnnjfbfpkLnAnoF599IM2yZhTVaUq0XWLKFfNP11oYzIavq4OjTO5DH4y3XpkvWmQBD16qkFJEg1BFFuOA2y1SJo6aE2yILIIo"
,
"IsCompromised"
:
"false"
,
"OsVersion"
:
"4.2.2"
,
"SerialNumber"
:
"1111111111"
,
"Name"
:
"Google occam"
,
"MacAddress"
:
"ff:ff:ff:ff:ff:ff"
,
"DeviceIdentifier"
:
"11111111111111"
,
"AWVersion"
:
"4.0.401"
,
"TransactionIdentifier"
:
"a8098ea5-a54e-412f-a911-a58920a24dc7"
}}
Finally add the bash script to your crontab by running “crontab –e” to edit the crontab and add the following at the end of the file:
0 */2 * * * /root/command.sh
This will cause the script to run every two hours. Conclusion
MDM solutions are great for employers to manage mobile devices. However, they are not without their problems. Not only was I able to bypass compliance for having a rooted device, but I was also able to bypass the need to encrypt my device from the profileGroupSetting table. Bypassing compliance restrictions for AirWatch is relatively trivial after a few hours and I’m sure it is probably similar with many others MDM solutions.
Post a Comment