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]
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.