Android Security: Dangers of hybrid frameworks (XDA:Devcon14 write-up)

At the end of September I gave a presentation at xda:devcon14 which gave an overview of attack surfaces in Android and security issues in web-based applications. I have put my slides online on slideshare, and a lot of people were asking questions, so I decided to post a write-up.

Attack Surfaces

A big part of the presentation covers attack surfaces in Android, what are they?

Attack surfaces are pieces of code which are executable by everyone who has access to a system. They are called the open flanks of a system and allow input or code execution, not necessarily from a malicious user. A hacker will usually search in these places as these are the most interesting to manipulate.

In order to decide which attack surfaces an attacker will try to attack some properties of the surface are considered, as mentioned in the slides. These properties determine what the gain is for an attacker once he successfully compromises the surface entirely or just the code behind the surface. The general rule here to follow, is that an attacker will try to gain as much privileges as possible with the least amount of investment of resources and time.

I will not cover all the attack surfaces but only the one that is interesting for web-based applications. This is called the remote attack surface, more specific the WebView component. This is a class which offers functionality to render web content using the webkit render engine. This is a broad attack surface as a lot of web technologies and protocols need to be supported. These all represent an attack surface on their own, with their own vulnerabilities and security models which can be in conflict with the Android security model. Which is the case when we consider hybrid frameworks.

To be on the same page, I define a web-based Android application as an application who uses the Webview class to render web content.

JavaScript-Java Bridges, burn them

Security issues arise when you use a JavaScript-Java bridge in your web-based application. Android allows in the Webview class to call Java native code from Javascript, you can register the native code that can be called by using addJavaScriptInterface(). The security issues become apparent when you don’t know which content you are loading.

What happens with JavaScript being loaded in an iFrame? Or more general with JavaScript coming from a third party source?

Basically there is nothing stopping them from calling your Java native code associated with the JavaScript bridge. Android uses a permissions model to allow apps to do certain actions. Third-party JavaScript can call the same public methods associated with the JS bridge. This is because the Same-Origin-Policy is not applied to the bridge. It is in conflict with at one side native code running in a permissions security model and on the other side web content, which is bound to the SOP. These two security models do not interleave perfectly and thus allows attackers to use functionality the user never granted permissions for.

Hybrid Frameworks (Apache Cordova, Sencha Touch, …)

Hybrid frameworks are frameworks who let you develop a web application using HTML5, CSS and JavaScript for example. They allow you to pack your application to run cross-platform. Benefits of this approach is the fact you only need to develop your application once and you can pack it for the different platforms. This saves you time and money if you need to pay the developers.

When packing your application for Android, the following happens. Your web application is nothing more than web-content running in a Webview class. These frameworks come default with a Java-JS bridge which are publicly available. The same problems arise as mentioned here above with simple Webview applications. There are however solutions to these problems.

Domain Whitelisting

Just implement your own origin policy! You decide which third parties you trust. For hybrid frameworks it is fairly easy, just use the domain whitelisting functionality. The funny part here, is the fact that default this is implemented as allow every domain. Yeah, you’re welcome.

In applications using a Webview-component the solution is to just intercept pageloads and resource loading requests and implement whitelist logic to deny loading if you don’t trust the origin. The slides give you the two interesting methods which you need to override in the Webview class: shouldOverrideUrlLoading() and shouldInterceptRequest()

When a third-party ad-network is used the same vulnerabilities are present as ad-networks can inject third-party content. Recent study of MWRLabs discovered the following numbers:

A script was then crafted to automatically download Android applications, decompile them and identify if an ad network was in use, and if so determine if it is vulnerable. Out of the 1,000 top applications 570 were found to be vulnerable.

This means that over 50% of the Top 1000 web-based Android applications are vulnerable. Makes you think, if security is a key aspect and concern, stay away from web-based applications. It is very tricky to get it right, and in the end native coding is more fun 😉


PS: Those who want to see the talk, it was filmed, but is not yet online. Keep an eye on this blog or my twitter feed 😉

Interviewing at Google

Yesterday I had two technical interviews for a software engineering internship position at Google. This article is an attempt to motivate people to apply and tell them what to expect. So, here we go.

The first Google engineer called me around 14:30. The connection was not optimal from the interviewers side so instead of a phone interview we had a Google Hangout interview. We shared a Google word document where I should write all my code (yes, a plain and simple Google doc).

The interviewer was nice to talk to, his first question was : “What made you apply at Google ?”. Well, everybody knows that I am an Android geek/enthusiast/dreamer. So that was my answer. Also, interning at Google will give you experience in the field which you can impossible learn in school. Things like for example : scaling of systems, coping with huge datasets, an extremely large codebase, etc. After that we proceeded towards the first question, which was something like this :

Question 1 : Assume you have a sentence represented by a string-object. Write a function (in Java) that will swap all vowels with a vowel at the end of the sentence. So for example : “United States => “Enated Stitus”.

Basically the approach here, is to work with an array of characters and work your way down the sentence using 2 pointers. One pointer points to a vowel on the left half of the string, the other to the right half of the string. If the right pointer is smaller than the left pointer, work is done and you can return the string.

I did OK on this question, had a little bug with my pointers that were incremented in the wrong place. But the interviewer pointed me to it, and I resolved it rather quickly.

Question 2 : Write a class called CollectionsIterator that is capable of iterating over a set of iterators. Make sure this class can hold Iterators of any type.

The interviewer thought this was the difficult question but I found it rather easier than the string traversal. Approach is again, rather easy. Create a class that implements the Iterator<E> interface. Use a field for a current_iterator and a field for the main_iterator. The main_iterator will loop over all the iterators and the current_iterator is the one that is providing the elements of a certain collection in the set of collections. Sounds easy, but tricky when implementing the hasNext() method. In the end, my first solution was perfect and that concluded the end of the first interview.

After a 15 minutes break I got the second interview. This one was by phone and again on a shared Google doc. This interview was not as good as the first one. The question was also more difficult than the first one.

Question 3 : Write a function that has as input a list of strings and will print to stdout strings that are rotational equivalent line per line. So all strings on one line are rotational equivalent.

I struggled the most with this question, due to the fact the interviewer started with the question : “Do you have any experience with rotation ciphers ?”. Sure I do know what they were, but never really implemented one so I didn’t know all the details about them. This threw me off a bit, but in the end you didn’t need to know exactly how they work. Just the notion how a string can be rotated over the alphabet.

So the approach I took for this question was looping over the strings and computing their fingerprint. Basically the fingerprint(String s) function should be a function that returns the same string for every rotational equivalent string. This can be achieved by using the convention that the first character of every string should be ‘a’. So we calculate the distance from the current first char to ‘a’. (only taking into account the chars a->z) and we rotate the whole string over this distance. We then use a HashMap to store a mapping “fingerprint -> set<rotational equivalent strings>”. In the end we write a prettyPrint() method which will iterate over the set and print out one set of rotational equivalent strings per line.

I needed some help, the interviewer for example pointed out to use a fingerprint method. After this I came up with the whole solution. A last question was what I thought was good/bad about my approach. At this point I perfected my code and told why I used some data-structures (like hashmaps and sets).

In the end it was a pleasant experience, much better than interviewing at Facebook. I have a good feeling, but if I don’t make it now , I can’t really be sad as I couldn’t do much more. At least I’m chasing dreams, as everybody should do !



Android systems , secure or not ?

By the end of this current year, 1.4 billion smartphones will be in use: 798 million of them will run Android, 294 million will run Apple’s iOS, and 45 million will run Windows Phone, according to a new study by ABI Research.

Source: BusinessInsider

This is an incredible number of smartphone users which are connected to the big wide web. But how secure are they ? Is it possible for a mobile operating system to be secure ? Or is it insecure from the roots up ?

As you already might guess I will only be covering the Android part, not surprisingly they have the bigger marketshare. So, how do you ‘test’ a secure mobile system ?

A system can be locked down extremely but this can have an impact on the user friendliness, where do you draw the line ? How do we test if a given Android system is secure. Do we forget the user friendliness or are we considering the bigger picture : a secure , user friendly, Android system. I think considering the bigger picture is a more realistic impact as it includes the user’s behavior, which makes up a great part of the system’s security.

Let’s take a look at the security mechanisms Android has implemented for save distribution of applications. Android applications are shared through the Google Play Store. Android has two important security mechanisms which involve distribution and installation of apps in order to protect the installing user from malicious actions.

  • applications need to be signed
  • applications need permissions to access phone functions

Applications need to be signed with a special unique key that a developer can obtain. The signing of an application can be thought of as providing the application of a digital certificate. With this certificate Android aims on establishing trust relationships between applications. For example consider an app which we call “AppX”. If “AppX” is first installed, it is signed with a specific private key. If the developer upgrades “AppX” to “AppX2”, he needs to use the same key which he used to sign “AppX”. This creates a trusted relationship between “AppX” and “AppX2”, because only the developer that holds the key for “AppX” can develop an upgrade for the app. But is this waterproof ?

Probably u know the answer already because else I wouldn’t have hinted it. Well, no this is not waterproof. A rather invasive bug was found in the signing process.

The core issue is that Android package (APK) files are parsed and verified by a different implementation of “unzip a file” than the code that eventually loads content from the package: the files are verified in Java, using Harmony’s ZipFile implementation from libcore, while the data is loaded from a C re-implementation.

The way that these two implementations handle multiple files with the same name occurring in the zip file differs. The way the Java implementation reads the file is that it goes through the “central directory” and adds each entry to a LinkedHashMap. The key the entry is stored using is the name of the file.

Later, the PackageParser goes through each entry in the zip file, verifying that the file was signed with a consistent signature. This code iterates over the LinkedHashMap. The result is that only the last entry with a given name is considered for signature verification: all previous duplicates are discarded.

Source : Saurik

This is a rather technical explanation of the bug, so a more noob explanation follows. As .APK files are nothing more than JAR files, this is where the problem lies. Where a JAR stands for Java ARchive, a sort of folder with all your Java code. If you want to ensure the integrity of a JAR as a self-contained entity such as an Application then the ability to sign individual files is not a requirement. In fact it is difficult to see in what circumstances the ability to sign individual files and only individual files could be a requirement.

Because it is only possible to sign individual files, a signed JAR is really nothing more than a collection of files which may or may not be signed and the verification of a signed JAR is a very convoluted way of determining into which category each file belongs. All of which leads us to question of what signed JARs are actually for ?

The ability to package files in this way was presumably considered useful when the specification was produced but it is clear that it is a decidedly sub-optimal way of attempting to ensure the integrity of an Application made up of a number of files which have been packaged as a ZIP file.

While signed JARs undoubtedly constitute a flexible mechanism for doing something, its just not clear what, they do so at a cost.

As we have seen the cost is the complexity of the verification process and the inconclusiveness of the result.

The process of verification is ridiculously complicated and consequently dangerously error-prone which is not what you want from something which is a key part of ensuring the security of your platform. (Source : Simon Lewis)

Now, what can a user do about this ? Nothing much actually. The bug is known for some time now, the only actions Google has taken so far was to change something in the .APK submission in the play store. A fix to the devices is coming with Android 4.3 . Older devices need to install the CyanogenMod custom ROM. They have included the 4 LINE BUGFIX, which google failed to deliver OTA.

Next up on the list was “Permissions”. Every app needs specific permissions to access phone functions. As an example I will include permissions my currently developing app needs :

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="" />

These permissions look like they’re asking a lot, but the only access they give to the phone are :

  • The use of internet
  • Ability to write to SD card(= caching images) and internal memory (= for settings)
  • Read error log on crash to send back a detailed error log to me
  • Google Cloud Messaging service
  • Accessing the network state , to check if there’s an internet connection
  • And wake lock, my app uses a service that needs to run with or without the app running , so the services needs a wake lock

These permissions will be shown to the user upon install. So this is the part where the user’s common sense plays a big part. If you want to play a game and the game asks for a whole list of permissions, the game is usual spyware. It will collect as much info as it can and will send it back to a server. The maintainers of this server will use the information to sell to advertising companies. So reading through the permissions is not time lost, as they can be pretty invasive on the privacy of the phone user.

So I did not reach a conclusion, as it as a whole research on its own (maybe a master thesis ? 😉 ). But I hope I gave some pointers that there’s a huge gap between user friendliness and optimal security of a mobile system. Any comments or questions, shoot !