Slide 1

Slide 1 text

REST in Peace: A Journey Through API Protection Andreas Luca & Marc Obrador 26 October 2023 I Droidcon London

Slide 2

Slide 2 text

*just for today Andreas Luca Head of Solution Engineering @ Build38 Marc Obrador CTO & Co-Founder @Build38 Head of Sec @ findyourflight.co.uk* Tech Lead @ findyourflight.co.uk* whoami

Slide 3

Slide 3 text

One Day during the Daily Standup...

Slide 4

Slide 4 text

Current Situation ü HTTPS is used ü API is protected with API Token

Slide 5

Slide 5 text

Finding URL, Endpoint Info & API-Token https://www.charlesproxy.com/

Slide 6

Slide 6 text

Certificate Pinning Source: https://developer.android.com/privacy-and-security/security-config#CertificatePinning In res/xml/network_security_config.xml:

Slide 7

Slide 7 text

Certificate Pinning https://www.charlesproxy.com/

Slide 8

Slide 8 text

Decompiling the APK $ brew install apktool $ apktool d MyApp.apk https://apktool.org/

Slide 9

Slide 9 text

Hiding the API Token private val iv = sha256(BuildConfig.APPLICATION_ID + BuildConfig.VERSION_NAME) private val key = byteArrayOf(0x00, 0x01, 0x02, 0x03, … private val aad = byteArrayOf(0x0F, 0x0E, 0x0D, 0x0C, … private val tag = byteArrayOf(0x85, 0xb8, 0x75, 0x61, … private val ciphertext = byteArrayOf(0xa1, 0xd1, 0x75, … private fun decryptSecretToken(): String { return aes256Decrypt(iv, aad, key, ciphertext, tag) } private fun aes256Decrypt( iv: ByteArray, aad: ByteArray, keyBytes: ByteArray, ciphertext: ByteArray, tag: ByteArray): String { val cipher = Cipher.getInstance("AES/GCM/NoPadding") val spec = GCMParameterSpec(TAG_LENGTH * 8, iv) val key = SecretKeySpec(keyBytes, 0, keyBytes.size, "AES") cipher.init(Cipher.DECRYPT_MODE, key, spec) cipher.updateAAD(aad) return String(cipher.doFinal(ciphertext + tag)) }

Slide 10

Slide 10 text

It is a bit more difficult, but…

Slide 11

Slide 11 text

It is a bit more difficult, but… Java.perform(function () { console.log("Setting hooks..."); var aesd = Java.use("c1.c"); aesd.e.implementation = function(str) { console.log("Input intercepted data: " + str); var res = this.e(str) console.log("Ouput intercepted data: " + res); return res; } console.log("Setting hooks done."); });

Slide 12

Slide 12 text

A Slightly Better Approach Idea: restrict validity of API token only for login request o Upon successful log in, a dynamic, short- lived token (e.g. a JWT) is issued to the app o All other API endpoints require the JWT (instead of the API key) To get full access to the API, both API token and valid user credentials are needed Cons: • Backend changes required • Enforces user log-in / sign-up

Slide 13

Slide 13 text

Closing Thoughts Is there a 100% protection? No. What can I do? Protect against all kind of attacks: o Network level o Static Analysis o Dynamic Analysis How long will it take? It could be time consuming…

Slide 14

Slide 14 text

Q&A Build38.com Munich I Barcelona I Singapore Find us at Booth 6! /build38/rest-in-peace-droidcon-london Andreas Luca Head of Solution Engineering Marc Obrador CTO & Co-Founder @theBIGGlucas @marcobrador