Skip to content

Commit 359b343

Browse files
security: fix CVE-2024-42490 (cherry-pick #11022) (#11025)
security: fix CVE-2024-42490 (#11022) CVE-2024-42490 Signed-off-by: Jens Langhammer <[email protected]> Co-authored-by: Jens L. <[email protected]>
1 parent b727656 commit 359b343

File tree

7 files changed

+101
-5
lines changed

7 files changed

+101
-5
lines changed

authentik/core/api/used_by.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from rest_framework.response import Response
1515

1616
from authentik.core.api.utils import PassiveSerializer
17+
from authentik.rbac.filters import ObjectFilter
1718

1819

1920
class DeleteAction(Enum):
@@ -53,7 +54,7 @@ class UsedByMixin:
5354
@extend_schema(
5455
responses={200: UsedBySerializer(many=True)},
5556
)
56-
@action(detail=True, pagination_class=None, filter_backends=[])
57+
@action(detail=True, pagination_class=None, filter_backends=[ObjectFilter])
5758
def used_by(self, request: Request, *args, **kwargs) -> Response:
5859
"""Get a list of all objects that use this object"""
5960
model: Model = self.get_object()

authentik/crypto/api.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from authentik.crypto.models import CertificateKeyPair
3636
from authentik.events.models import Event, EventAction
3737
from authentik.rbac.decorators import permission_required
38+
from authentik.rbac.filters import ObjectFilter
3839

3940
LOGGER = get_logger()
4041

@@ -265,7 +266,7 @@ def generate(self, request: Request) -> Response:
265266
],
266267
responses={200: CertificateDataSerializer(many=False)},
267268
)
268-
@action(detail=True, pagination_class=None, filter_backends=[])
269+
@action(detail=True, pagination_class=None, filter_backends=[ObjectFilter])
269270
def view_certificate(self, request: Request, pk: str) -> Response:
270271
"""Return certificate-key pairs certificate and log access"""
271272
certificate: CertificateKeyPair = self.get_object()
@@ -295,7 +296,7 @@ def view_certificate(self, request: Request, pk: str) -> Response:
295296
],
296297
responses={200: CertificateDataSerializer(many=False)},
297298
)
298-
@action(detail=True, pagination_class=None, filter_backends=[])
299+
@action(detail=True, pagination_class=None, filter_backends=[ObjectFilter])
299300
def view_private_key(self, request: Request, pk: str) -> Response:
300301
"""Return certificate-key pairs private key and log access"""
301302
certificate: CertificateKeyPair = self.get_object()

authentik/crypto/tests.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,46 @@ def test_private_key_download(self):
214214
self.assertEqual(200, response.status_code)
215215
self.assertIn("Content-Disposition", response)
216216

217+
def test_certificate_download_denied(self):
218+
"""Test certificate export (download)"""
219+
self.client.logout()
220+
keypair = create_test_cert()
221+
response = self.client.get(
222+
reverse(
223+
"authentik_api:certificatekeypair-view-certificate",
224+
kwargs={"pk": keypair.pk},
225+
)
226+
)
227+
self.assertEqual(403, response.status_code)
228+
response = self.client.get(
229+
reverse(
230+
"authentik_api:certificatekeypair-view-certificate",
231+
kwargs={"pk": keypair.pk},
232+
),
233+
data={"download": True},
234+
)
235+
self.assertEqual(403, response.status_code)
236+
237+
def test_private_key_download_denied(self):
238+
"""Test private_key export (download)"""
239+
self.client.logout()
240+
keypair = create_test_cert()
241+
response = self.client.get(
242+
reverse(
243+
"authentik_api:certificatekeypair-view-private-key",
244+
kwargs={"pk": keypair.pk},
245+
)
246+
)
247+
self.assertEqual(403, response.status_code)
248+
response = self.client.get(
249+
reverse(
250+
"authentik_api:certificatekeypair-view-private-key",
251+
kwargs={"pk": keypair.pk},
252+
),
253+
data={"download": True},
254+
)
255+
self.assertEqual(403, response.status_code)
256+
217257
def test_used_by(self):
218258
"""Test used_by endpoint"""
219259
self.client.force_login(create_test_admin_user())
@@ -246,6 +286,26 @@ def test_used_by(self):
246286
],
247287
)
248288

289+
def test_used_by_denied(self):
290+
"""Test used_by endpoint"""
291+
self.client.logout()
292+
keypair = create_test_cert()
293+
OAuth2Provider.objects.create(
294+
name=generate_id(),
295+
client_id="test",
296+
client_secret=generate_key(),
297+
authorization_flow=create_test_flow(),
298+
redirect_uris="http://localhost",
299+
signing_key=keypair,
300+
)
301+
response = self.client.get(
302+
reverse(
303+
"authentik_api:certificatekeypair-used-by",
304+
kwargs={"pk": keypair.pk},
305+
)
306+
)
307+
self.assertEqual(403, response.status_code)
308+
249309
def test_discovery(self):
250310
"""Test certificate discovery"""
251311
name = generate_id()

authentik/flows/api/flows.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
)
3838
from authentik.lib.views import bad_request_message
3939
from authentik.rbac.decorators import permission_required
40+
from authentik.rbac.filters import ObjectFilter
4041

4142
LOGGER = get_logger()
4243

@@ -281,7 +282,7 @@ def set_background_url(self, request: Request, slug: str):
281282
400: OpenApiResponse(description="Flow not applicable"),
282283
},
283284
)
284-
@action(detail=True, pagination_class=None, filter_backends=[])
285+
@action(detail=True, pagination_class=None, filter_backends=[ObjectFilter])
285286
def execute(self, request: Request, slug: str):
286287
"""Execute flow for current user"""
287288
# Because we pre-plan the flow here, and not in the planner, we need to manually clear

authentik/outposts/api/service_connections.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
KubernetesServiceConnection,
2727
OutpostServiceConnection,
2828
)
29+
from authentik.rbac.filters import ObjectFilter
2930

3031

3132
class ServiceConnectionSerializer(ModelSerializer, MetaNameSerializer):
@@ -75,7 +76,7 @@ class ServiceConnectionViewSet(
7576
filterset_fields = ["name"]
7677

7778
@extend_schema(responses={200: ServiceConnectionStateSerializer(many=False)})
78-
@action(detail=True, pagination_class=None, filter_backends=[])
79+
@action(detail=True, pagination_class=None, filter_backends=[ObjectFilter])
7980
def state(self, request: Request, pk: str) -> Response:
8081
"""Get the service connection's state"""
8182
connection = self.get_object()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# CVE-2024-42490
2+
3+
_Reported by [@m2a2](https://github.com/m2a2)_
4+
5+
## Improper Authorization for Token modification
6+
7+
### Summary
8+
9+
Several API endpoints can be accessed by users without correct authentication/authorization.
10+
11+
The main API endpoints affected by this:
12+
13+
- `/api/v3/crypto/certificatekeypairs/<uuid>/view_certificate/`
14+
- `/api/v3/crypto/certificatekeypairs/<uuid>/view_private_key/`
15+
- `/api/v3/.../used_by/`
16+
17+
Note that all of the affected API endpoints require the knowledge of the ID of an object, which especially for certificates is not accessible to an unprivileged user. Additionally the IDs for most objects are UUIDv4, meaning they are not easily guessable/enumerable.
18+
19+
### Patches
20+
21+
authentik 2024.4.4, 2024.6.4 and 2024.8.0 fix this issue.
22+
23+
### Workarounds
24+
25+
Access to the API endpoints can be blocked at a Reverse-proxy/Load balancer level to prevent this issue from being exploited.
26+
27+
### For more information
28+
29+
If you have any questions or comments about this advisory:
30+
31+
- Email us at [[email protected]](mailto:[email protected])

website/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ const docsSidebar = {
511511
items: [
512512
"security/security-hardening",
513513
"security/policy",
514+
"security/CVE-2024-42490",
514515
"security/CVE-2024-38371",
515516
"security/CVE-2024-37905",
516517
"security/CVE-2024-23647",

0 commit comments

Comments
 (0)