ADVISORIES
CVE-2020-13294
The following (slightly modified) advisory was sent to GitLab using Hackerone on 19th June 2020.
During the Responsible Disclosure process it turned out, that the vulnerability was known for quite some time. After elaborating further on the impact, a security release fixed the issue after few weeks.
The final security patch was released on 5th August 2020 in GitLab 13.2.3, 13.1.6 and 13.0.12: https://about.gitlab.com/releases/2020/08/05/gitlab-13-2-3-released/.
Acknowledgment
We made the observations within this advisory during the research for my master’s thesis on “Single Sign-On Security: Security Analysis of real-life OpenID Connect Implementations”. The thesis was written at the chair for network and data security of Ruhr University Bochum.
The advisors of my thesis are Dr.-Ing. Christian Mainka (@CheariX), Dr.-Ing. Vladislav Mladenov (@v_mladenov) and Prof. Dr. Jörg Schwenk (@JoergSchwenk). Huge “Thank you” for your continuous support! 🙂
Additionally, there is a blog post by Max Moroz (@Dor3s) which covers multiple OAuth 2.0 vulnerability patterns, including the described issue within this advisory: https://blog.avuln.com/article/4.
Advisory
GitLab can be configured to act as OpenID Connect Identity Provider. If this is the case, in a Single Sign-On scenario a relying party allows GitLab users to sign in using their existing account.
As defined within the OpenID Connect specification, the user has to give explicit consent which information is shared with the relying party [1]:
Once the End-User is authenticated, the Authorization Server MUST obtain an authorization decision before releasing information to the Relying Party. When permitted by the request parameters used, this MAY be done through an interactive dialogue with the End-User that makes it clear what is being consented to or by establishing consent via conditions for processing the request or other means (for example, via previous administrative consent). […]
GitLab implements the following dialog to ask End-Users for consent:
Additionally, GitLab allows users to revoke their consent for already granted accesses:
But if a user gave consent once, starts a new OIDC Authentication Flow and then revokes consent after a fresh code
was issued to the Relying Party, the code
is not correctly revoked and can be redeemed for an id_token
and access_token
/refresh_token
at GitLab’s Token Endpoint [3]. Even worse: The revoked authorized Application reappears at the “Authorized applications” section and restores the previously granted permissions persistently.
Steps to Reproduce
Prerequisite: The user has to give consent to share information with the Relying Party once - i.e. the users logs in at the Service Provider using his GitLab account:
0) Start an OpenID Connect Login flow from your Service Provider (in our example a Keycloak instance).
1) At first we enable Burp to intercept all request. The users starts an OIDC authentication flow at the Service Provider. We manually forward all requests up to the “Token Request” [2]. We save this request for later use (by sending it to Burp’s “Repeater”) and drop it at the “Intercept” tab. Afterwards we disable the interception mode.
2) At GitLab the user revokes the Authorization for the Application
3) Afterwards the saved “Token Request” from (1) is send to GitLab’s Token Endpoint http://gitlab.local/oauth/token - we observe that we actually receive fresh tokens and an id_token
from GitLab in response.
Token Request to GitLab’s Token Endpoint including the previously issued code:
POST /oauth/token HTTP/1.1
Authorization: Basic NDMzODI5ZjA3NTU1ODMwMjBlNmQ4ZWE4ZjEyOTdiZThiYWIyNzZiYmExMzY5YjMxNDFiZDk0NzFjNDM1NjI3MjowNzUxZDA3ZGQ4MjhhNThlYTllOTBjMmZmY2E0NmMzZTI2NjUyOTc2NDE5NDU0MmRkODU5ZTA4OWI2N2Q1MTA5
Content-Length: 205
Content-Type: application/x-www-form-urlencoded
Host: gitlab.local
User-Agent: Apache-HttpClient/4.5.11 (Java/11.0.7)
Accept-Encoding: gzip, deflate
Connection: close
code=c62e12a4c91c9a1094094d9aa5aa23e15edf81c8fa2adbc26a7abe8fd9f642b7&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fkeycloak-sp.local%3A9443%2Fauth%2Frealms%2Fmaster%2Fbroker%2Fgitlab%2Fendpoint
Token Response from GitLab including a fresh access_token
, id_token
and refresh_token
:
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 30 Jun 2020 14:53:36 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1410
Connection: close
Cache-Control: private, no-store
Etag: W/"7a1e2794759f2112401694c0f9b43b19"
Pragma: no-cache
X-Request-Id: B0Qz8kKu2G4
X-Runtime: 0.053147
Strict-Transport-Security: max-age=31536000
Referrer-Policy: strict-origin-when-cross-origin
{"access_token":"5af0cf103a8ef42169ced90c29854726afdcbb9a9248e6f599be2d8bf09ce81f","token_type":"Bearer","refresh_token":"4fc644703d1f34a7df5939ffd22cd4bea7435a346ac0e614da4f13262719a68c","scope":"openid","created_at":1593528816,"id_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InNfT3NfWE93d2ZjN18xMUV2SlM0VUVOeFR5aTMtVTF5dk83R2gxOTNpdE0ifQ.eyJpc3MiOiJodHRwOi8vZ2l0bGFiLmxvY2FsIiwic3ViIjoiMSIsImF1ZCI6IjQzMzgyOWYwNzU1NTgzMDIwZTZkOGVhOGYxMjk3YmU4YmFiMjc2YmJhMTM2OWIzMTQxYmQ5NDcxYzQzNTYyNzIiLCJleHAiOjE1OTM1Mjg5MzYsImlhdCI6MTU5MzUyODgxNiwibm9uY2UiOiIxeE4yTnpzdUJ1dG5BQUw0TlhkQ1NRIiwiYXV0aF90aW1lIjoxNTkzNTI1ODIwLCJzdWJfbGVnYWN5IjoiMWYyOThjOTk4NDlkYjc2MjhlYjFmNWRkMWUzMDJiY2NhNzNlNTFkZTA1YzZlODdkZmYyMzZmOGQ0YzVjZDJhNCJ9.YfGdgk86KCY_z6p9Jz2IZKYqSLcyaMw9vdmCgsvl79DER-4sd3vxVDHSLJw95_ym5aLekcjGBYkp4TcAG-KshACpChh0S4fpQMRkESPrXWmpetbSuWvGf-Yus-pbiWlOfDYL_DNQj77B4Tn1aPtY0eWsYksDlzqawr1pCZYU18zOOEd_77l5Ec4im28sOQWORPIWbrHcprByraNnGCzSRyMnJ0OFREm9Na8plffTVbjFo0-5UG5X_hGhEY7nZZ365Fi-MUaGQAuVz0AE__mTL6lNKtBnwoJmNgmFebfd_qpyXRLoj4KM3QmIa9PNkDVO8NHCDnvKyZDzZGTNXvqgshaG0TD-pYKmDQo0r2fni2pK3jU3u5oQusNba4M8n13i7I-BkoDQ8cWIdz3TaanIYcHn9WUAGChTXTPo8j1d3z_U4Cua6juTDgR7_uGsJ2M_VQrh-_35m-W9Q7K7FFuM22tB14DxEQ6rcaE13sXTEM2TGx7M8Dc6OkZ_isiRGauSQrSjMbi2MZ-Rq9INfAN5FqroSiKy7HNuWswqBIGCFOabhdTstRC69-UkCDjE_9QdZOqq66xyjTR6VamAqYw4u8o-KUD8CrU3eXFfI_bU_lAw4lSYHbhagWLPwro57s28Ub_k8FzQgpY_LZElF4KpoEtxFaTIzui2D_r26eWm3lQ"}
4) Finally, if we refresh GitLab’s Application overview (http://gitlab.local/profile/applications) we observe that the revoked Authorization reappeared.
Impact
A maliciously acting Service Provider could obtain sensitive data (id_token
) and Bearer tokens (access_token
/refresh_token
) without user’s consent (as the consent was explicitly revoked beforehand). Even worse, the malicious actor may restore the previously given and then revoked consent persistently, resulting in future access to resources and information.
Note: I am not a lawyer. Nevertheless, my naïve legal perspective on this vulnerability is described in the following.
Consent is a central aspect of the GDPR, without explicit consent no personal data is allowed to be processed or shared. Users may revoke their consent at any time, entities processing the data must not proceed after this point in time.
If you apply this to GitLab’s behavior, GitLab initially asks for consent to share personal data (i.e. the id_token
) with third parties (the Service Provider).
But: Due to this flaw, GitLab proceeds sharing personal data, if the user has explicitly revoked consent for this.
Mitigation
In order to mitigate the above described issue, all tokens and code values issued for a Client need to be invalidated if an End-User revokes the permissions for this Client.
References
[1] https://openid.net/specs/openid-connect-core-1_0.html#Consent
[2] https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
[3] https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
Responsible Disclosure
- 30th June 2020: [LH] Initial Report via Hackerone: https://hackerone.com/reports/912001
- 3rd July 2020: [GL] The report is closed as
Informative
. GitLab Staff outlines:
As was mentioned in your other recent OIDC reports, we do not consider rogue identity providers to be part of our threat model
- 3rd July 2020: [LH] Clarification: The report considers a rogue Service Provider as attacker model.
- 4th July 2020: [GL] Acknowledge mistake, report is still considered
informative
. There will be internal discussion. - 8th July 2020: [LH] Request Update.
- 10th July 2020: [GL] No news to share, still considered
informative
. - 17th July 2020: [LH] Request update, provide PoC including detailed retest environment based on https://github.com/lauritzh/oidc-custom-sp
- 17th July 2020: [GL] Report is reopened and immediately closed as duplicate to https://hackerone.com/reports/469728 - at this point no invitation to initial report.
- 17th July 2020: [LH] Ask for invitation to original report.
- 20th July 2020: [LH] Add GDPR perspective to report, as based on report ID, the original report is apparently ~2 years old.
- 22nd July 2020: [GL] Invitation to original report
- 5th August 2020: [GL] GitLab Security Release, Release notes acknowledge support:
Thanks @benaubin, @whitehattushu, and @lauritz for responsibly reporting this vulnerability to us.
https://about.gitlab.com/releases/2020/08/05/gitlab-13-2-3-released/
- 29th October 2020: [GL] GitLab issue becomes public https://gitlab.com/gitlab-org/gitlab/-/issues/26147
- 1st November 2020: [LH] This advisory is published.