This is a story of how I found a critical bug of one of the biggest GSM Operator in our country.

That bug allows me to log in any user account that I want, without a password.

After logging an account there is endless possibility what you can do, like forwarding all calls, reading his messages, fetching all invoices etc. So, that was a serious BUG and reported to the company immediately. This blog post will not make any disclosure about the company, about the application itself etc. All variable names and method names in the post are changed.

So, how I found the bug?

The story consists of 4 parts. Let me explain step by step.


Part 1- Sniff All Traffic

After downloading their mobile applications to my phone, I started to sniff all traffic of the application.

I used Charles MacBook app to sniff all traffic. All you must do;

Enable SSL sniff option in Charles, note your MacBook local wifi address (alt+wifi icon), set your wifi proxy address as your MacBook local address and set 8080 as port number (port of Charles) in your phone’s wifi configuration.

Alt + wifi icon to get your local address.

Phone WIFI settings to route traffic to Charles.

This is Charles:

Let me clarify some caveats.

You can not sniff SSL traffics unless you trust Charles root certificate on your mobile phone.

Even you trust the root certificate, some applications like Facebook, AppStore etc. use more security protocols like SSL Pinning to block sniffing.

When SSL Pinning in use, the client does not trust your Self-Signed root certificate.

But even SSL Pinning in use, you can bypass it also. Reference 1, Reference 2.

 

Lesson 1) So, you must know that there is no way, NO WAY, no way to block curious eyes to sniff your application network requests. Don’t forget this! Never forget this! Anyone can sniff your all network requests even you use SSL, even you use SSL Pinning! So, do not send critical information as plain texts in your requests!

 


So, after sniffing all traffic the app makes, I first tried to login to my account and I analyzed the network request in Charles.

There was nothing interesting. But after logging in, the app displayed a page with some of the images like rabbit, lion, rose etc.

It is designed for fast login, after you choose an image and want to re-login the app, you just click your security image to login without your password.

The bug was there. When setting security image, I analyzed the network request, there was only my phone number and image_id and some kinda signature in the POST data (I will not share the post data here because of not-disclosure respect). Did you get it? There was not my password in POST data!

I also analyzed what happens when I click my security image, the request consisted of same 3 parameters also to log me fast!

 

Lesson 2) Never trust your clients! Never trust your client’s input values on the request! You are in danger if you think “hashing something” is enough to execute requests!

 


So, I decided to re-simulate the first request in charles (the request when I set my security picture). (to re-simulate a request in charles, just right click on it and click “Compose”, after that, you can easily modify everything like post parameters, url etc. in the request and you can execute it)

Sample composing in Charles:

What I realized when I play with the request is; Whenever I modify “my phone number” OR “my security image id” OR that “signature“, the server simply did not accept my request. So, that signature must consist of “my phone number” and “my security image id”, the server just compare the real signature and client signature in order to continue.

 


Part 2- Decrypting the APP!

The first thing I realized about that signature, it was looking like that: “0b0e2288fc5e619c5587b914cf4830e34e1976b3”, so it has 40 characters, if you ever used some hashing algorithms, you would know that MD5 algorithm creates 32 characters output, SHA-1 algorithm creates 40 characters output etc. So, it is likely they used SHA-1 algorithm to create that signature.

Now, the fun part is here. Let’s decrypt the signed iOS app!

You may heard the jailbroken iOS devices’ capabilities.

The most important part of a jailbroken device for me is the ability to decrypt any app! Normally, you can not decrypt an app which is downloaded from AppStore because Apple signs all applications before distributing them! So, basically, no-one can decrypt an application. But, in jailbreak world, you can bypass Apple’s sign mechanism too!

After you apply jailbreak to your iOS device, activate the SSH and connect it. (this topic is a big topic, maybe I can write some blog about it in the close future)

Get the application’s PID number on your iOS device by looking processes;

ps aux | grep /var/containers/Bundle/Application/

After you find the PID number, it’s time to decrypt it. I personally use bfdecrypt to decrypt apps.

bash bfinject -p APPS_PIDNUMBER -l /bfdecrypt-master/bfdecrypt.dylib -L decrypt

After that command, you will see a message in device logs, something like:

[dumpDecrypted] IPAFile: /var/mobile/Containers/Data/Application/E188FD33-F01B-4F5F-A4D5-F415C3E094D3/Documents/decrypted-app.ipa

 

Go and download the decrypted-app.ipa file to your macbook.

After you download it, change the extension to .zip to unzip it’s contents.

After unzipping, you will see a folder like that:

The folder consists of all images and files app uses, localization files etc. There is also App’s executable file in that folder with the name of: “APPNAME”

 


Part 3- Class Dump All Headers of the APP!

After you got the executable APPNAME file. It’s time to dump all headers of it!

I personally use Class-Dump for this.

Open your MacBook terminal and run this command:

./class-dump APPNAME -o OUTPUT_FOLDER_NAME -H

After that command, there will be a new folder named OUTPUT_FOLDER_NAME, let’s look it’s content!

Can you believe that! I can see your application’s all header files!

I also can see your all method names, your all variables name too!

After looking all header files, I found the method which creates the SHA-1 signature. It was not so hard to find it because the method name was like “createSHA1SignatureStringForPhoneNumber:andPictureId” !

I opened the executable file with IDA, to see what that method is doing step by step, (nowadays, I’m using Hopper instead of IDA)

(I painted important parts with red, sorry, no disclosure!)

So, what is important here, please look number 1 and number 2 parts in red.

In number 1 part , I saw a static string like “35235nnASaf12” and in number 2 part I saw ‘%s%s’ method before returning the signature.

So it means, that method puts 2 string together and creates SHA-1 of them! I got the first string already in number 1 part.

So that method creates SHA-1 like SHA1(“35235nnASaf12+SOME_OTHER_STRING”).

But, how can I see SOME_OTHER_STRING part?

 


Part 4- Injecting into Method

So, at this point, I was very close to understanding how the application creates the signature.

It is time to dive into the method itself! I mean : “createSHA1SignatureStringForPhoneNumber:andPictureId”

I personally use a fantastic tool for that, Cycript

With Cycript, you can inject into processes, you can call any method of the application, you can create Objects which app uses, whatever you want! It’s like the root access for any process and it uses JavaScript syntax!

First, start cycript with the PID number of app.

cycript -p PIDNUMBER

After that, you are like the owner of the app!

You can call any method of the app with any parameters you want;

var data = [[NSFileManager defaultManager] contentsAtPath:@"/bla.txt"];
var f = [[Operation alloc] methodNameWithFile: data];
[f run];

You can get all created objects and get their variables too!

var a = choose(AppOperation)[0];
#"AppOperation: 0x15108b290>"

a.userName;
#"Jesus"

Or you can hook any method of the app with Theos Tweaks!

%hook ClassName

-(id)createSHA1SignatureStringForPhoneNumber:(id)arg1 andPictureId:(id)arg2
{
    //log
    NSLog(@"=================createSHA1SignatureStringForPhoneNumber=================");
    NSLog(@"arg1: %@",[arg1 absoluteString]);
    NSLog(@"arg2: %@",[arg2 absoluteString]);

    // do whatever you want

    //call the main original method
    id mainMethodReturn = %orig;
    NSLog(@"mainMethodReturn: %@", mainMethodReturn);

    return mainMethodReturn;
}

%end

So what happens now? Whenever the app itself calls this method, my hook will be called BEFORE, as you see in my code, I logged all parameters the method receives and after all, I called the main original method, I got it’s response, I logged it and I finally returned that value, so that the application can continue to work!

I finally finished my job! I saw how they created the SHA-1 signature string, it was something like: “THAT_PART1_STRING(35235nnASaf12) + MYPHONENUMBER + SECURITY_IMAGE_ID”

 

Lesson 3) Never do this mistake! If you think creating hash algorithms with some static random strings is enough and will not solvable, you are in a big mistake!

 


 

After all this information, I tested to login my sister’s account with 4 lines PHP code which generates SHA-1 string for the POST data, I was able to login her account without her password!

Timeline1: Bug was reported to the company immediately via email.

Timeline2: They reached me and asked a couple of questions about how I could obtain that static string and SHA-1 algorithm etc.

Timeline3: I summarized them the problem and the bug again.

Timeline4: They returned me back 1 week later and closed the bug.

Award for bug bounty: Come on, this is Turkey BRO 🙂