This is three small cracks in different walls, not one front door kicked in
Tenable plugin 187201 rolls up three different OpenSSH issues fixed in 9.6 and labels every pre-9.6 build as vulnerable. The bundle is: CVE-2023-48795 (*Terrapin*), a man-in-the-middle downgrade of early SSH transport integrity; CVE-2023-51384, an ssh-agent destination-constraint bug that only matters when adding PKCS#11-hosted keys and a token returns multiple keys; and CVE-2023-51385, a client-side command injection edge case when ssh(1) expands attacker-controlled %h / %u tokens inside ProxyCommand, LocalCommand, or Match exec. Upstream fixed all three in OpenSSH 9.6 released on 2023-12-18.
paragraph 2: The vendor's MEDIUM label is still a little generous for enterprise patch triage because the reachable attack paths are heavily constrained. The only remotely reachable issue against an SSH service is Terrapin, and OpenSSH's own release notes say its impact is *very limited* and, for OpenSSH itself, mainly strips a subset of keystroke-timing obfuscation. The more impactful bug in this bundle, CVE-2023-51385, is not a server-side port-22 smash at all; it is a client-side, user- or automation-driven chain that depends on risky ssh_config patterns and attacker-controlled host/user strings.
4 steps from start to impact.
Stage attacker-controlled SSH destination input
ssh(1), using shell metacharacters intended to survive into %h or %u expansion. There is no unauthenticated server-side bug here; the attacker is abusing a client workflow.- Victim uses
ssh(1)from OpenSSH before 9.6 - Attacker can supply or influence the hostname/username string
- A workflow exists that crosses a trust boundary, such as untrusted Git submodules
- This is client-side only; scanning port 22 on a server does not prove this path exists
- Many enterprises never use attacker-controlled host/user strings in SSH workflows
- The attack usually needs a developer, admin, or CI job to touch malicious content
Land inside a risky ssh_config command expansion
%h / %u value only becomes dangerous if local SSH configuration references it inside ProxyCommand, LocalCommand, or Match exec in a way the shell interprets. The upstream fix blocks most shell metacharacters on command-line supplied host/user names, but the original bug existed because some deployments pipe those tokens into shell commands. Weaponization here is straightforward shell injection, not a memory corruption exploit.- SSH config uses
ProxyCommand,LocalCommand, orMatch execwith expansion tokens - Quoting/sanitization is weak enough for shell metacharacters to matter
- A lot of OpenSSH client configs do not use these directives at all
- Even when used, correct quoting breaks the exploit
- EDR and shell telemetry often catch the resulting child process behavior
ssh_config. You need host-level config review.Execute commands as the invoking user
ssh. On a developer workstation or CI runner, that can be meaningful: source theft, credential access, or build pipeline tampering. It is still not a host-wide unauthenticated compromise; blast radius is bounded to the client context.- Victim actually launches the SSH operation
- Injected command reaches a shell
- Privilege level is only that of the invoking user
- Modern EDR should see suspicious child process creation from
sshorgit - Well-isolated CI runners and ephemeral build agents reduce persistence value
ssh spawning unexpected shells or utilities, and for git clone --recurse-submodules workflows followed by anomalous process trees.Alternate remote path: on-path Terrapin downgrade
SSH2_MSG_EXT_INFO. For OpenSSH, upstream says the most serious identified effect is disabling part of keystroke timing obfuscation, not breaking session secrecy or giving server RCE.- Attacker is on-path between client and server
- Negotiated cipher/MAC is in an affected mode
- Endpoints are OpenSSH before 9.6 or otherwise lack strict KEX protection
- Requires network position first, which implies another compromise or privileged access point
- Impact on OpenSSH itself is limited by upstream's own analysis
- No evidence here of a mature OpenSSH server takeover chain from Terrapin alone
The supporting signals.
| In-the-wild status | No CISA KEV listing was observed for CVE-2023-48795, CVE-2023-51384, or CVE-2023-51385 in the current KEV catalog page reviewed for this assessment. I also did not find an upstream OpenSSH statement claiming active exploitation of these three flaws against OpenSSH. |
|---|---|
| PoC / tooling availability | Public tooling exists for Terrapin: the researchers published Terrapin-Artifacts and Terrapin-Scanner. That is real research-grade tradecraft, but it is not the same thing as a one-shot unauthenticated OpenSSH server exploit. |
| EPSS | Public EPSS mirrors indicate the bundle is uneven: CVE-2023-51385 is the highest-risk item of the three, with OpenCVE surfacing an EPSS around 0.17234; the other two appear materially lower. I could not independently pull the live FIRST API value in this environment, so treat this as a directional signal, not a forensic-grade number. |
| KEV status and dates | Not KEV-listed in the CISA catalog page reviewed during this assessment. No federal due date applies from KEV because the CVEs are not present there. |
| Vendor baseline | Tenable plugin 187201 is currently MEDIUM and its changelog shows it settled on CVSS 6.5 using CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N, i.e. the command-injection CVE drives the roll-up more than Terrapin or the ssh-agent bug. |
| Affected versions | Upstream affected range is OpenSSH before 9.6. Practical scope is narrower per flaw: CVE-2023-48795 needs an on-path attacker and affected cipher/MAC negotiation; CVE-2023-51384 only applies to destination-constrained PKCS#11 keys where a token returns multiple keys; CVE-2023-51385 only applies to client-side command expansion scenarios using %h / %u in shell-sensitive directives. |
| Fixed versions / backports | Upstream fix is 9.6. Distro backports matter: Ubuntu shows Jammy 22.04 fixed at 1:8.9p1-3ubuntu0.5 for Terrapin and 1:8.9p1-3ubuntu0.6 for CVE-2023-51385, while Mantic 23.10 is fixed at 1:9.3p1-1ubuntu3.1 / 1:9.3p1-1ubuntu3.2. A host can therefore be patched while still reporting an upstream version lower than 9.6. |
| Exposure / scan data | The USENIX Terrapin paper found 71.6% of internet SSH servers supported an affected encryption mode and 63.2% even preferred one. That sounds scary, but it measures cipher support, not a turnkey OpenSSH exploit path; the attacker still needs MITM position and the OpenSSH impact remains limited. |
| Disclosure date | OpenSSH 9.6 shipped on 2023-12-18, and NVD lists all three CVEs as published on 2023-12-18. |
| Reporting researchers / upstream posture | Terrapin was disclosed by Fabian Bäumer, Marcus Brinkmann, and Jörg Schwenk. Upstream OpenSSH explicitly says the Terrapin impact on OpenSSH is 'very limited' and that the most serious identified effect is stripping part of keystroke timing obfuscation. |
noisgate verdict.
The decisive factor is attack-position friction: the only remotely reachable issue against an SSH service requires a man-in-the-middle foothold, and the more practically damaging bug is client-side and config-dependent. This bundle is common on scanners because OpenSSH is everywhere, but its real exploit population is far smaller than the raw package version count suggests.
Why this verdict
- Baseline starts at MEDIUM 6.5 because Tenable keyed the bundle off CVE-2023-51385's network-looking vector, but that baseline overstates what a port-22 finding means in practice.
- Downward adjustment: worst-impact bug is client-side. CVE-2023-51385 needs the victim to run
ssh(1)with attacker-controlled host/user data and a riskyssh_configpattern using%h/%uinsideProxyCommand,LocalCommand, orMatch exec. That excludes the majority of plain SSH server deployments. - Downward adjustment: remotely reachable path is MITM-only. CVE-2023-48795 is not Internet-to-daemon RCE; it requires on-path position, which usually implies the attacker already owns a network choke point, local segment, proxy, VPN edge, or other upstream foothold.
- Downward adjustment: Terrapin's OpenSSH blast radius is small. OpenSSH upstream states the most serious identified impact is disabling a subset of keystroke timing obfuscation and says there is no other discernable impact to session secrecy or session integrity.
- Downward adjustment: CVE-2023-51384 is niche by design. It requires
ssh-agent, PKCS#11-hosted keys, destination constraints, and multiple keys returned by one token. That is a narrow admin or high-assurance workstation corner case, not a fleet-wide server emergency. - Downward adjustment: scanner population is inflated by backports. Enterprise Linux distros patch these flaws in older package builds, so remote version checks can turn patched hosts into patch-chase noise.
Why not higher?
There is no evidence here of an unauthenticated OpenSSH server RCE, auth bypass, or mass-exploited wormable path. The server-side issue needs MITM position, and the client-side issue needs a chain of user workflow plus unsafe local config plus attacker-controlled destination strings.
Why not lower?
I am not dropping this to IGNORE because OpenSSH is ubiquitous and the client-side command injection bug can matter on developer workstations, admin jump boxes, and CI runners. Public Terrapin research tooling also means defenders should not dismiss the bundle entirely; it is just not urgent at enterprise scale.
What to do — in priority order.
- Audit risky SSH client directives — Review
ProxyCommand,LocalCommand, andMatch execusage in enterprisessh_configbaselines and automation images, especially where%hor%uare expanded into shell commands. For a LOW verdict there is no SLA (treat as backlog hygiene), but this is the highest-value compensating control because it collapses the practical CVE-2023-51385 path even before patching. - Prefer backport-aware validation — Do not mass-open tickets solely because a scanner saw
OpenSSH_8.xor9.3p1. Verify distro advisories and package changelogs first, because Ubuntu and other vendors backported fixes below 9.6. For a LOW verdict there is no SLA (treat as backlog hygiene); use this to cut false positives before scheduling work. - Constrain untrusted Git and CI inputs — On build agents and admin workstations, reduce workflows that recursively pull untrusted submodules or external SSH destinations without review. This directly reduces the attacker-controlled input required for CVE-2023-51385. For a LOW verdict there is no SLA (treat as backlog hygiene).
- Harden network trust boundaries — For Terrapin, the attacker must already be on path, so focus on VPN integrity, trusted bastions, NAC, and avoiding hostile intermediary networks for administrative SSH. This does not replace patching, but it attacks the key prerequisite. For a LOW verdict there is no SLA (treat as backlog hygiene).
- A generic WAF does not help; SSH is not traversing your HTTP inspection stack.
- Treating every pre-9.6 banner as vulnerable does not work because distro backports fix these CVEs in older package versions.
- Focusing only on server-side port 22 exposure misses the highest-practicality path in the bundle, which is the client-side command injection scenario.
Crowdsourced verification payload.
Run this on the target Linux host as a local check; no network access is required. Invoke it with bash check_openssh_187201.sh as root or an unprivileged user with read access to package metadata. It inspects the local OpenSSH version and, where possible, distro changelogs to distinguish upstream vulnerable from backport patched packages.
#!/usr/bin/env bash
# check_openssh_187201.sh
# Detect likely exposure to Tenable plugin 187201 (OpenSSH < 9.6 multiple vulnerabilities)
# Outputs exactly one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
cves='CVE-2023-48795|CVE-2023-51384|CVE-2023-51385'
have_cmd() { command -v "$1" >/dev/null 2>&1; }
extract_openssh_ver() {
local out ver
if have_cmd ssh; then
out=$(ssh -V 2>&1 || true)
ver=$(printf '%s' "$out" | sed -n 's/.*OpenSSH_\([0-9][0-9.]*p\{0,1\}[0-9]*\).*/\1/p' | head -n1)
if [ -n "$ver" ]; then
printf '%s\n' "$ver"
return 0
fi
fi
if have_cmd sshd; then
out=$(sshd -V 2>&1 || true)
ver=$(printf '%s' "$out" | sed -n 's/.*OpenSSH_\([0-9][0-9.]*p\{0,1\}[0-9]*\).*/\1/p' | head -n1)
if [ -n "$ver" ]; then
printf '%s\n' "$ver"
return 0
fi
fi
return 1
}
normalize_ver() {
# Converts 9.6p1 -> 9.6.1 for sort -V comparisons
printf '%s' "$1" | sed 's/p/./g'
}
upstream_patched() {
local found norm
found=$(extract_openssh_ver || true)
[ -z "$found" ] && return 1
norm=$(normalize_ver "$found")
if [ "$(printf '%s\n%s\n' "9.6" "$norm" | sort -V | tail -n1)" = "$norm" ]; then
return 0
fi
return 1
}
deb_backport_patched() {
local files f
files="/usr/share/doc/openssh-client/changelog.Debian.gz /usr/share/doc/openssh-server/changelog.Debian.gz /usr/share/doc/openssh/changelog.Debian.gz"
for f in $files; do
if [ -r "$f" ] && zgrep -Eiq "$cves" "$f"; then
return 0
fi
done
return 1
}
rpm_backport_patched() {
local pkgs pkg
pkgs="openssh openssh-server openssh-clients"
if ! have_cmd rpm; then
return 1
fi
for pkg in $pkgs; do
if rpm -q "$pkg" >/dev/null 2>&1; then
if rpm -q --changelog "$pkg" 2>/dev/null | grep -Eiq "$cves"; then
return 0
fi
fi
done
return 1
}
# Decision tree
if upstream_patched; then
echo PATCHED
exit 0
fi
# Backported distro packages may still show an upstream version lower than 9.6.
if deb_backport_patched || rpm_backport_patched; then
echo PATCHED
exit 0
fi
# If we can see an upstream-style version < 9.6 and no package metadata suggests a backport,
# call it vulnerable for locally built / portable installs.
ver=$(extract_openssh_ver || true)
if [ -n "$ver" ]; then
if [ -d /etc/apt ] || have_cmd dpkg || have_cmd rpm; then
echo UNKNOWN
exit 2
else
echo VULNERABLE
exit 1
fi
fi
echo UNKNOWN
exit 2
If you remember one thing.
%h/%u command-expansion path. For a LOW verdict there is no noisgate mitigation SLA and no noisgate remediation SLA — treat this as backlog hygiene: fold it into your normal patch cycle, and prioritize only those workstations, jump hosts, or build runners that use risky SSH client directives or handle untrusted Git content.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.