StreamSec Home  Forum Home 
 
Welcome, Guest.
Your IP: 216.73.217.167
2026-10-06 11:38:25 
 Announcements
 SECURITY ADVISORY - StreamSec Tools 4.1.1.349 to 4.1.4.360, patch P01 An explicitly pinned SSH host key does not hold.
Bottom
 
Total posts: 1
 Author SECURITY ADVISORY - StreamSec Tools 4.1.1.349 to 4.1.4.360, patch P01 An explicitly pinned SSH host key does not hold.
Henrick Wibell Hellström

2026-10-06 09:54:53
Registered user
AFFECTED RELEASES
StreamSec Tools 4.1.1.349 through 4.1.4.360. The vulnerability is in the
dotted StreamSec.SSH.* component stack - the units StreamSec.SSH.Client,
StreamSec.SSH.SocketClient, StreamSec.SSH.BaseComponent and
StreamSec.SSH.Options, behind TstSSHSocketClient, TstSSHClient and
TsnipClient. That stack entered the installed packages at 4.1.1.349 and
has shipped in every release since. The release after 4.1.4.360 carries
the fix; until it is published, patch P01
(StreamSec_Tools_4.1.4.360_P01_SshHostKeyPin.txt) carries the same fix as
a manual source edit.

THE TWO SSH BRANCHES, AND WHY THE RANGE STARTS AT 4.1.1.349
The library has carried two SSH component stacks with the same component
names. The dotted StreamSec.SSH.* stack above is the one that ships today.
It did not exist before 4.1.1.349: it entered the installed package in that
release and replaced, in the same release, the older st-prefixed stack -
stSSHClient, stSSHSocketClient, stSSHBaseComponent, stSSHOptions - which was
the installed SSH stack up to and including 4.1.0.348 and has not been
installed since. Its source stayed in the distribution, uninstalled,
through 4.1.3.356, and was removed at 4.1.3.357; a program could still
compile against it in that window.

So a release before 4.1.1.349 is not unaffected because it "has no SSH
client" - it has the st client. It is outside this advisory because the st
branch is a different, narrower case:
  - it pins RSA and DSS host keys only, with no ECDSA or EdDSA pinning;
  - it registers no host-key verification entries of its own (the
    application wires them up), so the algorithm-family bypass that is the
    core of this vulnerability - an accept-any entry of an unpinned family
    defeating the pin - does not arise there by default.
The st branch does share one lesser defect: a key component assigned to
ServerRSAKey or ServerDSSKey before its key is loaded registers accept-any
entries, so a client that pins by that route accepts any RSA (or DSS) key.
Whether the st stack in a still-supported release of 4.1.0.348 or earlier
warrants its own advisory is assessed separately; this patch does not
change the st units, as the library leaves its superseded units unchanged.
If you build against the st SSH units, say so when you report, with your
release (SECURITY.txt, section 2).

THE VULNERABILITY
A client pins a server's host key by assigning a key component to
ServerRSAKey, ServerDSSKey, ServerECDSAKey or ServerEdDSAKey. On the
affected releases the pin does not hold:

- The pin covered only its own algorithm family. The client also offers
  the other standard host-key algorithms with accept-any entries, and the
  SERVER chooses the algorithm. A machine-in-the-middle that presents a
  key of any other algorithm - its own key - is accepted without
  comparison against anything.
- A pin that yielded no key accepted any key of its algorithm, silently:
  a component assigned before its key was loaded, an identifier that found
  nothing, an ECDSA public key (which registered nothing at all), or a
  TstSSHPublicKeyList assigned to ServerECDSAKey or ServerEdDSAKey.
- A separate defect compounds the last case: a TstSSHPublicKeyList backed
  by a file (PublicKeyFileName) loaded no keys at all on these releases,
  so pins kept in a file silently became accept-any.
- On a server, a host key that was un-assigned (the property set to nil)
  went on being offered and signing until another key was assigned.

A client that pins nothing accepts the first host key a server presents.
That is the documented out-of-the-box behaviour and is not part of this
advisory; the vulnerability is that an explicit pin did not hold.

IMPACT
An attacker who can place themselves between a pinning client and its
server - on the network path, or at a spoofed address - can present their
own host key and complete the handshake as "the server". Everything the
client then sends, including a password login, goes to the attacker, and
everything it receives comes from them. The pin, which exists to prevent
exactly this, does not prevent it.

SEVERITY
High.
  CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
The attack is over the network (AV:N) and needs an active
machine-in-the-middle position, a condition of the target environment
(AT:P), with no privileges and no user interaction; it yields full
confidentiality and integrity of the SSH session (VC:H/VI:H). Subsequent
impact on systems reached THROUGH the session is left to environmental
scoring and is not counted in this base vector. The decimal score is the
one the official FIRST.org CVSS v4.0 calculator returns for this vector;
read it there at publication rather than computing it by hand, as the v4.0
score is a table lookup, not a formula.

WHAT TO DO
Do ONE of the following.

1. Upgrade to the first release after 4.1.4.360 when it is published, and
   rebuild your application.

2. Apply patch P01 to your release's source and rebuild the packages and
   your application. The patch file states the nine edits; every replaced
   routine is byte-identical across all twelve affected releases.

3. Use the work-around below. AN APPLICATION THAT APPLIES THE WORK-AROUND
   IN FULL, AND WHOSE PINS ARE RSA, DSS OR ED25519 KEYS, IS PROTECTED
   WITHOUT THE PATCH: it does not need to apply P01 or to rebuild against
   patched sources. Pinning an ECDSA or Ed448 public key cannot be made to
   hold by the work-around (those pins register nothing on the affected
   releases) - pin an RSA or Ed25519 key of the same server instead, or
   apply the patch.

THE WORK-AROUND
In the application, when setting up the client (TstSSHSocketClient,
TstSSHClient, or TsnipClient.SSHClient):

a. Load the key component BEFORE assigning it to the ServerXxxKey
   property, and assign the property again whenever the key is loaded or
   changed afterwards. After assigning, read the property back and treat
   nil as a failed pin.

b. After every pin is assigned, restrict the offered algorithms to the
   pinned ones by setting ServerKeyOptions.SelectedOptionNames to exactly
   the pinned algorithm names, and nothing else:
       RSA pin:      rsa-sha2-256, rsa-sha2-512, ssh-rsa
       Ed25519 pin:  ssh-ed25519
       DSS pin:      ssh-dss
   The server then cannot steer the handshake onto an unpinned algorithm,
   because none is offered; and a pinned entry compares fail-closed.

c. Verify the setup once: connect to an endpoint that presents a different
   key. The client must fail with "Host key not verifiable". If it
   connects, the pin has not taken - re-check (a) and (b).

d. If the pins are kept in a TstSSHPublicKeyList: add the keys at run time
   with SetPublicKey. A PublicKeyFileName file does not load on the
   affected releases. Assign the list only to ServerRSAKey or ServerDSSKey;
   assigned to ServerECDSAKey or ServerEdDSAKey it registers nothing.

e. On a server, replace a host key by assigning the new key component; do
   not merely set the property to nil and continue running.

CREDIT
Found in an internal security review of the Snif/Snip framework and the
SSH components. There is no evidence of exploitation.

IDENTIFIER
This advisory is identified by the releases it applies to and the patch
number P01 (counted per release, at 4.1.4.360). CVE identifiers are not
used (SECURITY.txt, section 4).

Attachments:
Top

:: Written with and Powered by StreamSec Tools 4.1 ::
Copyright © 2000-2026 StreamSec Handelsbolag
Forum data layer and page templates derived from the RealThinClient SDK web-forum example, Copyright © 2004-2022 Teppi Technology (MIT)