Some MiFit app analysis

Xiaomi MiBand data collection

I recently bought a Xiaomi MiBand, and after past episodes with RedMi sending smartphone’s IMEI to xiaomi.com I decided to test which data the app was giving away.

I used MiFit version 1.2.811 on Android 4.4.4 .

Internet Traffic

I used ProxyDroid and BurpSuite to sniff the outgoing traffic of the app and something interesting immediately came out:

HTTP requests (none with SSL/TLS) were made to different domains:

  • alog.umeng.com
  • apilocate.amap.com
  • api.developer.xiaomi.com

umeng.com

Umeng is a chinese company that provides mobile app data analytics, and to my great surprise is under the control of the Alibaba Holding .
I couldn’t exactly figure out which data it collects, but I guess that updates a remote “application log” via the company’s API at alog.umeng.co/app_log .
In its headers the request contained a X-Umeng-Sdk field with operating system version, app version and smartphone model.

amap.com

Amap is another chinese service providing web mapping and navigation, and is hosted on a Alibaba Hosting company.

Amap’s service is included in the Running Help section of the MiFit app. However, none of these requests happened while that activity was open.
So the app is simply fetching the position once in a while and sending an API request to apilocate.amap.com/mobile/binary.
The requests looked like this:

POST /mobile/binary HTTP/1.1
Accept-Encoding: gzip
gzipped: 1
X-INFO: H4sIAAAAAAAAAAFwAY/+JTNrVOyN3TWbyMxsoOGBH/20CClhkPPYpyq9AbZ42FU1tK1B6GsO8k2j4H28QC3sTVVdnKtt+twihbDtVhwBVaLLYQiKGtq3iQExiPBUvl4Gmc+xd8EnCtjplJHVfYoTcTqtmgX2u7q2OXx8P27P14Ocf8RwwvUcAQFLbgKpSd651oNfBOXmbS0nGhPmkyGTu4FBIUskJzAf4rfJgFRVBlqyoTkEAZl8phkIKyftmC21bK0RMGVL9LYmxzjmOA6hOB/dI58hdtEKaIPLVtjOrLpVkAO5NfQ7gRm10atfXcW3VOdKgYrVD6ibcT49jd+FHCaoDm2GdANFwo+a71VJW75QPsIij9UCgNLlaPMOKOyPC6Eq74Lh6ktNJq/mQMOjvsspLQyNKoi6zROghXA3ASbTuIC5BLCWl2RQuUe2nhGM6RuVxeLmlHAaCNtfvIcXMEdpXBRx59Bud0fxyix/IwIcBBTobNSA7Vgz1Ptv7xS3Z9+mcAEAAA==
X-BIZ: {“ex”:”bW9kPUdULUk5MTA1UCZzdj00LjQuNCZudD1XSUZJJm5wPUkgVElN”}
KEY: c0795b73d5df927742aac5b9a41ec327
ec: 1
User-Agent: AMAP Location SDK Android 1.3.0
ts: 1423501318915
scode: ef44b70e5fff971fb06b9642f6a11cb2
Content-Length: 221
Content-Type: application/octet-stream
Host: apilocate.amap.com
Proxy-Connection: close
Connection: close

I wasn’t able to determine the content of the X-INFO field (maybe it’s a string concatenation somehow formatted, let me know if someone finds out), but the X-BIZ field contains a base64 encoded string:

mod=GT-I9105P&sv=4.4.4&nt=WIFI&np=I TIM

that again contains smartphone model, software version, network traffic used and network provider info.
Unfortunately even if you do not accept to give GPS permissions to the app I guess it will take the approximate location based on Wi-Fi and GSM.
The app also creates an amap folder in the phone’s memory with the data necessary to draw the map (a series of .dat and .ind files).

api.developer.xiaomi.com

These requests happened when I opened the About section and checked for updates, so no surprises.

Reversing the apk

Using apktool I looked into the apk to find a correspondence with the findings above. AndroidManifest.xml showed the following:

[…]
<uses-permission android:name=”android.permission.REORDER_TASKS”/>
<uses-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW”/>
<uses-permission android:name=”android.permission.INTERNET”/>
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE”/>
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE”/>
<uses-permission android:name=”android.permission.CHANGE_WIFI_STATE”/>
<uses-permission android:name=”android.permission.BLUETOOTH”/>
<uses-permission android:name=”android.permission.BLUETOOTH_ADMIN”/>
<uses-permission android:name=”android.permission.VIBRATE”/>
<uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE”/>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
<uses-permission android:name=”android.permission.READ_PHONE_STATE”/>
<uses-permission android:name=”android.permission.GET_ACCOUNTS”/>
<uses-permission android:name=”com.xiaomi.permission.AUTH_SERVICE”/>
<uses-permission android:name=”android.permission.MOUNT_UNMOUNT_FILESYSTEMS”/>
<uses-permission android:name=”android.permission.READ_LOGS”/>
<uses-permission android:name=”android.permission.WAKE_LOCK”/>
<uses-permission android:name=”android.permission.WRITE_SETTINGS”/>
<uses-permission android:name=”android.permission.GET_TASKS”/>
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION”/>
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>
<uses-permission android:name=”android.permission.BROADCAST_STICKY”/>
<uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED”/>
<uses-permission android:name=”android.permission.CALL_PHONE”/>
<permission android:name=”com.xiaomi.hm.health.permission.MIPUSH_RECEIVE” android:protectionLevel=”signatureOrSystem”/>
<permission android:name=”com.xiaomi.hm.health.permission.CONFIG” android:protectionLevel=”signatureOrSystem”/>
<uses-permission android:name=”com.xiaomi.hm.health.permission.MIPUSH_RECEIVE”/>
<uses-permission android:name=”miui.permission.READ_STEPS”/><uses-permission android:name=”com.xiaomi.market.sdk.UPDATE”/><uses-permission android:name=”android.permission.CAMERA”/>
[…]
<service android:enabled=”true” android:name=”com.baidu.location.f” android:process=”:remote”/>
<meta-data android:name=”com.baidu.lbsapi.API_KEY” android:value=”dMGlsmpHOollXfGZ8jKfxxx”/>
<meta-data android:name=”com.amap.api.v2.apikey” android:value=”c0795b73d5df927742aac5b9a41ecxxx”/>
<meta-data android:name=”UMENG_APPKEY” android:value=”53eb6765fd98c559b7003xxx”/>
<meta-data android:name=”UMENG_CHANNEL” android:value=”Normal”/>
<meta-data android:name=”hm_channel” android:value=”Normal”/>
<meta-data android:name=”AA_DB_NAME” android:value=”mihealth.db”/>
<meta-data android:name=”AA_DB_VERSION” android:value=”1"/>
<meta-data android:name=”AA_MODELS” android:value=”cn.com.smartdevices.bracelet.weight.WeightInfo, cn.com.smartdevices.bracelet.weight.UserInfo”/>

Obviously the app has API keys to both Amap and Umeng, but also to Baidu’s lbsapi, that is the Baidu Maps API.
Some “health data” is apparently stored in mihealth.db but I couldn’t find it anywhere.
However, I found a locationCache in the com.xiaomi.hm.health folder in Android/data/ .
A hexdump showed that this cache uses libcore.io.DiskLruCache to store locally the location data fetched by the app :

I was blocking the access to geolocation while doing this, but we can identify the fields that would have been filled.
Despite this precaution I assure you that the location coordinates were quite accurate.

Conclusions

The MiFit app collects and sends data to third party companies without notification, without secure connections and without the user using any of the location tracking options.
But I bet it’s mentioned somewhere in the Privacy Policy …

It’s no surprise that apps are collecting data about the devices on which they run, but they should give a choice to users or at least allow them to understand under what conditions they’re using software.
I know there’s still someone who cares about what data he’s giving to who, and these people should pay close attention to any application is running on their devices. You can use software that limits data collection like PrivacyGuard on CyanogenMod, Xprivacy Xposed Module or edit system/etc/hosts to block certain domain names.