security: fix CVE-2024-47077 (#11535)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
		@ -29,7 +29,6 @@ class TesOAuth2Introspection(OAuthTestCase):
 | 
			
		||||
        self.app = Application.objects.create(
 | 
			
		||||
            name=generate_id(), slug=generate_id(), provider=self.provider
 | 
			
		||||
        )
 | 
			
		||||
        self.app.save()
 | 
			
		||||
        self.user = create_test_admin_user()
 | 
			
		||||
        self.auth = b64encode(
 | 
			
		||||
            f"{self.provider.client_id}:{self.provider.client_secret}".encode()
 | 
			
		||||
@ -114,6 +113,41 @@ class TesOAuth2Introspection(OAuthTestCase):
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_introspect_invalid_provider(self):
 | 
			
		||||
        """Test introspection (mismatched provider and token)"""
 | 
			
		||||
        provider: OAuth2Provider = OAuth2Provider.objects.create(
 | 
			
		||||
            name=generate_id(),
 | 
			
		||||
            authorization_flow=create_test_flow(),
 | 
			
		||||
            redirect_uris="",
 | 
			
		||||
            signing_key=create_test_cert(),
 | 
			
		||||
        )
 | 
			
		||||
        auth = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()
 | 
			
		||||
 | 
			
		||||
        token: AccessToken = AccessToken.objects.create(
 | 
			
		||||
            provider=self.provider,
 | 
			
		||||
            user=self.user,
 | 
			
		||||
            token=generate_id(),
 | 
			
		||||
            auth_time=timezone.now(),
 | 
			
		||||
            _scope="openid user profile",
 | 
			
		||||
            _id_token=json.dumps(
 | 
			
		||||
                asdict(
 | 
			
		||||
                    IDToken("foo", "bar"),
 | 
			
		||||
                )
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        res = self.client.post(
 | 
			
		||||
            reverse("authentik_providers_oauth2:token-introspection"),
 | 
			
		||||
            HTTP_AUTHORIZATION=f"Basic {auth}",
 | 
			
		||||
            data={"token": token.token},
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(res.status_code, 200)
 | 
			
		||||
        self.assertJSONEqual(
 | 
			
		||||
            res.content.decode(),
 | 
			
		||||
            {
 | 
			
		||||
                "active": False,
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_introspect_invalid_auth(self):
 | 
			
		||||
        """Test introspect (invalid auth)"""
 | 
			
		||||
        res = self.client.post(
 | 
			
		||||
 | 
			
		||||
@ -46,10 +46,10 @@ class TokenIntrospectionParams:
 | 
			
		||||
        if not provider:
 | 
			
		||||
            raise TokenIntrospectionError
 | 
			
		||||
 | 
			
		||||
        access_token = AccessToken.objects.filter(token=raw_token).first()
 | 
			
		||||
        access_token = AccessToken.objects.filter(token=raw_token, provider=provider).first()
 | 
			
		||||
        if access_token:
 | 
			
		||||
            return TokenIntrospectionParams(access_token, provider)
 | 
			
		||||
        refresh_token = RefreshToken.objects.filter(token=raw_token).first()
 | 
			
		||||
        refresh_token = RefreshToken.objects.filter(token=raw_token, provider=provider).first()
 | 
			
		||||
        if refresh_token:
 | 
			
		||||
            return TokenIntrospectionParams(refresh_token, provider)
 | 
			
		||||
        LOGGER.debug("Token does not exist", token=raw_token)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								website/docs/security/CVE-2024-47077.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								website/docs/security/CVE-2024-47077.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
# CVE-2024-47077
 | 
			
		||||
 | 
			
		||||
_Reported by [@quentinmit](https://github.com/quentinmit)_
 | 
			
		||||
 | 
			
		||||
## Insufficient cross-provider token validation during introspection
 | 
			
		||||
 | 
			
		||||
### Summary
 | 
			
		||||
 | 
			
		||||
Access tokens issued to one application can be stolen by that application and used to impersonate the user against any other proxy provider. Also, a user can steal an access token they were legitimately issued for one application and use it to access another application that they aren't allowed to access.
 | 
			
		||||
 | 
			
		||||
### Details
 | 
			
		||||
 | 
			
		||||
The proxy provider uses `/application/o/introspect/` to validate bearer tokens provided in the `Authorization` header:
 | 
			
		||||
 | 
			
		||||
The implementation of this endpoint separately validates the `client_id` and `client_secret` (which are that of the proxy provider) and the `token` without validating that they correspond to the same provider.
 | 
			
		||||
 | 
			
		||||
### Patches
 | 
			
		||||
 | 
			
		||||
authentik 2024.6.5 and 2024.8.3 fix this issue.
 | 
			
		||||
 | 
			
		||||
### For more information
 | 
			
		||||
 | 
			
		||||
If you have any questions or comments about this advisory:
 | 
			
		||||
 | 
			
		||||
-   Email us at [security@goauthentik.io](mailto:security@goauthentik.io)
 | 
			
		||||
@ -521,6 +521,7 @@ const docsSidebar = {
 | 
			
		||||
            items: [
 | 
			
		||||
                "security/security-hardening",
 | 
			
		||||
                "security/policy",
 | 
			
		||||
                "security/CVE-2024-47077",
 | 
			
		||||
                "security/CVE-2024-42490",
 | 
			
		||||
                "security/CVE-2024-38371",
 | 
			
		||||
                "security/CVE-2024-37905",
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user