Let’s Talk About TikTok
Derek Banks //
I recently heard something on the news that caught my attention. I suppose that isn’t abnormal these days, but this in particular was the first time I had heard of anything like it. The US Government was considering banning a popular application in use on mobile devices. Not just on government devices, but for all Americans.
That app was TikTok. Now, I am old enough where I only kind of know what TikTok is, something about sharing video clips over social media or something, apparently my kids like it… something something, get off my lawn…
The alleged reason given for banning such an app was that it was sending data on US citizens to the Chinese government. The only thing close to this that I recall bubbling up to national news was a ban on Huawei devices for the same kind of fears.
Data privacy concerns and surveillance capitalism tactics are fascinating and complex topics that I think really deserve more attention. I think that at this point in time, most infosec professionals would answer “Yes” to the question “Do your apps and devices spy on you?” But to what extent?
The intention of this blog is not to answer that question, that would probably take an entire book, but rather to cover a few core skills on how one could get started on the journey of mobile device and Android application analysis and answer that question for themselves.
We will be sticking to passive kinds of analysis. For example, we will attempt to identify network traffic and API calls, but we will not be sending manipulated data to the API servers. We can look at the application and data on the device but should be really careful manipulating the application as it may do something unintended upstream. There is a time and place for that kind of testing, and generally involves authorization to test the application in some form (a pen test or bug bounty program for example).
As luck would have it, I own a rooted Google 6P which is a Huawei manufactured Android phone. I use it as a lab phone running Android 6.0 and Kali NetHunter and I use it mostly for Android application tests.
I thought it would be interesting to take a look at what the network traffic looks like from the device. And then afterward install TikTok and see what the communication looks like from it.
Device Baseline Analysis
To start, I wanted to see what remote hosts the phone attempted to connect to prior to installing TikTok. I configured a Raspberry Pi 4 device that was part of a dropbox project that I did with Beau Bullock and Ralph May as an access point so that I could perform a packet capture of the device traffic.
To get the WiFi access point running, I used a slightly modified version of the instructions David Fletcher published on our blog in 2017. Once the wireless access point was functional, I associated the phone to the network then shut it off. I then started tcpdump listening to the br0 interface and writing the packet capture out to file. Next, I booted up the phone and let it sit idle for an hour while the pcap ran. Note that there was not a SIM card in the phone, so it would not have an alternative but to use the WiFi access point. Note that there were no other devices associated with the access point.
There are many options to analyze pcaps. Wireshark is by far the most popular, and I use it quite a bit. I also like to use command-line tools a fair amount too as in my opinion, they are easier to generate data that can be further processed. One of the techniques I like to start with when analyzing any network traffic is long and short tail analysis. In other words, I like to see which hosts were communicated to the most, and which ones the least. This can be valuable at scale to find outliers in the data. Tshark (the command line equivalent of Wireshark), can be used to generate this type of analysis. First, we can look to see what DNS lookups were performed the most and the least by the device.
In our case, there were only 51 unique hosts, but there were still some interesting results. As expected, there were a lot of requests for Google hosts. It was, after all, a Google device and Operating system. It should be obvious to all tech folks in 2020 that Google constantly tracks your location and behavior, but that is a different topic for a different time. For this goal, I wanted to find something unexpected. So let’s run the same tshark command, but exclude “google” and “gstatic” as a term.
That gets the list of hosts down to 23. Looking at the output, I think we could safely remove ytimg.com (YouTube) and ntp.org from the suspicious list. Note that when I say suspicious list at this point of an analysis, I mean it warrants more investigation, not that I think it is malicious. Malicious needs to be proven in my opinion.
As someone who has used cloudfront.net for relaying malware communications in the past, the 48 lookups to d2to8y50b3n6dq.cloudfront.net stuck out to me as something I would want to investigate as an analyst, same with akamaized.net. I don’t consider it a good idea to assume all Content Delivery Network (CDN) traffic to be benign. Attackers want to hide in the noise and CDNs are a great place for that.
Using whois, the app-measurement.com domain appeared to be related to Google, so we can shelve that one for analysis purposes. Also, I had Instagram on the phone, so we can ignore the related domains there too. Though it is somewhat interesting that after a reboot, the device, without the Instagram app being opened, there are communication attempts to the related hosts (likely the APIs).
The xtrapath3.izatcloud.net domain appeared to be related to the Android operating system and the GPS configuration. So we’re on to these weird-looking DNS lookups:
- qiqgyezmfcqf.example.org
- oxxlgxxwtp.example.org
- jmnqdgx.example.org
- jmnqdgx
- qiqgyezmfcqf
- oxxlgxxwtp
They sure do look like they would be related to something malicious, right? Well, turns out, Chrome does this for a pretty good reason. Some ISPs will respond to unresolved DNS requests with a page they control. Often, these contain Ads. Often, ad servers spread malware, and at the very least, users probably don’t want to see the ads. Chrome will notice if these requests resolve the same A record and if so, block any corresponding ads. This would be expected behavior on an Android phone.
The lightstep-collector.api.ua.com and identity.api.ua.com domains appeared to be related to Under Armor based on the whois information. This can be explained since MapMyRun was installed on the device.
The insightapi.p3-group.com seemed harder to explain. The whois information was protected by domain privacy. Visiting the p3-group.com website, they appeared to be a tech consulting company, but the site was in WordPress, and while it looked “nice”, it’s really not hard to stand up fake content in a WordPress site. Not that I am saying it’s not legitimate, only that I couldn’t reasonably explain the traffic at this point of the analysis and thought it needed further looking into. We will put that in the suspicious bin.
The cdn.ampproject.com domain appeared to be related to Google and accelerating searches on mobile devices. That left the two reverse DNS lookups to 89.62.225.13 and 160.62.225.13. One seemed to be related to a telecom in Germany and a pharmaceutical company hosted at a german ISP. I’ve seen before where whois was not accurate, and an IP address was reassigned, but we will put that in the suspicious bin since it’s not easily explained.
So from all the DNS hosts, the list of hosts that need more investigation were:
- D2to8y50b3n6dq.cloudfront.net
- p3ins.akamized.net
- 89.62.225.13.in-addr.arpa
- 160.62.225.13.in-addr.arpa
For further investigation, we move to Wireshark and Burp Suite. Opening the pcap up in Wireshark we can use filters to find the two lookups we are interested in.
dns.qry.name == 160.62.225.13.in-addr.arpa
It appeared that both PTR records pointed to server-13-225-62-89.ewr53.r.cloudfront.net.
There was no other traffic to the IP addresses or the server-13-225-62-89.ewr53.r.cloudfront.net and addresses. I still think that the reverse lookups were strange, but without additional traffic, it’s difficult to say that malicious communication is happening. The next step would be to attempt to find a reference to the IP addresses on the file system of the device to see what they may be associated with. But we should run down the rest of the network traffic first.
Since we have the pcap open in Wireshark, let’s take a look at the protocol hierarchy and see if there are other protocols besides HTTP and TLS we should investigate. This can be found under the Statistics menu. It’s expected that the vast majority of the traffic from the phone will be HTTP and TLS, though I have seen in the past where other protocols were in use. In this case, HTTP, TLS, and ICMP appeared to be the only protocols we would want to investigate.
Aside from pinging the local network gateway, all of the ICMP traffic appeared to be ICMP Destination Port unreachable so not likely any kind of ICMP tunnel or other covert communications over ICMP.
At this point, we should start looking at HTTP/S traffic. The best way to do this in my opinion would be to set up Burp Suite Professional as an intercepting proxy. I suggest spending the money on the professional for any level of application testing as it is too valuable of a tool for the cost. However, the community version should also be fine for just analyzing the requests and responses, which is mostly what we will be using it for.
Once Burp Suite has launched, you will want to configure the proxy to listen on a network that the mobile device is also on because the default is the localhost address where Burp is running. Likely this is just the same WiFi network. This is found under the Options tab under the Proxy tab.
Configure a web browser (I recommend Firefox for web and application testing) on the system running Burp and configure it to use the proxy. A handy tool for switching between the proxy settings and no proxy in Firefox is the FoxyProxy Standard extension.
Once the browser is configured, visit http://burp and click CA Certificate to download the CA cert. Once downloaded, while you’re here, import the certificate into Firefox’s certificate store. This is found under Preferences and Privacy and Security. Click View Certificates, then Import and follow the prompts and select Use this certificate to identify websites.
Getting the mobile device proxied through Burp Suite can be a little bit trickier depending on the version of Android in use. There is a reason that I use Android 6.0 for testing whenever possible. Starting with Android 7.0, the OS no longer honors the user certificate store to identify websites. So using Android 6.0 for testing purposes is usually a bit easier.
To install the Burp Suite Certificate for Android 6.0:
- Configure browser to use Burp and visit http://burp
- Download cacert.der, rename to cacert.crt
- Adb push cacert.crt /mnt/sdcard/Download
- On device – Settings>Security>Install from Storage, select cacert.crt
If you are using Android 7.0 and higher, you will need to install the certificate as a system-level cert. The instructions here should help get you started.
From the phone, to set the proxy up, go to advanced options of the connected WiFi network, then select manual for proxy settings, then enter the IP address and port that was configured in Burp Suite.
Once my phone was communicating through Burp, I rebooted it to see if the same traffic from the pcap would show up in Burp. The D2to8y50b3n6dq.cloudfront.net domain appeared to be used to download a certificate store. There were two files downloaded, cdnconfig.zip and truststore.zip.
The contents of the zip files correspond to what the URL stated, that purpose was to download certificate store contents. This seemed to explain the D2to8y50b3n6dq.cloudfront.net and p3ins.akamized.net traffic. Though I am not entirely sure how this is being used on the device when it is downloaded, it did not appear to be malicious. However, I did not verify each CA in the truststore file. If this was a corporate device, that effort may be worthwhile.
At this point, I felt pretty comfortable that at least for the hour the packet capture was running, that there was no data being siphoned from the phone without my knowledge or some other kind of compromise or malware. Does this mean that I am 100% sure that something doesn’t check in to a command and control server once a day or once a month? Not at all, but I am fairly confident that the device isn’t actively compromised.
App Analysis
Now on to TikTok. Before installing it from the Google Play Store, I used ADB to list the installed packages on the phone.
adb shell ‘pm list packages –f’
I started doing this on app assessments, because sometimes the app isn’t named something obvious. Then I installed TikTok from the Play Store and tried to find it with ADB. Sure enough, it was not named anything related to TikTok.
I created two text lists and used Python to find the difference between them. The name of the app was com.zhiliaoapp.musically. Note that after the fact, I realized I totally forgot about the command line utility diff. I have had Python on the brain for the last few months, and when you have a hammer everything looks like a nail.
Next, I used ADB to locate the base APK and pull it from the device for static analysis using the following steps:
adb shell pm path com.zhiliaoapp.musically
adb pull /data/app/com.zhiliaoapp.musically-1/base.apk path/to/desired/destination
Once the APK file was copied off, I processed it in MobSF to get an overview of the app with automated static analysis. I like starting mobile application assessments with MobSF because it automates some tasks that I would otherwise need to perform manually.
The application appeared to be relatively complex with 16 exported activities, 22 exported services, 22 exported receivers, and 4 providers. An activity is a user interaction, sort of like an application on a Windows OS, where the user interacts with the application. A service is a background task to perform some kind of operation. Broadcast receivers send and receive messages to other Android apps or the Android OS. Content providers manage data by the app and help share data with other apps.
All of these were essentially the attack surface area of the application and could be manipulated in some unintended way. The best way to do that in my opinion is to use the Drozer framework.
It turned out that TikTok was a relatively large application, most of the Android apps I have analyzed in penetration tests have about a quarter of this size of attack surface area. Analyzing these in detail will have to be a later blog post because of the number of them and that they may not help us answer our original question – what, if any, personal data is being sent from the application?
MobSF can provide some interesting information along these lines, as it extracts permission information from the Android manifest. It can be difficult to ascertain if apps are overly permissive and if there are permissions granted that shouldn’t be necessary, but as with the size of exported intents, there were a lot of declared permissions. There were 67 declared permissions. In comparison to other apps I have analyzed, this was a relatively large amount.
PERMISSION | DESCRIPTION |
---|---|
android.permission.INTERNET | Allows an application to create network sockets. |
android.permission.ACCESS_NETWORK_STATE | Allows an application to view the status of all networks. |
android.permission.READ_EXTERNAL_STORAGE | Allows an application to read from SD Card. |
android.permission.WRITE_EXTERNAL_STORAGE | Allows an application to write to the SD card. |
android.permission.ACCESS_WIFI_STATE | Allows an application to view the information about the status of Wi-Fi. |
android.permission.CAMERA | Allows application to take pictures and videos with the camera. This allows the application to collect images that the camera is seeing at any time. |
android.permission.RECORD_AUDIO | Allows application to access the audio record path. |
android.permission.FLASHLIGHT | Allows the application to control the flashlight. |
android.permission.WAKE_LOCK | Allows an application to prevent the phone from going to sleep. |
android.permission.GET_TASKS | Allows application to retrieve information about currently and recently running tasks. May allow malicious applications to discover private information about other applications. |
android.permission.READ_CONTACTS | Allows an application to read all of the contact (address) data stored on your phone. Malicious applications can use this to send your data to other people. |
android.permission.RECEIVE_BOOT_COMPLETED | Allows an application to start itself as soon as the system has finished booting. This can make it take longer to start the phone and allow the application to slow down the overall phone by always running. |
none.used.ACCESS_FINE_LOCATION | Access fine location sources, such as the Global Positioning System on the phone, where available. Malicious applications can use this to determine where you are and may consume additional battery power. |
none.used.ACCESS_COARSE_LOCATION | Access coarse location sources, such as the mobile network database, to determine an approximate phone location, where available. Malicious applications can use this to determine approximately where you are. |
android.permission.VIBRATE | Allows the application to control the vibrator. |
com.meizu.c2dm.permission.RECEIVE | Unknown permission from android reference |
com.zhiliaoapp.musically.permission.READ_ACCOUNT | Unknown permission from android reference |
com.zhiliaoapp.musically.permission.WRITE_ACCOUNT | Unknown permission from android reference |
com.android.launcher.permission.INSTALL_SHORTCUT | Allows an application to install a shortcut in Launcher. |
com.android.launcher.permission.UNINSTALL_SHORTCUT | Don’t use this permission in your app. This permission is no longer supported. |
com.android.launcher.permission.READ_SETTINGS | Unknown permission from android reference |
android.permission.AUTHENTICATE_ACCOUNTS | Allows an application to use the account authenticator capabilities of the Account Manager, including creating accounts as well as obtaining and setting their passwords. |
com.htc.launcher.permission.READ_SETTINGS | Unknown permission from android reference |
com.lge.launcher.permission.READ_SETTINGS | Unknown permission from android reference |
com.lge.launcher.permission.WRITE_SETTINGS | Allows an application to modify the system’s settings data. Malicious applications can corrupt your system’s configuration. |
com.huawei.launcher3.permission.READ_SETTINGS | Unknown permission from android reference |
com.huawei.launcher3.permission.WRITE_SETTINGS | Allows an application to modify the system’s settings data. Malicious applications can corrupt your system’s configuration. |
com.huawei.launcher2.permission.READ_SETTINGS | Unknown permission from android reference |
com.huawei.launcher2.permission.WRITE_SETTINGS | Allows an application to modify the system’s settings data. Malicious applications can corrupt your system’s configuration. |
com.ebproductions.android.launcher.permission.READ_SETTINGS | Unknown permission from android reference |
com.ebproductions.android.launcher.permission.WRITE_SETTINGS | Allows an application to modify the system’s settings data. Malicious applications can corrupt your system’s configuration. |
com.oppo.launcher.permission.READ_SETTINGS | Unknown permission from android reference |
com.oppo.launcher.permission.WRITE_SETTINGS | Allows an application to modify the system’s settings data. Malicious applications can corrupt your system’s configuration. |
com.huawei.android.launcher.permission.READ_SETTINGS | Unknown permission from android reference |
com.huawei.android.launcher.permission.WRITE_SETTINGS | Allows an application to modify the system’s settings data. Malicious applications can corrupt your system’s configuration. |
dianxin.permission.ACCESS_LAUNCHER_DATA | Unknown permission from android reference |
com.miui.mihome2.permission.READ_SETTINGS | Unknown permission from android reference |
com.miui.mihome2.permission.WRITE_SETTINGS | Allows an application to modify the system’s settings data. Malicious applications can corrupt your system’s configuration. |
com.zhiliao.musically.livewallpaper.permission.wallpaperplugin | Unknown permission from android reference |
com.zhiliaoapp.musically.permission.MIPUSH_RECEIVE | Unknown permission from android reference |
com.zhiliaoapp.musically.push.permission.MESSAGE | Unknown permission from android reference |
com.android.vending.BILLING | Unknown permission from android reference |
com.meizu.flyme.push.permission.RECEIVE | Unknown permission from android reference |
android.permission.WRITE_SYNC_SETTINGS | Allows an application to modify the sync settings, such as whether sync is enabled for Contacts. |
com.sec.android.provider.badge.permission.READ | Unknown permission from android reference |
com.sec.android.provider.badge.permission.WRITE | Unknown permission from android reference |
com.htc.launcher.permission.UPDATE_SHORTCUT | Unknown permission from android reference |
com.sonyericsson.home.permission.BROADCAST_BADGE | Unknown permission from android reference |
com.sonymobile.home.permission.PROVIDER_INSERT_BADGE | Unknown permission from android reference |
com.majeur.launcher.permission.UPDATE_BADGE | Unknown permission from android reference |
com.huawei.android.launcher.permission.CHANGE_BADGE | Unknown permission from android reference |
android.permission.MODIFY_AUDIO_SETTINGS | Allows application to modify global audio settings, such as volume and routing. |
android.permission.REQUEST_INSTALL_PACKAGES | Malicious applications can use this to try and trick users into installing additional malicious packages. |
android.permission.REORDER_TASKS | Allows an application to move tasks to the foreground and background. Malicious applications can force themselves to the front without your control. |
com.zhiliaoapp.musically.miniapp.PROCESS_COMMUNICATION | Unknown permission from android reference |
com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE | Unknown permission from android reference |
com.google.android.c2dm.permission.RECEIVE | Unknown permission from android reference |
com.zhiliaoapp.musically.permission.RECEIVE_ADM_MESSAGE | Unknown permission from android reference |
com.amazon.device.messaging.permission.RECEIVE | Unknown permission from android reference |
android.permission.USE_CREDENTIALS | Allows an application to request authentication tokens. |
android.permission.MANAGE_ACCOUNTS | Allows an application to perform operations like adding and removing accounts and deleting their password. |
android.permission.READ_APP_BADGE | Unknown permission from android reference |
me.everything.badger.permission.BADGE_COUNT_READ | Unknown permission from android reference |
me.everything.badger.permission.BADGE_COUNT_WRITE | Unknown permission from android reference |
android.permission.UPDATE_APP_BADGE | Unknown permission from android reference |
com.vivo.notification.permission.BADGE_ICON | Unknown permission from android reference |
There were a few permissions that seemed odd to me for an app that has a purpose of sharing short video clips online. The android.permission.AUTHENTICATE_ACCOUNTS allows for the creation of accounts and setting passwords. I would question why that would be necessary (and I have never seen that in other apps). Then the 16 specific settings for modifying system data – I would also wonder why those would be necessary. But again, it can be hard to determine from the outside looking in what functionality requires these. If I had to make a yes or no decision on if the app was overly permissive, I would say yes.
Since the phone was set up to use Burp as a proxy and the Burp CA installed and trusted we can move on to network traffic inspection. When the app was launched, the application traffic was intercepted. I went through the initial “what am I interested in” choices and created an account and started watching a few videos and using the app for a few minutes.
Next, I saved all HTTP requests intercepted by Burp to a file and used command line tools to get an idea of how many hosts were involved in communication from the app. Using command-line utilities, I counted 32 hosts that appeared to be related to TikTok network traffic. For the most part, I found these through manual analysis of the Proxy traffic listed in Burp and used the domains as search terms with grep on the command line to get an easier parse text list.
There were many GET requests to TickTok APIs profiling my device, but this is not uncommon for developers to do. Metrics for install base can be useful. But, it could definitely be viewed as data collection.
I also noticed something odd in the sense that I have not seen this with other apps that I have analyzed (*Note that the vast majority of the apps I look at are for work engagements). It appeared that most of the HTTP message bodies for API calls were encrypted.
Why do I say that the data being sent was encrypted? I have seen where API requests were gzip compressed, but I have been able to look through the requests and find where the compressed file began and decode the traffic.
To investigate this, I looked for the beginning of requests to hosts based on the time I launched the app and right-clicked on the message body and selected “Send to Decoder”. This sends the request to the Burp Suite decoder which allows you to choose various types of decoding. I was not able to locate a portion of data that was able to be decoded.
The requests in Burp can be saved to file by right-clicking in the proxy window and selecting Save Item. The request will be base64 encoded and can be decoded at the command line by:
$echo “<paste base64 blob here” | base64 -d -w 0 > file_name
Next, take the HTTP header information out of the saved file, and you are left with the message body. Using the file utility on the file results in “data” returned (no file magic bytes to discover).
I used the ent utility to check the entropy of a few of the larger message bodies and it appeared to be encrypted.
At this point, the best option to break the encryption would be to do some in-depth static analysis on the extracted APK and figure out how encryption is implemented and write some code to decrypt it. That’s a bit beyond the scope of this post.
At this point in the analysis though, if I were performing a risk analysis for allowing the app on company devices, I think there would be enough data to decide against it. But what about banning TikTok from the general public? My opinion is that without breaking the encryption, it would be hard for me to say. My guess is that it was decrypted by someone and that data was being collected was viewed as an invasion of privacy.
To play Devil’s Advocate though, what if we looked at other popular apps with huge install bases? Apps like Instagram, Twitter, Snapchat, or Facebook? They collect some amount of personal data. We are in the Age of Surveillance Capitalism, selling human behavior for targeted advertising is how money is made for these companies. What data are they sending?
Getting at the data sent by these other popular social media apps is even more difficult, as they are using a technique called Certificate Pinning to defeat traffic inspection. This is where a specific certificate is embedded in the application to establish TLS encrypted communication, and if that certificate is not used (as in our case with using the Burp certificate) then communication is not established.
To defeat Certificate Pinning, one would need to inject code into the application at runtime (using something like Frida) to remove or bypass the pinning code or decompile the app and edit smali files and repackage the app and install the modified app. Neither option is a trivial exercise.
Personally, I think it’s safe to assume as a user for any popular app, that personal data from your phone is being sent to any of these companies. Does it matter where the company is headquartered? Perhaps for some, perhaps not for most others. At the end of the day, I think that the majority of people have no real idea how much their privacy is compromised by apps on their mobile devices, but that is a conversation for another day and another blog post.
Ready to learn more?
Level up your skills with affordable classes from Antisyphon!
Available live/virtual and on-demand