Home Android Applications Pentesting, Intentional Exercise from Hackerone platform
Post
Cancel

Android Applications Pentesting, Intentional Exercise from Hackerone platform

Today we are going to practice some Android pentesting with a challenge made by Hackerone platform.

I’ll explain different techniques used in Android pentesting with a practical overview.

This article was made for the day 2 of the hack event organised by The Hacking News B’Darija.

Challenge

We can access the challenege using https://ctf.hacker101.com/ctf

image

Intentional Exercise Challenge setup

https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/

1
**Your Android APK is building. Please refresh in a few seconds.**
1
https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/level13.apk

https://book.hacktricks.xyz/mobile-pentesting/android-app-pentesting

Instal the apk using Bluestackes

I didn’t have time to setup a clean setup for an Android emulator on my Linux machine, so i just used my Windows machine with Bluestacks emulator. It’s probably simple to setup Burpsuite proxy with it, right ? :unamused:

After installing the app, we can see it in your app menu.

Pasted image 20220727190015

Proxy setup with Burpsuite

To intercept requests from our android app, I’ll use Burpsuite. You can use the community version it’s free https://portswigger.net/burp

image

We need to set the proxy used by bluestackes using HD-ConfigHttpProxy.exe. You can find it in your application installation.

Pasted image 20220727190717

Now let’s add our burp proxy.

Pasted image 20220727202122

After setting a proxy, you need to restart Bluestacks. You can use the reset option to go back to default settings.

Now we need to :

  • Use BlueStacks Tweaker to root the emulator.

  • Install root certificate manager from the Google Play store.

  • Import the burp certificate. You can export it from the proxy tab.

Intercept requests while opening the app

Before the app shows the webview, we can see a request to https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot?&hash=61f4518d844a9bd27bb971e55a23cd6cf3a9f5ef7f46285461cf6cf135918a1a

Pasted image 20220727202844

Here is the response : 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

HTTP/1.1 200 OK

Date: Wed, 27 Jul 2022 19:29:48 GMT

Content-Type: text/html; charset=utf-8

Content-Length: 64

Connection: close

Server: openresty/1.21.4.1

<h1>Welcome to Level13</h1><a href="appRoot/flagBearer">Flag</a>

After forwarding the requests, let’s see what happens after clicking “Flag.”

Pasted image 20220727203135

We can see a new request to /appRoot/flagBearer same output as our first request. After forwarding the request, we see an output with an invalid request 

Pasted image 20220727203253

Here is the response : 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

HTTP/1.1 200 OK

Date: Wed, 27 Jul 2022 19:32:18 GMT

Content-Type: text/html; charset=utf-8

Content-Length: 15

Connection: close

Server: openresty/1.21.4.1

Invalid request

Now let’s try to analyze what we were able to find :

  • Leaked the used domain : 86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com

  • Hash parametre with /appRoot : hash=61f4518d844a9bd27bb971e55a23cd6cf3a9f5ef7f46285461cf6cf135918a1a

  • openresty/1.21.4.1 : Web server version. It’s probably the load blanacer https://openresty.org/en/

  • The app may be trying to verify a hash token with /appRoot to access/appRoot/flagBearer which is our final access.

  • We can check the links with our browser, It’s seems like the app is using a webview. We can get the same behavior.

Pasted image 20220727204544

We did some testing with the app, now let’s switch to some reversing with the apk file.

What is an apk file ?

A file with the APK file extention is an Android Package file that’s used to distribute apps on Google’s Android operating system

APK files are saved in the ZIP format and are typically downloaded directly to Android devices, usually via Google Play, but can also be found on other websites.

APKLeaks

There is a tool called APKLeaks that helps with getting urls, endpoints, and secrets from our apk files. It’s used by bug bounty hunters  https://github.com/dwisiswant0/apkleaks

Pasted image 20220727214356

As we can see, there are some android xml files and a domain used with a endpoint or maybe a directory /appRoot.

Expectation :

And then you’ll be like, “emm, some juicy cash money for my bug bounty report :smirk: “

Reality : :skull:

Pasted image 20220727213844

Apktool

It’s a tool for reverse engineering Android apk files. We are going to use it to extract files from our apk. You can check the documentation for more details https://ibotpeaches.github.io/Apktool/

You can see instructions here to install it.

As i’m using Kali Linux, there is a package for it. We can use apt to install  sudo apt install apktool

Let’s extract the apk file 

Pasted image 20220727210300

Pasted image 20220727210635

  • The AndroidManifest.xml is important for security research, it’s has the permissions required by the app, which can be abused if it’s not configured properly. We can read more about that  : 

  https://pentestlab.blog/2017/01/24/security-guidelines-for-android-manifest-files/ 

  https://www.briskinfosec.com/blogs/blogsdetail/Android-Manifest-File-Analysis-101

  • Our focus today is the classes.dex file. The code is packed into .dex files. Dex stands for Dalvik Executable. A Dex file contains code that is ultimately executed by the Android Runtime. We can convert dex files to jar files using the dex2jar tool.

Pasted image 20220727211329

Now let’s decompile the jar file using JD-GUI http://java-decompiler.github.io/

Pasted image 20220727211659

As we can see here, the application configuration details.

Now let’s go to our target, the MainActivity.class. It’s like the main code from our Android app. We can read more about Android app development to get more details about it.

MainActivity.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.hacker101.level13;  
  
import android.net.Uri;  
import android.os.Bundle;  
import android.support.v7.app.AppCompatActivity;  
import android.webkit.WebView;  
import android.webkit.WebViewClient;  
import java.math.BigInteger;  
import java.nio.charset.StandardCharsets;  
import java.security.MessageDigest;  
import java.security.NoSuchAlgorithmException;  
  
public class MainActivity extends AppCompatActivity {  
  protected void onCreate(Bundle paramBundle) {  
    super.onCreate(paramBundle);  
    setContentView(2131296284);  
    WebView webView = (WebView)findViewById(2131165328);  
    webView.setWebViewClient(new WebViewClient());  
    Uri uri = getIntent().getData();  
    String str1 = "https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot";  
    String str3 = "";  
    if (uri != null) {  
      str3 = uri.toString().substring(28);  
      StringBuilder stringBuilder = new StringBuilder();  
      stringBuilder.append("https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot");  
      stringBuilder.append(str3);  
      str1 = stringBuilder.toString();  
    }   
    String str2 = str1;  
    if (!str1.contains("?")) {  
      StringBuilder stringBuilder = new StringBuilder();  
      stringBuilder.append(str1);  
      stringBuilder.append("?");  
      str2 = stringBuilder.toString();  
    }   
    try {  
      MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");  
      messageDigest.update("s00p3rs3cr3tk3y".getBytes(StandardCharsets.UTF_8));  
      messageDigest.update(str3.getBytes(StandardCharsets.UTF_8));  
      byte[] arrayOfByte = messageDigest.digest();  
      BigInteger bigInteger = new BigInteger();  
      this(1, arrayOfByte);  
      String str = String.format("%064x", new Object[] { bigInteger });  
      StringBuilder stringBuilder = new StringBuilder();  
      this();  
      stringBuilder.append(str2);  
      stringBuilder.append("&hash=");  
      stringBuilder.append(str);  
      webView.loadUrl(stringBuilder.toString());  
    } catch (NoSuchAlgorithmException noSuchAlgorithmException) {  
      noSuchAlgorithmException.printStackTrace();  
    }   
  }  
}

Now we have the source code what to do ?

Pasted image 20220727212805

It’s just the app code for us x)

As we see from our first interaction with app http requests, we need to understand how to get the hash to access /appRoot/flagBearer or maybe use it for other things.

Start analyzing

  • First we can see the libraires imported and used.
  • The app sets a webview to be able to see urls.
  • Start to build a url insied URI class probably https://developer.android.com/reference/java/net/URI

We can see the code when URI is null

1
2
3
4
5
6
7
    if (uri != null) {  
      str3 = uri.toString().substring(28);  
      StringBuilder stringBuilder = new StringBuilder();  
      stringBuilder.append("https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot");  
      stringBuilder.append(str3);  
      str1 = stringBuilder.toString();  
    }
  • str1 = “https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot”;
  • build the str2 with str1 + append “?”
  • Try to do some fancy encryption for a string to convert it to a hash and build the final URL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    try {  
      MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");  
      messageDigest.update("s00p3rs3cr3tk3y".getBytes(StandardCharsets.UTF_8));  
      messageDigest.update(str3.getBytes(StandardCharsets.UTF_8));  
      byte[] arrayOfByte = messageDigest.digest();  
      BigInteger bigInteger = new BigInteger();  
      this(1, arrayOfByte);  
      String str = String.format("%064x", new Object[] { bigInteger });  
      StringBuilder stringBuilder = new StringBuilder();  
      this();  
      stringBuilder.append(str2);  
      stringBuilder.append("&hash=");  
      stringBuilder.append(str);  
      webView.loadUrl(stringBuilder.toString());  
    } catch (NoSuchAlgorithmException noSuchAlgorithmException) {  
      noSuchAlgorithmException.printStackTrace();  
    }

If you can’t understand what the code does, you can simply create a Java code and start importing the used libraries and print each line to see the output. We need to add used string variables and also set a URI value for testing.

1
2
3
4
5
6
7
8
9
10
11
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
class test {
    public static void main(String[] args) {
    // here we need to the add used URI and string values.
    // put the try catch and start analysing using System.out.println()
    }
    
    }

After doing some testing, let’s get back to our way of finding the hash.

  • for URI, I abused the function that shows how the URI is built if it’s null.
1
2
3
4
5
6
7
    if (uri != null) {  
      str3 = uri.toString().substring(28);  
      StringBuilder stringBuilder = new StringBuilder();  
      stringBuilder.append("https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot");  
      stringBuilder.append(str3);  
      str1 = stringBuilder.toString();  
    }

As we can see, it does a substring of 28 and takes the last part https://www.javatpoint.com/substring

1
2
3
4
5
6
7
class test {
    public static void main(String[] args) {
        String URI = "AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBB";
        System.out.println(URI.toString().substring(28));
        
        }
}
1
BBBBBBB

for the str1 we have an URL + str3 (URI.toString().substring(28))

1
https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot + str3

We use “BBBB” for str3 at the moment. We can see that the beginning is probably a “/”

Now str1 = https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot/BBBB

The str2 is str1 + “?”

1
https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot/BBBB?

At the encryption part, we can see that the code appends another &hash= and the hash value to the final string.

1
2
3
      stringBuilder.append(str2);  
      stringBuilder.append("&hash=");  
      stringBuilder.append(str);
1
https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot/BBBB?hash=X

It looks familiar, right ? If we go back to our requests analysis at the beginning, we can see the same format.

1
https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot?&hash=61f4518d844a9bd27bb971e55a23cd6cf3a9f5ef7f46285461cf6cf135918a1a

For the BBBB part, it’s possible that it has flagBearer or /appRoot/flagBearer. URI Format can be URL/appRoot/flagBearer

Now let’s go for our solution. I used the same Main code with some modifications to get our hash. We can use an online Java compiler or execute it from your system if you have Java installed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


class get_hash {
    public static void main(String[] args) {
    String uri = "AAAAAAAAAAAAAAAAAAAAAAAAAAAA/flagBearer";
    String str1 = "https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot";
    String str3 = "";
    if (uri != null) {
      str3 = uri.toString().substring(28);
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append("https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot");
      stringBuilder.append(str3);
      str1 = stringBuilder.toString();
    } 
    String str2 = str1;
    if (!str1.contains("?")) {
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append(str1);
      stringBuilder.append("?");
      str2 = stringBuilder.toString();
    } 
    try {
      MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
      messageDigest.update("s00p3rs3cr3tk3y".getBytes(StandardCharsets.UTF_8));
      messageDigest.update(str3.getBytes(StandardCharsets.UTF_8));
      byte[] arrayOfByte = messageDigest.digest();
      BigInteger bigInteger = new BigInteger(1, arrayOfByte);
      String str = String.format("%064x", new Object[] { bigInteger });
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append(str2);
      stringBuilder.append("&hash=");
      stringBuilder.append(str);
      System.out.println(stringBuilder.toString());
    } catch (NoSuchAlgorithmException noSuchAlgorithmException) {
      noSuchAlgorithmException.printStackTrace();
    } 
  }
}

Output

1
https://86c65fe0ecf5117f91f7d2eaf9adf25e.ctf.hacker101.com/appRoot/flagBearer?&hash=8743a18df6861ced0b7d472b34278dc29abba81b3fa4cf836013426d6256bd5e

Let’s visit the url

Pasted image 20220727222124

We were able to solve the challenge with right hash value.

Conclusion

I hope you find this article useful. You can learn more about Android application pentesting. There are many interesting attacks. You can take a look at :

  • https://book.hacktricks.xyz/mobile-pentesting/android-app-pentesting
  • ANDROID APP SECURITY BASICS https://www.youtube.com/watch?v=a8Gh7d8GebA
  • HACKING ANDROID WebViews https://www.youtube.com/watch?v=qS5PkC-37io
This post is licensed under CC BY 4.0 by the author.

IoT Pentesting with Teltonika RUT9XX

Bypass captcha using OCR on Dolibarr login page