Hackerone H101 Android Challenges Walkthrough

June 13, 2020

I have recently completed the H101 CTF Android challenges. It was really fun learning and completing the challenges, so here's the writeup.

1) H1 Thermostat

The first challenge is in the easy category which was basically about intercepting traffic and reading source code in the APK.

In this case, we decompile the APK and inspect it. After analyzing the files, you can see a Java class named com.hacker101.level11.PayloadRequest.

H1 Thermostat Challenge Screenshot

Once we open it, we can see flag 0 and flag 1. But for flag 0, there was one more way around - if you had intercepted the traffic for the application, then you would have found the header as flag too:

X-Flag: ^FLAG^flag$FLAG$

Also in the source code, we can see that flag 1 is MD5 hashed and then sent to the server, so the only way was through reading the source code.

2) Intentional Exercise

The exercise was in the moderate category where the goal of the challenge was to get a single flag by generating a correct hash for the request.

Once we open the app, we can see a request going to the server like:

http://URL/appRoot?&hash=61f4518d844a9bd27bb971e55a23cd6cf3a9f5ef7f46285461cf6cf135918a1a

This displays a link /appRoot/flagBearer. The important clues we get are from inspection of the Java class - we can see that the URL is first taken, checked for ?, then using the secret key a hash is generated of type SHA-256. But in the first request we can see that hash=61.... is SHA-256 of the key itself, so that won't work.

Intentional Exercise MainActivity Code

So we also got our second request which was having a path /flagBearer.

Combining the two things, I tried doing SHA-256 by (key/flagBearer) which gave a hash:

8743a18df6861ced0b7d472b34278dc29abba81b3fa4cf836013426d6256bd5e

So I made a final request which looked like:

http://URL/appRoot/flagBearer?&hash=8743a18df6861ced0b7d472b34278dc29abba81b3fa4cf836013426d6256bd5e

Sending it to the server gave me the flag: ^FLAG^flag$FLAG$

3) Oauthbreaker

This was a moderate challenge containing two flags. When we open the app, we can see the request containing:

OAuth Challenge Request Analysis
/oauth?redirect_url=oauth%3A%2F%2Ffinal%2Flogin&response_type=token&scope=all

Inspecting the MainActivity class, we can see that redirect_uri is by default given the value of oauth://final/ which redirects it to the app with an authed request. So if we remove the redirect_uri parameter (i.e., sending blank values in it):

http://url/oauth?redirect_url=&response_type=token&scope=all

We get our first flag in response.

OAuth First Flag Response

For the second flag, we need to look at our WebAppInterface. Here we have a Java class which is not used anywhere, so I took the file and compiled it by adding few variables and executed it.

WebAppInterface Code Implementation

This gave me 48ce----.html

Now when we add this URL to our previous redirect_uri, we get our second flag: ^FLAG^flag$FLAG$

4) Mobile Webdev

This was the most awesome challenge which helped me to clear some of my doubts and learn good techniques on HMAC and zip files. The challenge was more a web category and some cryptography.

As we open the application, we can see it as a notesaver application where we can see the notes and edit them. As we analyze requests, we can see that these directories are used:

Among the four, all the functions were working normally except the upload function. Every time I tried uploading something, it gave me an error of HMAC missing.

Upon analyzing the APK, we can see that we have an HMAC key but no implementation visible of how to send it in the request.

HMAC Key in APK Analysis

To send any POST upload, the request would normally look like:

-----------------------------2220428816716698861687125981
Content-Disposition: form-data; name="file"; filename="file.file"
Content-Type: application/html

-----------------------------2220428816716698861687125981
Content-Disposition: form-data; name="something"

value
-----------------------------2220428816716698861687125981--

So we basically have to upload a file which was signed by our HMAC key. Also, we need to find the type of key that was used - in this case it was MD5. So concluding, we had to send our file and signature values signed with our keys. This can be done online as well as with our own script.

The final request of upload looked like:

-----------------------------2220428816716698861687125981
Content-Disposition: form-data; name="file"; filename="file.file"
Content-Type: application/html

-----------------------------2220428816716698861687125981
Content-Disposition: form-data; name="hmac"

signaturevalue
-----------------------------2220428816716698861687125981--

Once we uploaded the flag, we got our first flag and the message.

File Upload Success Message

This was our hint for the second level that files are uploaded in temp directory and we have to move to content folder. Basically it indicated a popular flaw of zip traversal:

If zip files are not properly handled in extraction and compression, they may lead to directory traversal. So in this case, we can fetch our files and even get sensitive information.

So I created a zip nested with zips (else you can use an online tool) such case of a zip-slip file which upon viewing should look like: ../../../../../../temp/test.zip

Next, I signed this zip again and uploaded it which finally gave me the flag.

Final Flag Achievement

Conclusion

Thanks for reading! If you have any doubts, feel free to connect with me.