Mobile Security
Godfrey Nolan
How did we get here
- Virtual Machines
- Static information
- Dynamic information
Decompilation 101
Decompilation 101
Decompilation 101
$ adb shell pm path com.united.mobile.android
package:/data/app/com.united.mobile.android-1/base.apk
$ adb pull /data/app/com.united.mobile.android-1/base.apk
4349 KB/s (51855610 bytes in 11.642s)
$ jadx-gui base.apk
$ adb backup com.united.mobile.android
Now unlock your device and confirm the backup operation.
$ java -jar abe.jar unpack backup.ab backup.tar
$ tar -xvf backup.tar
$ sqlite3 apps/com.united.mobile.android/db/united.db
Decompilation 101
Decompilation 101
Audit Reports
OWASP Top 10
- Weak Server Side Controls
- Insecure Data Storage
- Insufficient Transport Layer Protection
- Unintended Data Leakage
- Poor Authorization and Authentication
- Broken Cryptography
- Client Side Injection
- Security Decision via Untrusted Input
- Improper Session Handling
- Lack of Binary Protections
OWASP Top 10
- Identify Problem
- Show real world example
- Fix it!
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
GET http://herdfinancial.com/api/v1/balances/1234567899/
{"success":"true","checkingBalance":"0.0","savingsBalance":"0.0"}
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
GET http://herdfinancial.com/api/v1/balances/1234567890/
{"success":"true","checkingBalance":"947.3","savingsBalance":"0.0"}
Example
"actor": {“first_name": "Rita","last_name": "D.","title": "Rita D.","gender": "F",
"is_mvp": false,
"preferred_brand": 32,
"_links": {"self": [{"href": "\/v7.0\/user\/3273986\/","id": "3273986"}]},
"type": "user",
"friendship": null,
"id": 3273986
},"id": "1-3273986-9-1440092847",
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Use GUID that maps to ID
- REST verbs are easy to guess
- OWASP Web/Cloud top 10
- Don’t trust the client, verify
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<boolean name="remember" value="true" />
<string name="password">goatdroid</string>
<string name="username">goatdroid</string>
</map>
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- No caching of passwords, SSNs etc.
- Multi-factor authentication
- Client / Server side access control
- "Sensitive data should be encrypted and very sensitive data should be stored on server" - Zapata
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
More Problems
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Fix
private static String PUB_KEY = "30820122300d06092a864886f70d0101" +
"0105000382010f003082010a0282010100b35ea8adaf4cb6db86068a836f3c85" +
"5a545b1f0cc8afb19e38213bac4d55c3f2f19df6dee82ead67f70a990131b6bc" +
"ac1a9116acc883862f00593199df19ce027c8eaaae8e3121f7f329219464e657" +
"2cbf66e8e229eac2992dd795c4f23df0fe72b6ceef457eba0b9029619e0395b8" +
"609851849dd6214589a2ceba4f7a7dcceb7ab2a6b60c27c69317bd7ab2135f50" +
"c6317e5dbfb9d1e55936e4109b7b911450c746fe0d5d07165b6b23ada7700b00" +
"33238c858ad179a82459c4718019c111b4ef7be53e5972e06ca68a112406da38" +
"cf60d2f4fda4d1cd52f1da9fd6104d91a34455cd7b328b02525320a35253147b" +
"e0b7a5bc860966dc84f10d723ce7eed5430203010001";
// Pin it!
final boolean expected = PUB_KEY.equalsIgnoreCase(encoded);
if (!expected) {
throw new CertificateException("checkServerTrusted: Expected public key: "
+ PUB_KEY + ", got public key:" + encoded);
}
}
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Error out on SSLHandshakeException
- Assume SSL is broken, root level CA's
- SSL pinning but use SafetyNet API
- Do more on the server
- Scan server with nogotofail
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Example
public ActivityLaunchAppLoad() {
this.WAY_WAY_TOO_LOW = 49;
this.A_LITTLE_LESS_WAY_TOO_LOW = 50;
this.LESSER_WAY_TOO_LOW = 51;
this.BIT_TOO_LOW = 52;
this.TOO_LOW = 53;
this.MORE = 54;
this.A_LITTLE_MORE = 55;
this.WAY_TOO_MORE = 97;
this.BIG_DADDY = 102;
this.orderOfTheThronesTrois = new int[]{this.BIG_DADDY, this.MORE, this.WAY_TOO_MORE, this.MORE};
this.orderOfTheThronesQuatre = new int[]{this.LESSER_WAY_TOO_LOW, this.MORE, this.LESSER_WAY_TOO_LOW, this.TOO_LOW};
this.orderOfTheThronesUn = new int[]{this.BIT_TOO_LOW, this.BIT_TOO_LOW, this.WAY_WAY_TOO_LOW, this.BIT_TOO_LOW};
this.orderOfTheThronesDeux = new int[]{this.MORE, this.A_LITTLE_MORE, this.A_LITTLE_LESS_WAY_TOO_LOW, this.BIT_TOO_LOW};
}
String createTheHalfBloodPrince() {
String strTemp = StringUtils.EMPTY;
int x = 0;
while (x < 4) {
int[] xyz = null;
if (x == 0) {
xyz = this.orderOfTheThronesTrois;
} else if (x == 1) {
xyz = this.orderOfTheThronesQuatre;
} else if (x == 2) {
xyz = this.orderOfTheThronesUn;
} else if (x == 3) {
xyz = this.orderOfTheThronesDeux;
}
int y = 3;
while (y >= 0) {
strTemp = new StringBuilder(String.valueOf(strTemp)).append(Character.toString((char) xyz[y])).toString();
y--;
}
x++;
}
return strTemp;
}
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Strip out unneccesary logging code
- Obfuscate method names
- Check any third party libraries
- Double check your webview caches
- Download and unzip your APK
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="TM_MEMBER_EMAIL">godfrey@riis.com</string>
<int name="TM_MEMBER_MARKET_ID" value="7" />
<string name="TM_MEMBER_TAP_ID">77ef62159ad9c32913dfdbee0e58aea3</string>
<string name="TM_MEMBER_LNAME"></string>
<string name="TM_MEMBER_LANGUAGE">en-us</string>
<int name="TM_BILLING_COUNTRY_CODE" value="-1" />
<string name="TM_MEMBER_POSTCODE">48070</string>
<string name="TM_LAST_BILLING_ID"></string>
<int name="TM_MEMBER_COUNTRY" value="840" />
<string name="TM_MEMBER_PASSWORD">2secret4me</string>
<string name="TM_MEMBER_FNAME">Godfrey</string>
</map>
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- No password caching
- Multi Factor Authentication
- Encryption
- Public-Private Key exchange
- Tokens, tokens, tokens
- OAuth
- Use Server side nonce’s
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Example
public static String decrypt(String paramString)
throws Exception
{
if (paramString != null)
return new String(decrypt(getRawKey("3lIoM_d0idrn4|4TleD".getBytes()), toByte(paramString)));
return null;
}
private static byte[] decrypt(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2)
throws Exception
{
SecretKeySpec localSecretKeySpec = new SecretKeySpec(paramArrayOfByte1, "AES");
Cipher localCipher = Cipher.getInstance("AES");
localCipher.init(2, localSecretKeySpec);
return localCipher.doFinal(paramArrayOfByte2);
}
Example
// NDK code - still see the code in disassembler
jstring Java_com_riis_decompilingandroid_getPassword(JNIEnv* env, jobject thiz)
{
return (*env)->NewStringUTF(env, "xeHnwfiy4uzefrabruebeb");
}
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Use asymmetric encryption
- Encrypt databases
- Security Jetpack w/Titan chip
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Problem
public boolean checkLogin(String param1, String param2)
{
boolean bool = false;
Cursor cursor = db.rawQuery("select * from login where USERNAME = '" +
param1 + "' and PASSWORD = '" + param2 + "';", null);
if (cursor != null) {
if (cursor.moveToFirst())
bool = true;
cursor.close();
}
return bool;
}
select * from login where USERNAME = '' OR 1=1 --' and PASSWORD = 'test'
Fix
public boolean checkLogin(String param1, String param2)
{
boolean bool = false;
Cursor cursor = db.rawQuery("select * from login where " +
"USERNAME = ? and PASSWORD = ?", new String[]{param1, param2});
if (cursor != null) {
if (cursor.moveToFirst())
bool = true;
cursor.close();
}
return bool;
}
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
<script>alert("xss");</script>
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Use parameterized queries
- setJavaScriptEnabled(false)
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Problem
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.riis.login"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.riis.login.LoginActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.riis.login.IntentReceiverActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="com.riis.login.IntentReceiverActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
Problem
<activity
android:name="com.riis.login.IntentReceiverActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="com.riis.login.IntentReceiverActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Problem
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.riis.hellointent"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.riis.hellointent.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.riis.login.IntentReceiverActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
Fix
// implicit
Intent intent = new Intent();
// explicit
Intent intent = new Intent(this, IntentReceiverActivity.class);
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Use explicit intents
- Scan using Intent Sniffer / Drozer
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
if (dao.isDevicePermanentlyAuthorized(deviceID)) {
String newAuthToken = Utils.generateAutToken();
doa.updateAuthrizedDeviceAuth(deviceID, newAuthToken);
login.setAuthToken(newAuthToken);
login.setUserName(dao.getUserName(newAuthToken));
login.setAccountNumber(dao.getAccountNumber(newAuthToken));
login.setSuccess(true);
}
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Example
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Expire sessions
- Try backup to another phone
- Careful using OAuth logins to FB etc.
Problem
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
/**
* Logs you into your SIP provider, registering this device as the location to
* send SIP calls to for your SIP address.
*/
public void initializeLocalProfile() {
if (manager == null) {
return;
}
if (me != null) {
closeLocalProfile();
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String username = prefs.getString("namePref", "");
String domain = prefs.getString("domainPref", "");
String password = prefs.getString("passPref", "");
Example
Fix
Weak Server Side Controls
Insecure Data Storage
Insufficient Transport Layer Protection
Unintended Data Leakage
Poor Authorization and Authentication
Broken Cryptography
Client Side Injection
Security Decision via Untrusted Input
Improper Session Handling
Lack of Binary Protections
- Obfuscation helps remove useful info
- Set minifyEnabled = true
- Not a silver bullet
- Anti ProGuard apps out there
- Hackers just move to Smali
- Code in C++ using NDK
- Much harder to read
- Can still disassemble C++
The Leftovers
- android:debuggable(true)
- some Smali required
- SSL Pinning
- Bug Bounties
- SafetyNet API
- Frida
The Leftovers
The Leftovers
- Disassemble using apktool
- Find main class in AndroidManifest.xml
- Add debug wait to onCreate method
- Recompile using apktool
- Sign and install
java -jar apktool.jar d -d test.apk -o out
<activity android:label="@string/app_name" android:name="com.riis.helloworld.MainActivity">
a=0;// # virtual methods
a=0;// .method protected onCreate(Landroid/os/Bundle;)V
a=0;// invoke-static {}, Landroid/os/Debug;->waitForDebugger()V
a=0;//
a=0;// .locals 1
a=0;// .param p1, "savedInstanceState" # Landroid/os/Bundle;
java -jar apktool.jar b -d out -o debug.apk
The Leftovers
- Security is too difficult to keep up with??
- Crowdsource it with Bug Bounties
- United Airlines offering substantial airmiles
- Lessons Learned
- Requires effort to keep up with submissions
- Update your app often to keep interest alive
- Not a tool for shutting down researchers
The Leftovers
The Leftovers
The Leftovers
byte[] nonce = getRequestNonce(); // Should be at least 16 bytes in length.
SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
.setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {
@Override
public void onResult(SafetyNetApi.AttestationResult result) {
Status status = result.getStatus();
if (status.isSuccess()) {
// Indicates communication with the service was successful.
// Use result.getJwsResult() to get the result data.
} else {
// An error occurred while communicating with the service.
}
}
});
{
"nonce": "R2Rra24fVm5xa2Mg",
"timestampMs": 9860437986543,
"apkPackageName": "com.package.name.of.requesting.app",
"apkCertificateDigestSha256": ["base64 encoded, SHA-256 hash of the
certificate used to sign requesting app"],
"apkDigestSha256": "base64 encoded, SHA-256 hash of the app's APK",
"ctsProfileMatch": true, // Compatibility Testing Suite
"basicIntegrity": true,
}
The Leftovers
The Leftovers
MASVS / MSTG
-
OWASP MASVS
-
OWASP MSTG
-
OWASP Mobile Security Checklists
MASVS / MSTG
MASVS / MSTG
MASVS / MSTG
MASVS / MSTG
MASVS / MSTG
Reasons to Ignore Security
- Security is too difficult to keep up with
- Requires physical access
- Avast report - 80k old phones on eBay
- allowBackup=false
- Proguard / DexGuard is too hard to use
- The code is already obfuscated
- You need to talk to the API team
- Fragmentation
-
We don't have time
Recommendations
- Understand debuggable=true, allowbackup=true
- Don’t trust, verify
- Rewrite SSL code, use asymmetric encryption
- Provide an email or security page for white hats
- Attacks are going to get more complex
- Start a Bug Bounty
- Store nothing important on the device
- Don't ignore Smali attacks
- Secure your server
- Use SafetyNet API
Resources
http://www.decompilingandroid.com
http://www.owasp.org
https://github.com/nelenkov/android-backup-extractor
http://www.charlesproxy.com
http://www.programering.com/a/MjM5UTMwATg.html
http://www.cs.ru.nl/~joeri/papers/spsm14.pdf
https://www.mwrinfosecurity.com/products/drozer
https://github.com/skylot/jadx
http://keyczar.org
https://www.nccgroup.trust/us/about-us/resources/intent-sniffer/
http://www.guardsquare.com
http://sqlitebrowser.org
http://bit.ly/1JlPoiY - How to hide your android API key
http://bit.ly/1hIeNNi - Where to store your password
https://github.com/google/nogotofail
https://github.com/godfreynolan/bulletproof
http://riis.com/blog/android-obfuscation
http://riis.com/blog/android-safetynet
http://frida.re
Gist List of Old* Hacks
Delta: https://gist.github.com/cbeyer-riis/32e3d028c0deebca4057
Groupon: https://gist.github.com/cbeyer-riis/151a3eeed66a0516d50f
Walgreens: https://gist.github.com/cbeyer-riis/4f3758f9a58f554d40a4
Target: https://gist.github.com/cbeyer-riis/a55d90e38554c7122c89
Match: https://gist.github.com/cbeyer-riis/73318ee997132024b17d
Walgreens: https://gist.github.com/cbeyer-riis/372212c1fb5128841dcf
eHarmony: https://gist.github.com/cbeyer-riis/9e21e9b9996ea536cc5c
Hilton Honors: https://gist.github.com/cbeyer-riis/0834606d33c581b2a045
Hyatt: https://gist.github.com/cbeyer-riis/bfcab3d7673fba868624
Holiday Inn: https://gist.github.com/godfreynolan/e01f6ae1fab31ab66c39
*Find older apk's on apkpure.com
Contact Details
godfrey@riis.com
@godfreynolan
slides.com/godfreynolan/bulletproofandroidmeetup
Mobile Security
By godfreynolan
Mobile Security
- 1,322