Lets Learn English - Hacking 10M+ Users
The Motivation
This work started with me working on my videos on Android Hacking Series.
So, I started exploring android security vulnerabilities. Reading blogposts, disclosed reports, watching some videos, practicing broken apps etc. Most of it was the static analysis which I had already covered in my first two parts.
I was more focused on the dynamic instrumentation part of it. Exploring Frida and using it to bypass some checks, encryption in the app. I had very limited experience with it during my time playing CTFs, while in college. So that was all to it.
tl;dr
- Walkthrough to my approach to android app pentesting
- Static and Dynamic analyses compliment each other
- Found 4 vulns — All critical or high. Account takeover, user PII leak etc. None of these depended upon my frida skills though 😛
That’s bug bounties, you never know what’s gonna work 😉 - Understood how to hook functions using frida — Next part
- Change functions and response from JS code in frida, no automated framework — Next part
The Story
Let’s start with this.
I had a few candidates for testing, all of these apps were app advertisements’ that I saw while using other apps or in YouTube advertisements.
Eventually I chose an app which had the highest user base, 10 Million+ , at the time I tested this. This app is used by millions to learn English in a fun manner.
Stage 1 : Static Analysis
Always start with decompilation of the app, I use apktool as well as jadx. After decompilation from apktool, I find grepping is faster in certain region/folders of the app, which isn’t possible in jadx. You might find some easy wins here.
How to do :
Prerequisites :
- Install apktool : Instructions here
- Download and use jadx from their github page here
Now pull the apk from the mobile or download it from any of the online apk stores like evozi apk downloader, apkpure.com , apkonline.net
I installed the app onto the phone and pulled the apk onto my machine using adb :
adb shell pm path <app_identifier>
adb pull <path_of_base_apk>
Now with apk on my local machine. I started decompiling it using apktool
apktool d <app_identifier>
After this I start with jadx-gui , which can be run on linux and mac as
./jadx-gui
and for windows there’s a ‘jadx-gui.bat’ file as well
You can manually check the AndroidManifest.xml for any secrets and also in the app’s code folders.
I prefer using gf in the decompiled directory from apktool to search for secrets. Like this :
Doing static analysis on the app, I found sensitive info in AndroidManifest.xml and also in other files as well. Hence, always ‘grep’ 😄
As luck would’ve it I found the following :
Bug 1 : s3 buckets with write access
— Contained user PII ( Personally Identifiable Information like aadhar, PAN card etc ). The other bucket was a staging one and hence didn’t have a lot of data. I uploaded a ‘poc.txt’ to show that it’s world writable and hence vulnerable.
Bug 2 : Open firebase database — Contained less sensitive info
I also found a ‘Constants.Java’ file, which contained constants used in the app, like s3 bucket address, SNS default topic arn, google client id for the oauth client etc this wasn’t useful straight out of the decompiler but later on proved to be more useful.
Stage 2: Dynamic Analysis
How to do :
Prerequisites :
- Physical Device or Emulator ( genymotion is fast, hence I prefer that )
- Open BURP on your laptop
- Install BURP certificate and set the mobile proxy settings to pass through your laptop — Here’s the guide by portswigger labs themselves Configuring an Android device to work with Burp Essentially it involves two steps :
- Setup BURP as proxy in your wifi settings
- Install the BURP CA cert on your phone
I set up BURP on my testing device, lenovo ZUK Z2+ and installed the apk from playstore onto it. I couldn’t see the traffic coming through BURP.
I could see HTTPs traffic from my mobile’s chrome browser coming through BURP but not of this particular application. This is an indication of certificate pinning being used by the app.
What is SSL Pinning ?
Let’s take a step back and ask ourselves a question.
Why did we need to add a BURP certificate to ‘see’ the HTTPs traffic, why not just setting up BURP machine as proxy allow us to pass traffic through BURP 🤔
The answer to the above question is SSL Pinning.
Certificate pinning ( SSL Pinning ) restricts which certificates are considered valid for a particular website, limiting risk. Instead of allowing any trusted certificate to be used, operators “pin” the certificate authority (CA) issuer(s), public keys or even end-entity certificates of their choice. Clients connecting to that server will treat all other certificates as invalid and refuse to make an HTTPS connection.
So whenever you make a request to a HTTPs website there are certificates involved which help prove the identity of the parties involved in the communication. Now this communication is encrypted by the certificate amongst the two parties, who’re communicating.
What purpose does this solve ?
This ensures that no unauthorized person is able to view the traffic between the client and the server ( the two parties involved ).
To view this traffic, what BURP does is it acts a middleman, a proxy and talks to the server on behalf of client and vice-versa.
That’s why when you’re passing all your traffic through BURP you could see certificate authority as Portswigger on every website that you visit.
A video explaining these details can be found on my channel here :
Unpinning the App
With the basic understanding of SSL pinning. Let’s now start to unpin the app and get it’s HTTPs traffic going through BURP.
The easiest way I have seen to bypass cert pinning is using objection framework.
What’s Objection Framework ?
It’s a framework built on top of Frida ( an instrumentation toolkit ) that helps you hook into functions and libraries very easily. Moreover it has a lot of these ready to use modules for common tasks like ssl unpinning.
The last part in the above video series focuses on using this to ssl unpin Flipkart app.
How do I ssl unpin the app using objection framework ?
First you need to connect your device using usb and enable usb debugging on it. You would also need to run frida server on your mobile phone, it’s easier to do if you’ve a rooted mobile phone else you need to use frida-gadget.
Here is a blogpost explaining the same : Frida’s Gadget Injection on Android: No Root, 2 Methods
After the device is connected to the laptop and frida server is up and running, start the objection framework with the following command :
objection --gadget <app_identifier> explore
You should see a screen similar to the below screenshot. Now to disable SSL pinning all you need to do is run the following command :
android sslpinning disable
This works in most of the cases, some really determined apps might try to thwart this but even that can be worked out by writing some custom frida scripts.
Now traffic started to pour in 🤩
Bug 3 : OTP bypass login into any User’s account
The app had an OTP based login. In BURP Suite I could see the requests going to an amazon API gateway as the URL was of the form :
https://{restapi_id}.execute-api.{region}.amazonaws.com
" "
I saw OTP being sent in the payload request.
So OTP was generated on the mobile itself and sent to the AWS server. The only reason why request was being sent to the server was to send an SMS to the mobile user and when the OTP was sent by the user to verify, an authentication token was generated by the server.
So we’re now able to log in to anyone’s account by just entering their mobile number and intercepting the request being sent. This way we will already have the OTP to log in to the app.
With this account takeover bug we could log in to anyone of the 10M+ accounts using just their mobile number. And the previous data leak helps in getting the mobile number of these customers.
Some other ideas that came to mind after I found this bug were :
- Can we avoid sending the request and silently log in to a victim’s account 🤔 ?
Well this can’t be done because unless that request is sent, the server won’t have the OTP to verify against a mobile user and thus when you next send the verify request, there won’t be any OTP to verify against for the backend. - Can we go on abusing this service and send free SMS to any mobile user ?
This can’t be done easily. The payload signature is also added to the headers. The AWS SDK already handles the signing part. Eventually I figured out how to do this. Will talk about this in detail in the second part.
Bug 4: Reward System & Unlimited Free Coins
There is a reward system in the app, which rewards users coins. These coins could be redeemed to buy subscriptions, which otherwise could also be bought with fiat currency such as INR.
So to buy a subscription you either paid 5000 virtual coin or 1000 Indian rupees.
The fourth bug was adding unlimited coins to the wallet. This bug was critical as it led to financial losses for the company.
How did you exploit it ?
The app had a scratch card feature, which rewarded the user with some in-game coins. You just needed to replay the request to get some coins.
I wrote a python script and automated this to get unlimited coins. This endpoint also had the payload signature checks and hence amazon sdk for python was required. Also some of the values from ‘Constants.java’ file, which I found during the static analysis of the app, was also required.
But where’s frida and bypassing payload checks ?
Well let’s keep that for the next part. In the next part will talk about Frida and amazon’s different services like amazon gateway and cognito.
Summary
This post describes the approach I take when pentesting on an android application. It includes things like :
- Static analysis
- SSL Unpining through Frida
- Dynamic Analysis of app’s network requests
In this process I found and reported 4 critical issues to the company.
Want to learn Android hacking ?
I am still in process of making videos on in depth android hacking, things like exploiting content providers, deeplink issues etc
You can checkout the : [Mobile App Pentesting Series] on my channel.
Thanks. Hope you learnt something.
Bugs are simple. Persistence is the key 😀
Checkout the latest video from the channel :
Twitter : @AseemShrey
Thanks for reading :)