We discussed the rampant collection of IMEI earlier, and actually we found something even stranger about apps so casually sending the IMEI: we noticed that a few apps were sending the IMEI to 3rd parties but they didn’t have the permission they needed to access it! This is definitely not supposed to happen. What’s going on? Could there be a security bug in Android that’s being exploited? Or maybe the app gets the IMEI from somewhere else (i.e., outside of the official Android APIs), maybe over the network? What we found, however, was that other apps were stashing the IMEI on the shared filesystem for other apps to find. The way that this works is that one app with the Baidu SDK that has permission to access the IMEI saves it to the shared filesystem, and then other one without the permission then reads it.

A covert channel is a way that two parties can talk and share information that’s somehow secret or not apparent. This channel allows colluding apps to work together to circumvent some security enforcement mechanism. Lots of covert channels can exist (and in exotic ways, such as two juxtaposed rack computers running fast and slow to measure the other’s temperature). For what we uncovered, however, the covert channel is nowhere near as sophisticated: it’s just a file stored on the phone’s shared filesystem (i.e., the SD card).

Apps using this covert channel are able to get around the permission system by having one app with access to lots of your data store it all so that another app—in particular, one without the needed permission—reads the data from the file and doesn’t even try to ask permission.  This allows, for example, Hong Kong Disneyland (produced by the Walt Disney Corporation) to send your phone’s IMEI to the Chinese media company Baidu while being able to falsely characterize itself as unable to access your IMEI.

How does this work in detail? Well, when an app is installed that has Baidu’s SDK included, it creates the following hidden file on the SD card:

/sdcard/backups/.SystemConfig/.cuid2

Its contents are a base64-encoded block like this:

vRWuhLnV2edm/DoGf9lKSTW69dDiZTqoV6cfw7nv2a7XcmE2zrU4RqlglrH6qfezs+qA4IENHG6u3dhmlY0yfg==

The problem is that this doesn’t decode to anything meaningful. It’s just a bunch of seemingly-random binary data, which means that it’s probably encrypted. So now it’s a matter of looking to see where the encryption is happening in the program. When we reverse engineered it, we found the encryption key conveniently written out for us:

Both the key and the initialization vector (IV) hard coded. We’ve mentioned not to do this before, but we should add here that the IV is suppose to be random each time! It defeats the point of having them if you hard code them! Anyways, the key (and IV) looks like 30212102dicudiab, except that there are two things wrong with it. First, if it is a hexadecimal string then it is only 64-bits long, which is too short to be an encryption key. Second, it has the letters i and u in it, which aren’t hexadecimal numerals. It turns out that Baidu also has the letters and u in it, and reading it backwards suggests Baidu has used this technique since 2012: baiducid20121203.

Baidu turns this ASCII string into an encryption key by taking the bytes of the ASCII string’s binary representation as the key, so the actual key (and IV) is 33303231323130326469637564696162 which it uses for 128-bit AES in CBC mode (i.e., AES_128_CBC). The 128-bit part is misleading, however, because while the key is 128-bits long, there aren’t 128-bits of effective security if you take the bytes of an alphanumeric string. And the CBC mode is misleading because of the use of fixed IVs. But still, it does technically use AES. One out of three points for Baidu!

The result of decrypting our example file contents is:

{“deviceid”:”your device id”,”imei”:”your imei”,”ver”:2}

Normally, this above example would have real identifiers. This example, however, corresponds to the base64 data above and was created ourselves. We chose to store this file on our SD card and then installed the Disney app on our phone, which then read and decrypted our file, and faithfully sent this alternative data to Baidu instead of our real IMEI. That’s how it’s possible for apps not holding the READ_PHONE_STATE permission to still send your IMEI to 3rd parties, or, in our case, the string “your imei.”

Baidu isn’t the only SDK engaged in this deceptive behaviour. Salmonads, who bill themselves as “a third party developers’ assistant platform in Greater China” also does the exact same thing—except that it doesn’t encrypt the file to help cover its tracks. It uses a hidden file it creates on the SD card:

/sdcard/.googlex9/.xamdecoq0962

And in that file, it stores—if it can access them—your advertising ID, your Android ID, your MAC address, and your IMEI. Other apps with the Salmonads SDK then read the file and send your personal identifiers to Salmonads’ servers when communicating. Again, we tested it by storing our own file on the SD card, which we populated with different values, and observed the app faithfully send it to api.salmonads.com.

For reference, here are the apps, version codes, and md5 hashes of the apps we saw sending the IMEI to Baidu without permission:

Package NameVersionMD5 hash
com.ape.weather3 713425 fe97c7fbd812e3ed6e9bcdc54b6501b1
com.asiabasehk.cgg.share.free 9 5cb534f94fec9256e10482edc3eca2ce
com.disney.hongkongdisneyland_goo 4102 b4ea6aa9ef686738e44e86ef0f4ee097
com.disney.hongkongdisneyland_goo 5 6d7da2c5d74ed1fffd31e541c07347c3
com.kapp.ifont 138 db54edd17cb74ac2b1ea60b28358be73
com.kapp.ifont 143 967b74f4b86f64fcb12dc1b6f7d976c1
com.p1.mobile.putong 181 7dc8d9d52b85f3a27f22e6701d048865
com.p1.mobile.putong 184 fd440a881e88175eba562a01cd7d16f4
com.p1.mobile.putong 186 71e12bf05c2efe0f8f8d341114813bc6
com.p1.mobile.putong 207 93de530aeccc0ae31a27e99a0ab177b0
com.p1.mobile.putong 220 ba2b57171df238e853cae446ebac7220
com.p1.mobile.putong 221 77dae19eb6588b0f9c7442cc05bbaa5f
com.p1.mobile.putong 230 e59a7c861a065892355fa62b845b9f32
com.p1.mobile.putong 241 0e9e258d6f7a640f13dd0f65b585fc9a
com.p1.mobile.putong 251 1d96c8fa982cad1a020cf96dfcef3742
com.p1.mobile.putong 258 d76d1b8c3e27c81f73b47387853004a4
photo.editor.polarr 16054902 57033a0b3b750d4e1b52d823764ff2e3

Here are the apps doing the same for Salmonads:

Package NameVersionMD5 hash
com.fotoable.faceswap.c403 48 557ec26cba7a30863b06921bfff95348
com.fotoable.faceswap.c403 50 4d67bb04e1aacf2cb41092185615108c
com.fotoable.faceswap.c403 55 152a06be2325145e9b3047df55091f14
com.fotoable.faceswap.c403 56 e3e546b1957b19b6a188be116f53d905
com.fotoable.faceswap.c403 58 6d74083add83b6313e83bcc2ae5785d9
com.fotoable.fotobeauty 177 481db944e552f9294f000b8826983e09
com.fotoable.fotobeauty 178 31d3794a23fb2e0e5063770d5efb4f6c
com.fotoable.selfieplus 71 e7af47f534e0851aa094c90dcd03b863
com.fotoable.selfieplus 72 8d2f258a939cd413f6070e9a2af1e530
com.wonder.pool.eightball 48 dc3de3338a7d4f872005cccbfa1c504e
com.words.game.wordcandy 42 098a2f06d3cf02153f6b995b47ce3073

Apps Using Side and Covert Channels