Baidu and Salmonads Saving IMEI on the Filesystem

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 i 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 Name | Version | MD5 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 Name | Version | MD5 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 |