I just hacked your app - TakeOff 2016

I just hacked your app - TakeOff 2016

Android security is nowhere near where it should be. I have been able to hack and get sensitive information from a few different apps and I’m just an amateur hacker at best.

In this session we will explore a number of ways an Android app can be exploited and most importantly methods that we can use to avoid these attacks.

755c8de62a6b84adb347797f374670c9?s=128

Marcos Placona

October 20, 2016
Tweet

Transcript

  1. 2.
  2. 3.
  3. 5.

    NOT

  4. 6.
  5. 7.
  6. 8.
  7. 9.
  8. 14.

    POST /users/461845f5d03e6c052a43afbc/points Accept: application/json Accept-Language: en-gb X-App-Version: 1.28.0 User-Agent: Dalvik/2.1.0

    (Linux; U; Android 6.0.1;) ... Content-Type: application/json; charset=UTF-8 Content-Length: 375 Host: api.eatapp.com Connection: Keep-Alive Accept-Encoding: gzip { "authentication_token":"boKUp9vBHNAJp7XbWZCK", "latitude":..., "longitude":..., "point":{ "isDoneByGesture":false, "main_beacon":{ "major":38995, "minor":12702, "uuid":"2C75E74B-41B7-49E3-BD26-CE86B2F569F8" }, "place_id":"450", "promoted_products_ids":[ {"id":"647035946536601578040000"}, {"id":"647035946536601578040000"}, {"id":"647035946536601578050000"} ] } }
  9. 15.

    POST /users/461845f5d03e6c052a43afbc/points Accept: application/json Accept-Language: en-gb X-App-Version: 1.28.0 User-Agent: Dalvik/2.1.0

    (Linux; U; Android 6.0.1;) ... Content-Type: application/json; charset=UTF-8 Content-Length: 375 Host: api.eatapp.com Connection: Keep-Alive Accept-Encoding: gzip { "authentication_token":"boKUp9vBHNAJp7XbWZCK", "latitude":..., "longitude":..., "point":{ "isDoneByGesture":false, "main_beacon":{ "major":38995, "minor":12702, "uuid":"2C75E74B-41B7-49E3-BD26-CE86B2F569F8" }, "place_id":"450", "promoted_products_ids":[ {"id":"647035946536601578040000"}, {"id":"647035946536601578040000"}, {"id":"647035946536601578050000"} ] } }
  10. 16.

    POST /users/461845f5d03e6c052a43afbc/points Accept: application/json Accept-Language: en-gb X-App-Version: 1.28.0 User-Agent: Dalvik/2.1.0

    (Linux; U; Android 6.0.1;) ... Content-Type: application/json; charset=UTF-8 Content-Length: 375 Host: api.eatapp.com Connection: Keep-Alive Accept-Encoding: gzip { "authentication_token":"boKUp9vBHNAJp7XbWZCK", "latitude":..., "longitude":..., "point":{ "isDoneByGesture":false, "main_beacon":{ "major":38995, "minor":12702, "uuid":"2C75E74B-41B7-49E3-BD26-CE86B2F569F8" }, "place_id":"450", "promoted_products_ids":[ {"id":"647035946536601578040000"}, {"id":"647035946536601578040000"}, {"id":"647035946536601578050000"} ] } }
  11. 17.
  12. 18.
  13. 19.
  14. 20.

    • Encrypt all the values • Utilise security features when

    they exist • Certificate pinning • DO NOT TRUST THE DEVICE
  15. 21.

    // Sending side byte[] data = text.getBytes("UTF-8"); String base64 =

    Base64.encodeToString(data, Base64.DEFAULT); // Receiving side byte[] data = Base64.decode(base64, Base64.DEFAULT); String text = new String(data, "UTF-8"); Encrypt all the values
  16. 23.

    • Encrypt all the values • Utilise security features when

    they exist • Certificate pinning • DO NOT TRUST THE DEVICE
  17. 25.

    • Encrypt all the values • Utilise security features when

    they exist • Certificate pinning • DO NOT TRUST THE DEVICE
  18. 26.

    public class KeyPinStore { private static KeyPinStore instance = null;

    private SSLContext sslContext = SSLContext.getInstance("TLS"); public static synchronized KeyPinStore getInstance() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException{ if (instance == null){ instance = new KeyPinStore(); } return instance; } private KeyPinStore() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException{ // Load CAs from an InputStream // (could be from a resource or ByteArrayInputStream or ...) CertificateFactory cf = CertificateFactory.getInstance("X.509"); // randomCA.crt should be in the Assets directory InputStream caInput = new BufferedInputStream(MainActivity.context.getAssets().open("randomCA.crt")); Certificate ca; try { ca = cf.generateCertificate(caInput); System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); } finally { caInput.close(); } // Create a KeyStore containing our trusted CAs String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); // Create a TrustManager that trusts the CAs in our KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); // Create an SSLContext that uses our TrustManager // SSLContext context = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); } public SSLContext getContext(){ return sslContext; } } Certificate pinning https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#Android
  19. 27.

    • Encrypt all the values • Utilise security features when

    they exist • Certificate pinning • DO NOT TRUST THE DEVICE
  20. 31.

    Options • Make sure you encrypt them • Protect them

    with tools like DexGuard and ProGuard • Get them off a server http://bit.ly/SafeKey
  21. 32.
  22. 33.

    Tampering detection // myPackageName should decode at runtime to "com.yourpackagename"

    // google should decode at runtime to "com.android.vending"; // amazon should decode at runtime to "com.amazon.venezia"; public boolean isHacked(Context context, String myPackageName, String google, String amazon) { //Crooks renamed your app? if (context.getPackageName().compareTo(myPackageName != 0) return true; // BOOM! //Rogues relocated your app? String installer = context.getPackageManager().getInstallerPackageName(myPackageName); if (installer == null) return true; // BOOM! if (installer.compareTo(google) != 0 && installer.compareTo(amazon) != 0) return true; // BOOM! return false; } http://bit.ly/isHacked
  23. 34.

    Tampering detection // myPackageName should decode at runtime to "com.yourpackagename"

    // google should decode at runtime to "com.android.vending"; // amazon should decode at runtime to "com.amazon.venezia"; public boolean isHacked(Context context, String myPackageName, String google, String amazon) { //Crooks renamed your app? if (context.getPackageName().compareTo(myPackageName != 0) return true; // BOOM! //Rogues relocated your app? String installer = context.getPackageManager().getInstallerPackageName(myPackageName); if (installer == null) return true; // BOOM! if (installer.compareTo(google) != 0 && installer.compareTo(amazon) != 0) return true; // BOOM! return false; } http://bit.ly/isHacked
  24. 35.

    • Check your app’s signature • Check for rooted device

    • Check for emulator • Check if the app is debuggable
  25. 36.

    private static final int VALID = 0; private static final

    int INVALID = 1; private static final String APP_SIGNATURE = "1038C0E34658923C4192E61B16846"; public static int checkAppSignature(Context context) { try { PackageInfo packageInfo = context.getPackageManager() .getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); for (Signature signature : packageInfo.signatures) { byte[] signatureBytes = signature.toByteArray(); MessageDigest md = MessageDigest.getInstance("SHA"); md.update(signature.toByteArray()); //compare signatures if (SIGNATURE.equals(APP_SIGNATURE)){ return VALID; }; } } catch (Exception e) { //assumes an issue in checking signature., but we let the caller decide on what to do. } return INVALID; } Check your app’s signature http://bit.ly/AndroidTampering
  26. 37.

    • Check your app’s signature • Check for rooted device

    • Check for emulator • Check if the app is debuggable
  27. 38.

    private static boolean canExecuteCommand(String command) { try { int exitValue

    = Runtime.getRuntime().exec(command).waitFor(); if (exitValue != 0) return false; else return true; } catch (Exception e) { return false; } } Check for rooted device
  28. 39.

    • Check your app’s signature • Check for rooted device

    • Check for emulator • Check if the app is debuggable
  29. 41.

    • Check your app’s signature • Check for rooted device

    • Check for emulator • Check if the app is debuggable
  30. 44.
  31. 45.