Tuesday, November 22, 2011

Kindle Fire Security, Part II- ADB, DropBox Manager

Another day, another short post detailing some other interesting things about the Kindle Fire. After only a day on the market, it was already rooted.  Here's a link to how it's done: http://forum.xda-developers.com/showthread.php?t=1348830

So, the two highlights of this post: 

Aside from the fact that the Fire shipped with KNOWN exploits present (as many devices sadly do), something else caught my attention through it all: ADB is enabled by default, and users have no way to disable it through the UI. Unlike other Android devices that at least force users to make a conscious decision to leave it enabled at all times, the Fire opts you in. For anyone that's not familiar with ADB, it stands for the Android Debug Bridge.  It's used for debugging, testing, and poking around on a device.  Anyone that can follow the steps within the XDA Developers link, pretty much has access to everything on your device. Even with a locked device. You lose your device = the bad guys win.

Besides everything our apps store and transmit about us, what lurks on the Kindle Fire? Well, let's fast forward to having a rooted device. This lets us navigate the entire filesystem, including app data directories and other directories only intended for privileged users. Here is the output of running 'ls -l' on the / directory:

$ su
su
# ls -l
ls -l
dr-x------ root     root              2011-11-17 14:10 config
drwxrwx--- system   system            2011-11-20 21:02 dropbox
drwxrwx--- system   cache             1969-12-31 19:00 cache
lrwxrwxrwx root     root              2011-11-17 14:10 sdcard -> /mnt/sdcard
drwxr-xr-x root     root              2011-11-17 14:10 acct
drwxrwxr-x root     system            2011-11-17 14:10 mnt
lrwxrwxrwx root     root              2011-11-17 14:10 vendor -> /system/vendor
lrwxrwxrwx root     root              2011-11-17 14:10 d -> /sys/kernel/debug
lrwxrwxrwx root     root              2011-11-17 14:10 etc -> /system/etc
-rw-r--r-- root     root         4203 1969-12-31 19:00 ueventd.rc
-rw-r--r-- root     root          840 1969-12-31 19:00 ueventd.omap4430.rc
-rw-r--r-- root     root            0 1969-12-31 19:00 ueventd.goldfish.rc
drwxr-xr-x root     root              2011-11-15 17:24 system
drwxr-xr-x root     root              2011-11-17 14:10 sys
drwxr-x--- root     root              1969-12-31 19:00 sbin
dr-xr-xr-x root     root              1969-12-31 19:00 proc
-rwxr-x--- root     root        14943 1969-12-31 19:00 init.rc
-rwxr-x--- root     root        11357 1969-12-31 19:00 init.omap4430.rc
-rwxr-x--- root     root         1677 1969-12-31 19:00 init.goldfish.rc
-rwxr-x--- root     root        90116 1969-12-31 19:00 init
-rw-r--r-- root     root          118 1969-12-31 19:00 default.prop
drwxrwx--x system   system            2011-11-20 20:41 data
drwx------ root     root              2011-11-05 00:17 root
drwxr-xr-x root     root              2011-11-17 14:15 dev


Hmm, the /dropbox directory seems interesting. Before you get all excited and think that this is some type of Dropbox integration, this isn't it.  This directory is used for DropBoxManager (android.os.DropBoxManager) files, which are generally used for system-wide verbose log storage. Here is what it contains:

# cd dropbox
cd dropbox
# ls -l
ls -l
drwxrwx--- system   cache             2011-11-17 10:11 recovery
-rw------- system   system      50619 2011-11-20 21:02 data_app_crash@1321840952
079.txt.gz
-rw------- system   system      57759 2011-11-20 20:41 system_app_anr@1321839667
379.txt.gz


Of interest in particular (to me, anyway) are the data_app_crash* files.  Whenever an app crashes, a file is written with the errors causing the crash as well as stack traces.  This can include sensitive information in some cases. 

Within the /system/app directory, there is a package called com.amazon.dcp.apk. This application performs metric collection, handles OTA messages, and more. It also interacts directly with files located in the /dropbox directory. It monitors the DropBox service to determine when new entries have been created. This is part of Amazon's metrics and analysis framework. If you want to call it a backdoor, then go for it. This will be a topic within a future post.

To be fair, the DropBoxManager is widely used on other devices as well. Additionally, lots of juicy stuff does get logged to the global logs on other devices too. But it certainly worth examining as many developers may be unaware of the fact that even though they are not explicitly logging events, additional channels exist for unintended data leakage. 

To examine the com.amazon.dcp application a bit deeper, we need to decompile it.  There are many resources on the web that detail how to do this.  Here are a few:



The latest version of Agnitio has the decompilation steps automated, but uses JAD for decompilation rather than JD-GUI: http://www.securityninja.co.uk/application-security/agnitio-security-code-review-tool-v2-1-released/  

Additionally, the Android Reversing Toolset is a distro that contains all of the tools mentioned in the blog posts above.  http://threatpost.com/en_us/blogs/android-reverse-engineering-toolset-debuts-110111

We aren't going to post the source code to Amazon's applications here, since cease-and-desist letters are no fun. Decompiling it using the resources listed above is EASY.

Every time an application crashes, Amazon dumps the stack trace and other information to a crash file within the /dropbox directory via the DropBox service. The files follow the format of data_app_crash@<time_in_milliseconds>.txt.gz. I've observed these files existing for several days without being cleared.  

So the worst part about this: the DropBox service doesn't support granular per-app permissions for retrieving crash log entries. You merely need the READ_LOGS permission, and any arbitrary application can retrieve the contents of each crash that's entered into the DropBox. Often, we tell developers that they are safe as long as they aren't logging sensitive information to the GLOBAL logs. What we leave out is that information such as crash logs (that aren't globally logged) may be inadvertently leaked out via other unexpected channels.     

To connect to the DropBox service used on the Kindle Fire, we can create a new DropBoxManager and get an entry with the following snippet of code:

DropBoxManager mDropBoxMan = ((DropBoxManager) context
                                   .getSystemService("dropbox"));
DropBoxManager.Entry localEntry = mDropBoxMan.getNextEntry(null, 0);

With access to the DropBoxManager, we can list entries.  With the entry we just retrieved, we can retrieve the body of the message with the following:

InputStream inStream = localEntry.getInputStream();
BufferedReader reader = new BufferedReader(
                              new InputStreamReader(inStream));
String line = "";
String logData = "";
while ((line = reader.readLine()) != null) {
          logData += line;
  }
  
If we want to iterate through every entry within the DropBoxManager, we need to get the time in milliseconds of the last entry, and pass that into our next request. The easiest way to do this is to wrap the code above within a do-while block:


DropBoxManager mDropBoxMan = ((DropBoxManager) context
                                   .getSystemService("dropbox"));
DropBoxManager.Entry localEntry = mDropBoxMan.getNextEntry(null, 0);

do {
     try {
          InputStream inStream = localEntry.getInputStream();
          BufferedReader reader = new BufferedReader(
                                        new InputStreamReader(inStream));
          String line = "";
          String logData = "";
          while ((line = reader.readLine()) != null) {
                    logData += line + "\n";
          }
     } catch (IOException e) {
     }
     //do something with the data here
} while ((localEntry = mDropBoxMan.getNextEntry(null,
               localEntry.getTimeMillis())) != null);

A malicious application on the Kindle Fire with just the READ_LOGS permission and INTERNET, can intentionally crash other applications, retrieve the logs, and exfiltrate them. How? Easy: explicit Intents with malformed or unexpected data sets. There are many ways to interact with other components, but this one is easy to illustrate. Any application can instantiate the Activity of another application provided it is either exported or has at least one Intent Filter in place. If there are permissions required to start a specific Activity, then that application would also need that permission to start it. By calling a specific Activity and sending it unexpected data or while in an unexpected state, in some scenarios it may be possible to intentionally dump information of interest to the crash logs. Also, applications do crash on their own. A malicious app has access to any and all crash logs.

We can call a package named com.nvisium.crashdummy with an Activity class called CrashActivity. The resulting Activity would crash as a resulting of a missing value within the Bundle passed within the Intent. The code for this is below:

ComponentName toLaunch = new ComponentName(
               "com.nvisium.crashdummy",
               "com.nvisium.crashdummy.CrashActivity");
Intent intent = new Intent("android.intent.action.VIEW");
Bundle bundle = new Bundle();
bundle.putString("userName","superman");
intent.setComponent(toLaunch);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(intent);

Combining the ability to crash other apps on demand with the ability to instantly retrieve that data, this is a serious problem in my opinion. 


Stay tuned for Part III, coming soon.

Tuesday, November 15, 2011

Kindle Fire Security- Initial Thoughts

After a few hours of messing with the Kindle Fire, I wanted to post a few observations that jumped out almost immediately. This is the first of several posts on the Fire. These are the "low hanging" fruits:
  • Emails are all stored in the /sdcard directory and can be read by any application
  • No built-in device lockout after X failed logon attempts
  • Your device is shipped already tied to your account, and does not require additional authentication for activation
  • User and device identifier information leak out in many public places (more in a later post)
  • Other, potentially much worse problems (more in a later post)
There are a few issues that seem to be a lot worse, but we'll save those for a rainy day. In many ways, the Fire seems rushed. Amazon got a lot right, but certainly missed some easy things.

First off, if you use the Kindle Fire's email client, congratulations- all of your email is stored within the SD card directory. Any application can list the contents of this directory, copy the database where your email is stored, and read it. This is a significantly degraded approach compared to how Google's Gmail client works, where emails are kept within internal storage. Internal storage = permissions protect you from non-rooted malicious apps. External storage = anyone can read it. When you plug your Fire into a computer, you have access to the /sdcard directory. The commands below show the /sdcard directories and files leading to your email, while plugged into a computer:

mannino$ pwd
/Volumes/KINDLE/Android/data

mannino$ ls
com.amazon.email          com.android.providers.media
com.amazon.venezia          com.cooliris.media

mannino$ cd com.amazon.email
mannino$ ls
files

mannino$ cd files/
mannino$ ls
76f24e2f-cd70-4def-9ad3-17e590d2dc96.db
76f24e2f-cd70-4def-9ad3-17e590d2dc96.db_att

mannino$ sqlite3 76f24e2f-cd70-4def-9ad3-17e590d2dc96.db
SQLite version 3.6.12
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables
android_metadata  folders           messages       
attachments       headers           pending_commands
sqlite> select * from messages;
4|0|12|1|Get Gmail on your mobile phone|1321422874000|X_GOT_ALL_HEADERS,X_DOWNLOADED_FULL|mail-noreply@google.com;|kindlefiretrainwreck@gmail.com;||||<html>
<font face="Arial, Helvetica, sans-serif">
<p>
       alt="Access Gmail on your mobile phone"
       style="border:0px;"/>
</a>


If you lose your device, someone with a lot of time on their hands will eventually brute force your password. There is no lockout function, at all. Compared to most other Android distributions that default to locking a user out after several failed attempts, this one simply doesn't.  Hence, this fails to protect you against even "casual" bad guys, assuming your password is reasonably simple.  

Finally, when Amazon shipped your device, they were "kind" enough to tie it to your account. Yes, the account that is also tied to your credit card(s). After entering your wireless network key, the device will instantly bypass the part of the registration where credentials are required.  So if someone snatched your device before you did, they could have went on a shopping spree, downloaded a bunch of books or music, and lived happily ever after with their content.  I'm not sure about you, but when something is tied to my credit card, I'd like a little more protection. Amazon should at least require the user's password before proceeding.

There are actually quite a few other issues, but I'm going to give Amazon some time to fix them before a public disclosure.  Yes, this is a device built for consumers.  Still, there are no excuses for missing the simple things.

This is the first of several posts on the Fire. So, stay tuned!