From 00ae97944ac21c4835127092287e6057d877fd27 Mon Sep 17 00:00:00 2001 From: "gcp-cherry-pick-bot[bot]" <98988430+gcp-cherry-pick-bot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 18:32:03 +0100 Subject: [PATCH] providers/oauth2: fix CVE-2024-21637 (cherry-pick #8104) (#8105) * providers/oauth2: fix CVE-2024-21637 (#8104) Signed-off-by: Jens Langhammer * update changelog Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer Co-authored-by: Jens L --- .../providers/oauth2/tests/test_authorize.py | 19 +++++++ authentik/providers/oauth2/views/authorize.py | 12 ++-- authentik/providers/oauth2/views/token.py | 6 ++ website/docs/releases/2023/v2023.10.md | 56 +++++++++++++++++++ website/docs/security/CVE-2024-21637.md | 39 +++++++++++++ website/sidebars.js | 1 + 6 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 website/docs/security/CVE-2024-21637.md diff --git a/authentik/providers/oauth2/tests/test_authorize.py b/authentik/providers/oauth2/tests/test_authorize.py index 91cdc330a..fcaddff7c 100644 --- a/authentik/providers/oauth2/tests/test_authorize.py +++ b/authentik/providers/oauth2/tests/test_authorize.py @@ -85,6 +85,25 @@ class TestAuthorize(OAuthTestCase): ) OAuthAuthorizationParams.from_request(request) + def test_blocked_redirect_uri(self): + """test missing/invalid redirect URI""" + OAuth2Provider.objects.create( + name=generate_id(), + client_id="test", + authorization_flow=create_test_flow(), + redirect_uris="data:local.invalid", + ) + with self.assertRaises(RedirectUriError): + request = self.factory.get( + "/", + data={ + "response_type": "code", + "client_id": "test", + "redirect_uri": "data:localhost", + }, + ) + OAuthAuthorizationParams.from_request(request) + def test_invalid_redirect_uri_empty(self): """test missing/invalid redirect URI""" provider = OAuth2Provider.objects.create( diff --git a/authentik/providers/oauth2/views/authorize.py b/authentik/providers/oauth2/views/authorize.py index 520f02d65..6bb66be43 100644 --- a/authentik/providers/oauth2/views/authorize.py +++ b/authentik/providers/oauth2/views/authorize.py @@ -75,6 +75,7 @@ PLAN_CONTEXT_PARAMS = "goauthentik.io/providers/oauth2/params" SESSION_KEY_LAST_LOGIN_UID = "authentik/providers/oauth2/last_login_uid" ALLOWED_PROMPT_PARAMS = {PROMPT_NONE, PROMPT_CONSENT, PROMPT_LOGIN} +FORBIDDEN_URI_SCHEMES = {"javascript", "data", "vbscript"} @dataclass(slots=True) @@ -175,6 +176,10 @@ class OAuthAuthorizationParams: self.check_scope() self.check_nonce() self.check_code_challenge() + if self.request: + raise AuthorizeError( + self.redirect_uri, "request_not_supported", self.grant_type, self.state + ) def check_redirect_uri(self): """Redirect URI validation.""" @@ -212,10 +217,9 @@ class OAuthAuthorizationParams: expected=allowed_redirect_urls, ) raise RedirectUriError(self.redirect_uri, allowed_redirect_urls) - if self.request: - raise AuthorizeError( - self.redirect_uri, "request_not_supported", self.grant_type, self.state - ) + # Check against forbidden schemes + if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES: + raise RedirectUriError(self.redirect_uri, allowed_redirect_urls) def check_scope(self): """Ensure openid scope is set in Hybrid flows, or when requesting an id_token""" diff --git a/authentik/providers/oauth2/views/token.py b/authentik/providers/oauth2/views/token.py index 93578d6ce..2fdf3201b 100644 --- a/authentik/providers/oauth2/views/token.py +++ b/authentik/providers/oauth2/views/token.py @@ -6,6 +6,7 @@ from hashlib import sha256 from re import error as RegexError from re import fullmatch from typing import Any, Optional +from urllib.parse import urlparse from django.http import HttpRequest, HttpResponse from django.utils import timezone @@ -54,6 +55,7 @@ from authentik.providers.oauth2.models import ( RefreshToken, ) from authentik.providers.oauth2.utils import TokenResponse, cors_allow, extract_client_auth +from authentik.providers.oauth2.views.authorize import FORBIDDEN_URI_SCHEMES from authentik.sources.oauth.models import OAuthSource from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS @@ -205,6 +207,10 @@ class TokenParams: ).from_http(request) raise TokenError("invalid_client") + # Check against forbidden schemes + if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES: + raise TokenError("invalid_request") + self.authorization_code = AuthorizationCode.objects.filter(code=raw_code).first() if not self.authorization_code: LOGGER.warning("Code does not exist", code=raw_code) diff --git a/website/docs/releases/2023/v2023.10.md b/website/docs/releases/2023/v2023.10.md index 755cd09e3..dfdbed1a1 100644 --- a/website/docs/releases/2023/v2023.10.md +++ b/website/docs/releases/2023/v2023.10.md @@ -137,6 +137,62 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2023.10 - web/admin: fix @change handler for ak-radio elements (#7348) - web/admin: fix role form reacting to enter (#7330) +## Fixed in 2023.10.3 + +- ci: explicitly give write permissions to packages (cherry-pick #7428) (#7430) +- core: fix worker beat toggle inverted (cherry-pick #7508) (#7509) +- events: fix gdpr compliance always running (cherry-pick #7491) (#7505) +- providers/oauth2: set auth_via for token and other endpoints (cherry-pick #7417) (#7427) +- providers/proxy: fix closed redis client (cherry-pick #7385) (#7429) +- root: Improve multi arch Docker image build speed (cherry-pick #7355) (#7426) +- sources/oauth: fix patreon (cherry-pick #7454) (#7456) +- stages/email: fix duplicate querystring encoding (cherry-pick #7386) (#7425) +- web: bugfix: broken backchannel selector (cherry-pick #7480) (#7507) +- web/admin: fix html error on oauth2 provider page (cherry-pick #7384) (#7424) +- web/flows: attempt to fix bitwareden android compatibility (cherry-pick #7455) (#7457) + +## Fixed in 2023.10.4 + +- ci: fix permissions for release pipeline to publish binaries (cherry-pick #7512) (#7621) +- core: bump golang from 1.21.3-bookworm to 1.21.4-bookworm (cherry-pick #7483) (#7622) +- events: don't update internal service accounts unless needed (cherry-pick #7611) (#7640) +- events: fix missing model\_\* events when not directly authenticated (cherry-pick #7588) (#7597) +- events: sanitize functions (cherry-pick #7587) (#7589) +- providers/proxy: Fix duplicate cookies when using file system store. (cherry-pick #7541) (#7544) +- providers/scim: fix missing schemas attribute for User and Group (cherry-pick #7477) (#7596) +- root: specify node and python versions in respective config files, deduplicate in CI (#7620) +- security: fix [CVE-2023-48228](../../security/CVE-2023-48228.md), Reported by [@Sapd](https://github.com/Sapd) (#7666) +- stages/email: use uuid for email confirmation token instead of username (cherry-pick #7581) (#7584) +- web/admin: fix admins not able to delete MFA devices (#7660) + +## Fixed in 2023.10.5 + +- blueprints: improve file change handler (cherry-pick #7813) (#7934) +- events: add better fallback for sanitize_item to ensure everything can be saved as JSON (cherry-pick #7694) (#7937) +- events: fix lint (#7700) +- events: include user agent in events (cherry-pick #7693) (#7938) +- providers/scim: change familyName default (cherry-pick #7904) (#7930) +- root: don't show warning when app has no URLs to import (cherry-pick #7765) (#7935) +- root: Fix cache related image build issues (cherry-pick #7831) (#7932) +- stages/email: improve error handling for incorrect template syntax (cherry-pick #7758) (#7936) +- tests: fix flaky tests (cherry-pick #7676) (#7939) +- web: dark/light theme fixes (#7872) +- web: fix overflow glitch on ak-page-header (cherry-pick #7883) (#7931) +- web/admin: always show oidc well-known URL fields when they're set (#7560) +- web/user: fix search not updating app (cherry-pick #7825) (#7933) + +## Fixed in 2023.10.6 + +- core: fix PropertyMapping context not being available in request context +- outposts: disable deployment and secret reconciler for embedded outpost in code instead of in config (cherry-pick #8021) (#8024) +- outposts: fix Outpost reconcile not re-assigning managed attribute (cherry-pick #8014) (#8020) +- providers/oauth2: fix [CVE-2024-21637](../../security/CVE-2024-21637.md), Reported by [@lauritzh](https://github.com/lauritzh) (#8104) +- providers/oauth2: remember session_id from initial token (cherry-pick #7976) (#7977) +- providers/proxy: use access token (cherry-pick #8022) (#8023) +- rbac: fix error when looking up permissions for now uninstalled apps (cherry-pick #8068) (#8070) +- sources/oauth: fix missing get_user_id for OIDC-like sources (Azure AD) (#7970) +- web/flows: fix device picker incorrect foreground color (cherry-pick #8067) (#8069) + ## API Changes #### What's New diff --git a/website/docs/security/CVE-2024-21637.md b/website/docs/security/CVE-2024-21637.md new file mode 100644 index 000000000..f7322ed2e --- /dev/null +++ b/website/docs/security/CVE-2024-21637.md @@ -0,0 +1,39 @@ +# CVE-2024-21637 + +_Reported by [@lauritzh](https://github.com/lauritzh)_ + +## XSS in Authentik via JavaScript-URI as Redirect URI and form_post Response Mode + +### Summary + +Given an OAuth2 provider configured with allowed redirect URIs set to `*` or `.*`, an attacker can send an OAuth Authorization request using `response_mode=form_post` and setting `redirect_uri` to a malicious URI, to capture authentik's session token. + +### Patches + +authentik 2023.8.6 and 2023.10.6 fix this issue. + +### Impact + +The impact depends on the attack scenario. In the following I will describe the two scenario that were identified for Authentik. + +#### Redirect URI Misconfiguration + +While advising that this may cause security issues, Authentik generally allows wildcards as Redirect URI. Therefore, using a wildcard-only effectively allowing arbitrary URLS is possible misconfiguration that may be present in real-world instances. + +In such cases, unauthenticated and unprivileged attackers can perform the above described actions. + +### User with (only) App Administration Permissions + +A more likely scenario is an administrative user (e.g. a normal developer) having only permissions to manage applications. + +This relatively user could use the described attacks to perform a privilege escalation. + +### Workaround + +It is recommended to upgrade to the patched version of authentik. If not possible, ensure that OAuth2 providers do not use a wildcard (`*` or `.*`) value as allowed redirect URI setting. (This is _not_ exploitable if part of the redirect URI has a wildcard, for example `https://foo-.*\.bar\.com`) + +### For more information + +If you have any questions or comments about this advisory: + +- Email us at [security@goauthentik.io](mailto:security@goauthentik.io) diff --git a/website/sidebars.js b/website/sidebars.js index fe1b6725e..cce2be45f 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -407,6 +407,7 @@ const docsSidebar = { }, items: [ "security/policy", + "security/CVE-2024-21637", "security/CVE-2023-48228", "security/GHSA-rjvp-29xq-f62w", "security/CVE-2023-39522",