This is an easy-difficulty mobile challenge - and here is the description:
This app has stored my credentials and I can only login automatically. I tried to intercept the login request and restore my password, but this seems to be a secure connection. Can you help bypass this security restriction and intercept the password in plaintext?
First, we need to install the APK (pinned.apk
) on our device. The test file in the archive tells us which version of Android to use, but I didn’t want to set up a whole new emulator so I went through some troubleshooting steps to make it work.
adb install pinned.apk
Performing Streamed Install
adb: failed to install pinned.apk: Failure [-124: Failed parse during installPackageLI: Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary]
So to make this work we should just have to re-align the APK and sign it.
zipalign -p -f -v 4 pinned.apk align-pinned.apk
Then you’ll need a key store to use to sign it:
keytool -genkey -v -keystore research.keystore -alias research_key -keyalg RSA -keysize 2048 -validity 10000
Then we can sign it and install:
apksigner sign --ks research.keystore align-pinned.apk
adb install .\align-pinned.apk
Now we can access the app in our emulator:
When I try to use Burp or the HTTP Toolkit we get some issues when trying to use the app though:
This makes me believe that we need to get around SSL Pinning. (Also, this is a pretty normal part of testing android applications and the name of the challenge is Pinned so we know we signed up for this) Normally when an app makes a request to a server over HTTPS the server presents its TLS/SSL certificate - which is signed by a trusted CA. This is normal for most things which is why we need to import the PortSwigger CA certificate when proxying traffic. SSL Pinning is when the trust for the certificate is hard-coded into the application itself. This can be done in a variety of ways but we need to get around it in order to actually intercept the app’s traffic.
We can use frida
to see running processes and list if they are ones we can interact with using Dynamic Instrumentation.
frida-ps -Uia
PID Name Identifier
----- -------------- ------------------------------
9732 Calendar com.android.calendar
11811 Files com.android.documentsui
11603 HT2048 io.hextree.privacyfriendly2048
12503 HTTP Toolkit tech.httptoolkit.android.v1
12258 Hidden Secrets io.hextree.reversingexample
12379 Pinned com.example.pinned
9817 Rethink com.celzero.bravedns
1199 SIM Toolkit com.android.stk
11471 Settings com.android.settings
- Camera com.android.camera2
- Clock com.android.deskclock
- Contacts com.android.contacts
- FridaTarget io.hextree.fridatarget
- Gallery com.android.gallery3d
- Messaging com.android.messaging
- Phone com.android.dialer
- PocketHexMaps io.hextree.pocketmaps
- Search com.android.quicksearchbox
- WebView Shell org.chromium.webview_shell
The above command lists the processes running on our emulator, using -i
to only list instrumentable processes and -a
to show additional application data.
We see that com.example.pinned
is our target here. To bypass the SSL pinning we can use objection
which is a part of frida
that can make this part of the process easier. In order to do this make sure you have the right version of the frida-server running on the android device or emulator.
#I opted to push it to the tmp directory
adb push frida-server /data/local/tmp
#then get a shell and make it excecutable and run it
adb root
adb shell
cd /data/local/tmp
chmod +x frida-server
./frida.server
Then we can inject objection
into the running app:
objection -g com.example.pinned explore
Using USB device `Android Emulator 5554`
Agent injected and responds ok!
_ _ _ _
___| |_|_|___ ___| |_|_|___ ___
| . | . | | -_| _| _| | . | |
|___|___| |___|___|_| |_|___|_|_|
|___|(object)inject(ion) v1.11.0
Runtime Mobile Exploration
by: @leonjza from @sensepost
[tab] for command suggestions
com.example.pinned on (Android: 14) [usb] #
We can use android sslpinning disable
to, as you may have guessed, disable SSL pinning.
com.example.pinned on (Android: 14) [usb] # android sslpinning disable
(agent) Custom TrustManager ready, overriding SSLContext.init()
(agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.verifyChain()
(agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.checkTrustedRecursive()
(agent) Registering job 443476. Type: android-sslpinning-disable
com.example.pinned on (Android: 14) [usb] # (agent) [443476] Called SSLContext.init(), overriding TrustManager with empty one.
Then on the app we will go ahead and log in and in your traffic inspector (Burp or HTTP Toolkit) we will see the flag: