Bug 2462351 (CVE-2026-55653) - CVE-2026-55653 openssh: Double free in Red Hat Enterprise Linux versions of OpenSSH DH-GEX client path during FIPS known-group validation leads to client-side denial of service
Summary: CVE-2026-55653 openssh: Double free in Red Hat Enterprise Linux versions of O...
Keywords:
Status: NEW
Alias: CVE-2026-55653
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-04-26 18:55 UTC by OSIDB Bzimport
Modified: 2026-06-22 23:20 UTC (History)
11 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-04-26 18:55:02 UTC
AI_ONLY_REPORT
package: openssh-9.9p1-22.el10_2
------
Summary: Double Free in DH-GEX Client during FIPS Mode Check: a malicious  
SSH server can trigger a double free in the DH-GEX client path during FIPS  
known-group validation, leading to client-side process termination in  
affected configurations.
Requirements to exploit: An affected `openssh-9.9p1-22.el10_2` client build  
with OpenSSL support must run in FIPS mode, negotiate  
`diffie-hellman-group-exchange-sha256`, and process attacker-controlled  
DH-GEX group parameters; the clearest demonstrated second-free path is a  
non-fatal client flow such as `ssh-keyscan`.
Component affected: `openssh-9.9p1-22.el10_2`: DH-GEX client handling in  
`kexgexc.c` (`input_kex_dh_gex_group()`), with later teardown in `kex.c`  
(`kex_free()`).
Version affected: `openssh-9.9p1-22.el10_2` when built with OpenSSL support  
and used in FIPS mode with `diffie-hellman-group-exchange-sha256` negotiated
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:R/S:U/C:N/I:N/A:H - 5.9 (MEDIUM)
AV:N - The triggering input is delivered by a remote SSH server during  
key exchange.
AC:L - In an affected configuration, the attacker only needs to return a  
size-valid DH group that fails the FIPS known-group check.
PR:N - No authentication or prior access to the client is required.
UI:R - A user or automation must initiate the SSH connection or scan to  
the attacker-controlled server.
S:U - The impact is confined to the vulnerable client process.
C:N - No confidentiality impact is established by the available evidence.
I:N - No integrity impact is established by the available evidence.
A:H - The demonstrated outcome is a reachable double free that can abort  
or terminate the affected client process.
Impact: Moderate. This is a remote, availability-focused flaw, but the  
demonstrated double-free path depends on FIPS mode, DH-GEX negotiation, and  
a client flow that continues to teardown after the validation error.  
Because the available evidence supports process termination rather than  
broader compromise, and the common `ssh` client path often exits before the  
second free, this fits Red Hat's Moderate category rather than Important.
Embargo: no
Reason: The established impact is client-side denial of service in a  
constrained FIPS/DH-GEX path, with no demonstrated confidentiality or  
integrity loss and a straightforward local fix.
Acknowledgement: Aisle Research
Vulnerability Details: In `input_kex_dh_gex_group()`, the client parses  
server-supplied `p` and `g`, transfers them into `kex->dh` via  
`dh_new_group()`, and only then performs the FIPS known-group validation.  
If that validation fails, execution jumps to `out` before the local  
pointers are nulled. The local cleanup then frees BIGNUMs that are already  
owned by `kex->dh`, and later teardown can free the same objects again  
through `DH_free(kex->dh)`.
```c
if ((kex->dh = dh_new_group(g, p)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
p = g = NULL; /* belong to kex->dh now */
...
out:
BN_clear_free(p);
BN_clear_free(g);
return r;
```
The ownership transfer happens in `dh_new_group()` through `DH_set0_pqg()`:
```c
if ((dh = DH_new()) == NULL)
return NULL;
if (!DH_set0_pqg(dh, modulus, NULL, gen)) {
DH_free(dh);
return NULL;
}
return dh;
```
The practical reachability is nuanced. In the normal `ssh` client flow,  
fatal dispatch commonly exits immediately before later teardown, which  
reduces impact there. In contrast, the `ssh-keyscan` client flow uses  
non-fatal dispatch and later closes the SSH state, reaching `kex_free()`  
and a second `DH_free(kex->dh)`. Based on the available evidence, this  
supports a real double free with demonstrated availability impact, but not  
a demonstrated confidentiality or integrity impact.
Steps to reproduce:
1. Use an affected `openssh-9.9p1-22.el10_2` build with OpenSSL support and  
run it in FIPS mode.
2. Exercise a non-fatal DH-GEX client path, such as the `ssh-keyscan` flow  
present in this source tree.
3. Ensure `diffie-hellman-group-exchange-sha256` is negotiated with an  
attacker-controlled SSH server.
4. Have the server return `(p, g)` values that pass the size check in  
`input_kex_dh_gex_group()` but fail `dh_is_known_group()`.
5. Observe the first free at `BN_clear_free(p)` / `BN_clear_free(g)` on the  
`goto out` path, followed by a second free during later teardown when  
`ssh_packet_close()` reaches `kex_free()` and calls `DH_free(kex->dh)`.
Mitigation: Until a fix is shipped, avoid negotiating  
`diffie-hellman-group-exchange-sha256` in affected FIPS deployments and  
avoid using the affected non-fatal client flow against untrusted hosts  
while FIPS mode is enabled.
Proposed Fix: Move the pointer nulling immediately after successful  
`dh_new_group()` so all later error paths treat ownership correctly.
```diff
diff --git a/kexgexc.c b/kexgexc.c
@@ -115,12 +115,12 @@ input_kex_dh_gex_group(int type, u_int32_t seq,  
struct ssh *ssh)
if ((kex->dh = dh_new_group(g, p)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
+    p = g = NULL; /* belong to kex->dh now */
if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
   p = g = NULL; /* belong to kex->dh now */
```


------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.