REDHAT-BUG-2478446: Medium severity redhat/krb5 vulnerability
AIONLYREPORT package: krb5-1.21.3-8.el100 ------ Summary: Unbounded Memory Leak in clnttcpcall on XID Mismatch (plus retry leak on AUTHREFRESH): a malicious RPC peer or on-path attacker can cause unbounded client-side memory growth and denial of service by sending accepted TCP RPC replies with mismatched transaction IDs and non-empty verifiers. Requirements to exploit: An application using the TCP RPC client path in krb5-1.21.3-8.el100 must issue a call through clnttcpcall, and the attacker must be able to act as the RPC server or inject syntactically valid reply records on the connection before a matching reply is processed. Component affected: krb5-1.21.3-8.el100, src/lib/rpc/clnttcp.c, clnttcpcall (with verifier allocation reached through xdropaqueauth() and xdrbytes()) Version affected: krb5-1.21.3-8.el100 when the TCP RPC client path in clnttcpcall is used 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 - A malicious RPC peer, or an attacker able to inject replies on the network path, can trigger the flaw remotely. AC:L - The attack requires only syntactically valid REPLY messages with a mismatched rmxid and a non-empty verifier. PR:N - No privileges on the client are required. UI:N - No additional user interaction is required once the vulnerable client performs the RPC call. S:U - The impact is confined to the client process using the affected library path. C:N - No confidentiality impact is established by the available evidence. I:N - No integrity impact is established by the available evidence. A:H - Each mismatched accepted reply can leak up to MAXAUTHBYTES (400) and the mismatch loop is unbounded for the duration of the call, allowing sustained memory growth and possible process termination. Impact: Moderate. Red Hat classifies remote denial-of-service issues as Important when they are easy and broadly exploitable, but this case is narrower: it affects a specific client-side RPC path, requires an attacker-controlled or intercepted peer, and the demonstrated consequence is denial of service of the consuming client process only. The available evidence does not establish confidentiality, integrity, or broader system compromise. Embargo: no Reason: This is an availability-only, client-side issue that requires a malicious RPC server or an on-path attacker while the affected TCP RPC client path is in use; the current evidence does not show broad compromise or wormable behavior. Acknowledgement: Aisle Research Vulnerability Details: In clnttcpcall, reply headers are decoded in a loop until replymsg.rmxid == xid. For each iteration, replymsg.acptedrply.arverf is reset to gssrpcnullauth before xdrreplymsg() decodes the reply. When a syntactically valid accepted reply carries a non-matching XID, the loop continues without freeing the verifier buffer that may have been allocated during decode. c while (TRUE) { replymsg.acptedrply.arverf = gssrpcnullauth; replymsg.acptedrply.arresults.where = NULL; replymsg.acptedrply.arresults.proc = xdrvoid; if (! xdrrecskiprecord(xdrs)) return (ct->cterror.restatus); / now decode and validate the response header / if (! xdrreplymsg(xdrs, &replymsg)) { / Free some stuff allocated by xdrreplymsg() to avoid leaks, since it may allocate memory from partially successful decodes. / enum xdrop op = xdrs->xop; xdrs->xop = XDRFREE; xdrreplymsg(xdrs, &replymsg); xdrs->xop = op; if (ct->cterror.restatus == RPCSUCCESS) continue; return (ct->cterror.restatus); } if (replymsg.rmxid == xid) break; }
The final verifier cleanup runs only after the loop exits, and the retry path can also bypass that cleanup: c else { / maybe our credentials need to be refreshed ... / if (refreshes-- && AUTHREFRESH(h->clauth, &replymsg)) goto callagain; } / free verifier ... / if ((replymsg.rmreply.rpstat == MSGACCEPTED) && (replymsg.acptedrply.arverf.oabase != NULL)) { xdrs->xop = XDRFREE; (void)xdropaqueauth(xdrs, &(replymsg.acptedrply.arverf)); } xdropaqueauth() decodes arverf through xdrbytes(), which allocates oabase on decode and releases it only under XDRFREE. On an XID mismatch, the next loop iteration overwrites arverf before that free occurs, so the previous pointer is lost. A second leak exists when AUTHREFRESH() succeeds and jumps to callagain before verifier cleanup. The retry-path leak is bounded by the refresh count and is secondary; the main issue is the unbounded mismatch loop. The available evidence supports availability impact only. Steps to reproduce: 1. Build with ASan, or run under Valgrind, and exercise any client path that uses clnttcpcall. 2. Connect the client to a controlled TCP RPC server, or position an on-path interceptor, that repeatedly sends syntactically valid REPLY records with rmdirection = REPLY, rpstat = MSGACCEPTED, arverf.oalength > 0 (up to MAXAUTHBYTES), and rmxid != client xid. 3. Keep sending mismatched replies while the client waits for the legitimate response. 4. Observe monotonic memory growth in the client process through RSS, ASan, or Valgrind. 5. Optionally, return replies that trigger an auth error followed by a successful AUTHREFRESH() to reproduce the retry-path leak. Mitigation: No complete runtime mitigation is established in the package. Exposure can be reduced by limiting this TCP RPC client path to trusted servers and protected networks, and by using conservative RPC timeouts so a waiting call cannot be held open indefinitely. These measures reduce exposure but do not remove the underlying leak. Proposed Fix: Free the verifier for non-matching accepted replies before the next decode, and free it before retrying callagain on successful AUTHREFRESH(). diff diff --git a/src/lib/rpc/clnttcp.c b/src/lib/rpc/clnttcp.c — a/src/lib/rpc/clnttcp.c +++ b/src/lib/rpc/clnttcp.c @@ -320,6 +320,15 @@ clnttcpcall(CLIENT h, rpcproct proc, xdrproct xdrargs, void argsptr, if (replymsg.rmxid == xid) break; + / Free verifier from non-matching replies before next decode. / + if ((replymsg.rmreply.rpstat == MSGACCEPTED) && + (replymsg.acptedrply.arverf.oabase != NULL)) { + enum xdrop op = xdrs->xop; + xdrs->xop = XDRFREE; + (void)xdropaqueauth(xdrs, &(replymsg.acptedrply.arverf)); + xdrs->xop = op; + } } @@ -340,8 +349,18 @@ clnttcpcall(CLIENT h, rpcproct proc, xdrproct xdrargs, void argsptr, else { / maybe our credentials need to be refreshed ... / if (refreshes- && AUTHREFRESH(h->clauth, &replymsg)) + if (refreshes-- && AUTHREFRESH(h->clauth, &replymsg)) { + / Free verifier before retrying callagain. / + if ((replymsg.rmreply.rpstat == MSGACCEPTED) && + (replymsg.acptedrply.arverf.oabase != NULL)) { + enum xdrop op = xdrs->xop; + xdrs->xop = XDRFREE; + (void)xdropaqueauth(xdrs, + &(replymsg.acptedrply.arverf)); + xdrs->xop = op; + } goto callagain; + } } ------ This report was generated using AI technology. Always review AI-generated content prior to use
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
Limit use of the TCP RPC client path to trusted RPC servers and protected networks, and configure conservative RPC timeouts so a waiting call cannot be held open indefinitely.
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
Exposure requires krb5-1.21.3-8.el10_0 to be used by an application that makes TCP RPC client calls through clnttcp_call. The affected code is src/lib/rpc/clnt_tcp.c.
What access does an attacker need to trigger the denial of service?
The attacker must either act as the RPC server or be able to inject syntactically valid TCP RPC reply records on the connection before the legitimate matching reply is processed. The malicious replies need accepted status, mismatched transaction IDs, and non-empty verifiers.
How can I assess whether a system is affected?
Confirm whether the installed package is krb5-1.21.3-8.el10_0 and whether relevant applications use the TCP RPC client path that reaches clnttcp_call. The report does not identify a released fixed package version.
Is a vendor package fix available?
No released package fix has been established in the provided information. A proposed patch is referenced, but the fixed version is unknown.