The GSS-RPC transport layer in MIT Kerberos 5 (aka krb5) 1.4 and later does not release the previous authentication context when a client switches from an RPCSEC_GSS or AUTH_GSSAPI flavor to a non-GSS flavor on the same TCP connection. This allows remote attackers to cause a denial of service (memory exhaustion in kadmind) by repeatedly establishing and abandoning GSS authentication contexts.
AI_ONLY_REPORT
package: krb5-1.21.3-8.el10_0
------
Summary: RPCSEC_GSS Auth-Flavor Switching Causes Unbounded Per-Connection
Memory Leak (Unauthenticated DoS): switching a persistent TCP connection
from `RPCSEC_GSS` to `AUTH_NONE`, `AUTH_UNIX`, or `AUTH_SHORT` can orphan
heap-backed auth state and let an unauthenticated remote client exhaust
server memory.
Requirements to exploit: The attacker must be able to reach a service built
from `krb5-1.21.3-8.el10_0` that uses the `src/lib/rpc` GSS-RPC server path
over a long-lived TCP connection with `RPCSEC_GSS` enabled. No prior
authentication or user interaction is required.
Component affected: `krb5-1.21.3-8.el10_0` GSS-RPC server authentication
lifecycle in `src/lib/rpc`, notably `svc_do_xprt()` in `svc.c`,
`gssrpc_authenticate()` in `svc_auth.c`, `gssrpc_svcauth_gss()` in
`svc_auth_gss.c`, and the non-GSS handlers in `svc_auth_none.c` and
`svc_auth_unix.c`.
Version affected: `krb5-1.21.3-8.el10_0` (reachable when a service from
this SRPM exposes the GSS-RPC server path over persistent TCP with
`RPCSEC_GSS` enabled)
Patch available: no released package fix established; proposed patch
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 (HIGH)
AV:N - The attack is performed by sending RPC traffic over the network
to an exposed service.
AC:L - Once the affected TCP GSS-RPC path is reachable, alternating auth
flavors on one connection is straightforward and repeatable.
PR:N - The leak can be triggered before successful authentication is
established.
UI:N - No user interaction is required.
S:U - The impact is limited to the vulnerable service's own security
scope.
C:N - No confidentiality impact is demonstrated.
I:N - No integrity impact is demonstrated.
A:H - Repetition can drive unbounded memory growth until the service
becomes unavailable or is terminated.
Impact: Important. The demonstrated effect is an unauthenticated remote
denial of service through memory exhaustion on a network-reachable service,
which aligns with Red Hat's Important rating for remote DoS. It is not
Critical because no system compromise or confidentiality/integrity impact
is shown, and reachability depends on a deployment exposing the affected
`RPCSEC_GSS` TCP path.
Embargo: no
Reason: This is an availability-only issue with configuration-dependent
reachability, and administrators can reduce exposure by restricting access
to the affected service. The available evidence does not show code
execution or silent data compromise that would strongly justify delayed
public disclosure.
Acknowledgement: Aisle Research
Vulnerability Details: The issue is a lifecycle mismatch for
`xprt->xp_auth`. `gssrpc__svcauth_gss()` allocates heap-backed
`SVCAUTH`/GSS private state and stores it on the transport. `svc_do_xprt()`
intentionally preserves `RPCSEC_GSS` auth handles across requests, but
later non-GSS authenticators overwrite the same pointer with the static
`&svc_auth_none` handle without first calling `SVCAUTH_DESTROY()`. After
the overwrite, the original heap object is no longer reachable and leaks
until process exit.
In `src/lib/rpc/svc_auth_gss.c`, `RPCSEC_GSS` authentication attaches
per-connection auth state to the transport:
```c
if (rqst->rq_xprt->xp_auth == NULL ||
rqst->rq_xprt->xp_auth == &svc_auth_none) {
...
auth->svc_ah_ops = &svc_auth_gss_ops;
SVCAUTH_PRIVATE(auth) = gd;
rqst->rq_xprt->xp_auth = auth;
}
```
In `src/lib/rpc/svc.c`, non-GSS auth handles are nulled at request
teardown, while GSS handles are intentionally retained:
```c
} else if ((xprt->xp_auth != NULL) &&
(xprt->xp_auth->svc_ah_ops != &svc_auth_gss_ops)) {
xprt->xp_auth = NULL;
}
```
In `src/lib/rpc/svc_auth_none.c`, and likewise in `gssrpc__svcauth_unix()`
and `gssrpc__svcauth_short()`, a later non-GSS request overwrites the
transport pointer:
```c
rqst->rq_xprt->xp_auth = &svc_auth_none;
```
An unauthenticated client can therefore keep one TCP connection open, send
an `RPCSEC_GSS` `INIT` or `CONTINUE_INIT` request to allocate `xp_auth`,
then switch to `AUTH_NONE`, `AUTH_UNIX`, or `AUTH_SHORT` on the same
connection to orphan that state. Repeating the sequence causes monotonic
heap/RSS growth bounded only by available memory. The available evidence
supports availability impact only.
Steps to reproduce:
1. Run a service built from `krb5-1.21.3-8.el10_0` that uses the
`src/lib/rpc` server stack over TCP with `RPCSEC_GSS` enabled.
2. Keep a single TCP connection open to the service.
3. Send one `RPCSEC_GSS` request on that connection, such as `INIT` or
`CONTINUE_INIT`, so `gssrpc__svcauth_gss()` allocates `xp_auth`.
4. On the same connection, send a request using `AUTH_NONE`, `AUTH_UNIX`,
or `AUTH_SHORT` so `xp_auth` is overwritten.
5. Repeat steps 3 and 4 in a loop.
6. Observe monotonic memory growth in the server process; repeated
switching can eventually exhaust memory and make the service unavailable.
Mitigation: Restrict network access to affected GSS-RPC services to trusted
clients until a fix is available. Deployments that do not expose the
vulnerable TCP GSS-RPC path or do not enable `RPCSEC_GSS` are not reachable
through this issue. If memory growth is observed, restart the affected
service to reclaim leaked memory.
Proposed Fix: Centralize cleanup in `gssrpc__authenticate()` before
dispatching to non-`RPCSEC_GSS` authenticators so auth-flavor switching
cannot orphan the previous heap allocation.
```diff
diff --git a/src/lib/rpc/svc_auth.c b/src/lib/rpc/svc_auth.c
— a/src/lib/rpc/svc_auth.c
+++ b/src/lib/rpc/svc_auth.c
@@ -38,6 +38,7 @@
*/
#include <gssrpc/rpc.h>
+extern struct svc_auth_ops svc_auth_gss_ops;
/*
Server side authenticators are called from authenticate by
@@ -92,6 +93,14 @@ gssrpc__authenticate(
rqst->rq_xprt->xp_verf.oa_length = 0;
cred_flavor = rqst->rq_cred.oa_flavor;
*no_dispatch = FALSE;
+
+ /* Drop stale RPCSEC_GSS auth state if client switches flavor. */
+ if (rqst->rq_xprt->xp_auth != NULL &&
+ rqst->rq_xprt->xp_auth->svc_ah_ops == &svc_auth_gss_ops &&
+ cred_flavor != RPCSEC_GSS) {
+ SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth);
+ rqst->rq_xprt->xp_auth = NULL;
+ }
+
for (i = 0; i < svcauthnum; i++) {
if (cred_flavor == svcauthsw[i].flavor &&
svcauthsw[i].authenticator != NULL) {
```
------
This report was generated using AI technology. Always review AI-generated
content prior to use
AI_ONLY_REPORT package: krb5-1.21.3-8.el10_0 ------ Summary: RPCSEC_GSS Auth-Flavor Switching Causes Unbounded Per-Connection Memory Leak (Unauthenticated DoS): switching a persistent TCP connection from `RPCSEC_GSS` to `AUTH_NONE`, `AUTH_UNIX`, or `AUTH_SHORT` can orphan heap-backed auth state and let an unauthenticated remote client exhaust server memory. Requirements to exploit: The attacker must be able to reach a service built from `krb5-1.21.3-8.el10_0` that uses the `src/lib/rpc` GSS-RPC server path over a long-lived TCP connection with `RPCSEC_GSS` enabled. No prior authentication or user interaction is required. Component affected: `krb5-1.21.3-8.el10_0` GSS-RPC server authentication lifecycle in `src/lib/rpc`, notably `svc_do_xprt()` in `svc.c`, `gssrpc_authenticate()` in `svc_auth.c`, `gssrpc_svcauth_gss()` in `svc_auth_gss.c`, and the non-GSS handlers in `svc_auth_none.c` and `svc_auth_unix.c`. Version affected: `krb5-1.21.3-8.el10_0` (reachable when a service from this SRPM exposes the GSS-RPC server path over persistent TCP with `RPCSEC_GSS` enabled) Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 (HIGH) AV:N - The attack is performed by sending RPC traffic over the network to an exposed service. AC:L - Once the affected TCP GSS-RPC path is reachable, alternating auth flavors on one connection is straightforward and repeatable. PR:N - The leak can be triggered before successful authentication is established. UI:N - No user interaction is required. S:U - The impact is limited to the vulnerable service's own security scope. C:N - No confidentiality impact is demonstrated. I:N - No integrity impact is demonstrated. A:H - Repetition can drive unbounded memory growth until the service becomes unavailable or is terminated. Impact: Important. The demonstrated effect is an unauthenticated remote denial of service through memory exhaustion on a network-reachable service, which aligns with Red Hat's Important rating for remote DoS. It is not Critical because no system compromise or confidentiality/integrity impact is shown, and reachability depends on a deployment exposing the affected `RPCSEC_GSS` TCP path. Embargo: no Reason: This is an availability-only issue with configuration-dependent reachability, and administrators can reduce exposure by restricting access to the affected service. The available evidence does not show code execution or silent data compromise that would strongly justify delayed public disclosure. Acknowledgement: Aisle Research Vulnerability Details: The issue is a lifecycle mismatch for `xprt->xp_auth`. `gssrpc__svcauth_gss()` allocates heap-backed `SVCAUTH`/GSS private state and stores it on the transport. `svc_do_xprt()` intentionally preserves `RPCSEC_GSS` auth handles across requests, but later non-GSS authenticators overwrite the same pointer with the static `&svc_auth_none` handle without first calling `SVCAUTH_DESTROY()`. After the overwrite, the original heap object is no longer reachable and leaks until process exit. In `src/lib/rpc/svc_auth_gss.c`, `RPCSEC_GSS` authentication attaches per-connection auth state to the transport: ```c if (rqst->rq_xprt->xp_auth == NULL || rqst->rq_xprt->xp_auth == &svc_auth_none) { ... auth->svc_ah_ops = &svc_auth_gss_ops; SVCAUTH_PRIVATE(auth) = gd; rqst->rq_xprt->xp_auth = auth; } ``` In `src/lib/rpc/svc.c`, non-GSS auth handles are nulled at request teardown, while GSS handles are intentionally retained: ```c } else if ((xprt->xp_auth != NULL) && (xprt->xp_auth->svc_ah_ops != &svc_auth_gss_ops)) { xprt->xp_auth = NULL; } ``` In `src/lib/rpc/svc_auth_none.c`, and likewise in `gssrpc__svcauth_unix()` and `gssrpc__svcauth_short()`, a later non-GSS request overwrites the transport pointer: ```c rqst->rq_xprt->xp_auth = &svc_auth_none; ``` An unauthenticated client can therefore keep one TCP connection open, send an `RPCSEC_GSS` `INIT` or `CONTINUE_INIT` request to allocate `xp_auth`, then switch to `AUTH_NONE`, `AUTH_UNIX`, or `AUTH_SHORT` on the same connection to orphan that state. Repeating the sequence causes monotonic heap/RSS growth bounded only by available memory. The available evidence supports availability impact only. Steps to reproduce: 1. Run a service built from `krb5-1.21.3-8.el10_0` that uses the `src/lib/rpc` server stack over TCP with `RPCSEC_GSS` enabled. 2. Keep a single TCP connection open to the service. 3. Send one `RPCSEC_GSS` request on that connection, such as `INIT` or `CONTINUE_INIT`, so `gssrpc__svcauth_gss()` allocates `xp_auth`. 4. On the same connection, send a request using `AUTH_NONE`, `AUTH_UNIX`, or `AUTH_SHORT` so `xp_auth` is overwritten. 5. Repeat steps 3 and 4 in a loop. 6. Observe monotonic memory growth in the server process; repeated switching can eventually exhaust memory and make the service unavailable. Mitigation: Restrict network access to affected GSS-RPC services to trusted clients until a fix is available. Deployments that do not expose the vulnerable TCP GSS-RPC path or do not enable `RPCSEC_GSS` are not reachable through this issue. If memory growth is observed, restart the affected service to reclaim leaked memory. Proposed Fix: Centralize cleanup in `gssrpc__authenticate()` before dispatching to non-`RPCSEC_GSS` authenticators so auth-flavor switching cannot orphan the previous heap allocation. ```diff diff --git a/src/lib/rpc/svc_auth.c b/src/lib/rpc/svc_auth.c — a/src/lib/rpc/svc_auth.c +++ b/src/lib/rpc/svc_auth.c @@ -38,6 +38,7 @@ */ #include <gssrpc/rpc.h> +extern struct svc_auth_ops svc_auth_gss_ops; /* Server side authenticators are called from authenticate by @@ -92,6 +93,14 @@ gssrpc__authenticate( rqst->rq_xprt->xp_verf.oa_length = 0; cred_flavor = rqst->rq_cred.oa_flavor; *no_dispatch = FALSE; + + /* Drop stale RPCSEC_GSS auth state if client switches flavor. */ + if (rqst->rq_xprt->xp_auth != NULL && + rqst->rq_xprt->xp_auth->svc_ah_ops == &svc_auth_gss_ops && + cred_flavor != RPCSEC_GSS) { + SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth); + rqst->rq_xprt->xp_auth = NULL; + } + for (i = 0; i < svcauthnum; i++) { if (cred_flavor == svcauthsw[i].flavor && svcauthsw[i].authenticator != NULL) { ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use