Description
The OpenSSH server negotiates three families of algorithms with each client, set by
Ciphers, MACs and KexAlgorithms in sshd_config. This control requires every algorithm
the server offers to be in an allow list:
- ciphers: ChaCha20-Poly1305, AES-GCM, AES-CTR;
- MACs: HMAC-SHA2-256/512, preferably in encrypt-then-MAC (
-etm) mode; - key exchange: hybrid post-quantum (
mlkem768x25519-sha256,sntrup761x25519-sha512), Curve25519, NIST ECDH, and Diffie-Hellman groups of at least 2048 bits with SHA-2.
The first key exchange algorithm offered must be a hybrid post-quantum one.
Ubuntu ships OpenSSH 8.2 (20.04), 8.9 (22.04), 9.6 (24.04) and 10.2 (26.04). All of them
exclude weak ciphers but still offer SHA-1 and UMAC MACs. Only 26.04 puts a post-quantum key
exchange first; 22.04 and 24.04 offer [email protected] after Curve25519,
and 20.04 has none (its [email protected] is an older, withdrawn
variant), so the post-quantum check does not apply to 20.04. The fix writes the three lists in
/etc/ssh/sshd_config.d/00-cirsec.conf, read before the cloud image files (50-cloud-init.conf,
60-cloudimg-settings.conf) since sshd keeps the first value it reads, keeping only the
algorithms the installed OpenSSH supports (ssh -Q): mlkem768x25519-sha256 is only set on
26.04. On 24.04 and later, sshd is started by ssh.socket; sshd -T fails with a missing
/run/sshd until a first connection has started ssh.service, so the checks report an error
until then, and the fix creates the directory before testing the configuration.
Rationale
CBC ciphers, RC4, 3DES, SHA-1 and MD5 based MACs, 64-bit tag UMAC and SHA-1 Diffie-Hellman are broken or too weak for long-term protection; UMAC is kept out to stay with the widely reviewed HMAC-SHA2 constructions. Sessions recorded today can be decrypted later by a quantum computer unless the key exchange is post-quantum, which is why it must be preferred.
Impact
Old clients and network equipment that only support removed algorithms cannot connect anymore
(for example hmac-sha1 or diffie-hellman-group14-sha1). Check the clients, automation tools
and SFTP libraries in use before applying.
Applies when
Detected: when: OpenSSH server is installed A scanner reports the control not applicable when one is false.
Setting
| Location | /etc/ssh/sshd_config.d/00-cirsec.conf (`Ciphers`, `MACs`, `KexAlgorithms`) |
| Default | OpenSSH defaults, including hmac-sha1 and umac-64 MACs |
| Recommended | Only the allowed algorithms, post-quantum key exchange first |
Audit
Run sshd -T | grep -E '^(ciphers|macs|kexalgorithms) ' and check that:
- ciphers are among
[email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr; - MACs are among
[email protected],[email protected],hmac-sha2-512,hmac-sha2-256; - key exchange algorithms are among
mlkem768x25519-sha256,sntrup761x25519-sha512(with or without@openssh.com),curve25519-sha256(with or without@libssh.org),ecdh-sha2-nistp256/384/521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512, and the first one ismlkem768x25519-sha256orsntrup761x25519-sha512.
Automated: every check must pass. Scanners report each check by its id.
ciphers
Effective Ciphers list.
key: ciphers
operator: match
value: ^((chacha20-poly1305@openssh\.com|aes(128|256)-gcm@openssh\.com|aes(128|192|256)-ctr)(,|$))+$
macs
Effective MACs list.
key: macs
operator: match
value: ^(hmac-sha2-(256|512)(-etm@openssh\.com)?(,|$))+$
kex
Effective KexAlgorithms list.
key: kexalgorithms
operator: match
value: ^((mlkem768x25519-sha256|sntrup761x25519-sha512(@openssh\.com)?|curve25519-sha256(@libssh\.org)?|ecdh-sha2-nistp(256|384|521)|diffie-hellman-group-exchange-sha256|diffie-hellman-group14-sha256|diffie-hellman-group(16|18)-sha512)(,|$))+$
kex-post-quantum
First key exchange algorithm is a hybrid post-quantum one.
key: kexalgorithms
operator: match
value: ^(mlkem768x25519-sha256|sntrup761x25519-sha512(@openssh\.com)?)(,|$)
Remediation
Create /etc/ssh/sshd_config.d/00-cirsec.conf (mode 0600) with the lists below, removing the
algorithms that ssh -Q cipher, ssh -Q mac or ssh -Q kex does not print:
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
MACs [email protected],[email protected],hmac-sha2-512,hmac-sha2-256
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,[email protected],curve25519-sha256,[email protected],ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256,diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,diffie-hellman-group14-sha256
Check with sshd -t, then run systemctl reload ssh (on 24.04 and later, when ssh.service
is not running yet, the next connection starts it with the new settings). Keep an open
session until a new connection succeeds.
| Restart | service: ssh |
| Disruption | low |
| Lockout risk | yes: can cut off administrative access. Off by default in generated scripts and playbooks, opt in through a tailoring file. |
Rollback
Remove the three lines from /etc/ssh/sshd_config.d/00-cirsec.conf and run systemctl reload ssh.
algorithms
# CB-UBU-NET-015: set strong SSH server algorithms, keeping only those this OpenSSH version supports.
PATH="$PATH:/usr/sbin"
# sshd -T and -t need /run/sshd, which only exists once ssh.service has run (ssh.socket on 24.04 and later).
[ -d /run/sshd ] || mkdir -p -m 0755 /run/sshd
f=/etc/ssh/sshd_config.d/00-cirsec.conf
grep -Eqi '^[[:space:]]*Include[[:space:]]+/etc/ssh/sshd_config.d/\*\.conf' /etc/ssh/sshd_config || {
echo '/etc/ssh/sshd_config does not include sshd_config.d/*.conf' >&2
exit 1
}
# keep TYPE LIST: the algorithms of LIST that "ssh -Q TYPE" knows, comma separated, in LIST order.
keep() {
sup=$(ssh -Q "$1") || return 1
out=
for a in $(printf '%s' "$2" | tr ',' ' '); do
printf '%s\n' "$sup" | grep -Fxq -- "$a" && out="${out:+$out,}$a"
done
[ -n "$out" ] && printf '%s' "$out"
}
nokeep() {
echo "ssh -Q $1 failed or knows none of the recommended algorithms" >&2
exit 1
}
c=$(keep cipher [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr) || nokeep cipher
m=$(keep mac [email protected],[email protected],hmac-sha2-512,hmac-sha2-256) || nokeep mac
k=$(keep kex mlkem768x25519-sha256,sntrup761x25519-sha512,[email protected],curve25519-sha256,[email protected],ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256,diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,diffie-hellman-group14-sha256) || nokeep kex
mkdir -p /etc/ssh/sshd_config.d
cb_backup "$f"
touch "$f"
chmod 600 "$f"
sed -i '/^[[:space:]]*\(ciphers\|macs\|kexalgorithms\)[[:space:]]/Id' "$f"
printf 'ciphers %s\nmacs %s\nkexalgorithms %s\n' "$c" "$m" "$k" >>"$f"
if ! sshd -t; then
cb_restore "$f"
echo 'sshd -t rejected the change, reverted' >&2
exit 1
fi
Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.
References
- sshd_config(5), Ubuntu manual pages Canonical, vendor-doc, accessed 2026-10-19
- ssh(1), Ubuntu manual pages (ssh -Q) Canonical, vendor-doc, accessed 2026-10-19
- OpenSSH - Post-Quantum Cryptography OpenSSH, vendor-doc, accessed 2026-10-19
- NIST IR 7966 - Security of Interactive and Automated Access Management Using Secure Shell (SSH) NIST, guide, accessed 2026-10-19
Mappings
| Framework | ID | Relation | Note |
|---|---|---|---|
| NIST SP 800-53 Rev. 55.1.1 | SC-8 | partial | |
| NIST SP 800-53 Rev. 55.1.1 | SC-13 | partial |
How this control relates to the other framework's: equivalent, stricter, looser, partial or related.
Threats mitigated
People and lifecycle
| Authors |
|
| Verified | 2026-10-19 by Sn0wAlice on 20.04, Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic, BIOS boot. MACs with UMAC and SHA-1 reported, post-quantum check not applicable; fix.sh writes the lists filtered with ssh -Q; a UMAC client is refused; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot. |
| Verified | 2026-10-19 by Sn0wAlice on 22.04, Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic, BIOS boot. MACs and post-quantum order reported; fix.sh puts [email protected] first; a UMAC client is refused; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot. |
| Verified | 2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic, BIOS boot. Checks report an error before the first SSH connection (no /run/sshd), then MACs fail; fix.sh works on a fresh boot; a UMAC client is refused; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot. |
| Verified | 2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic, BIOS boot. MACs reported, mlkem768x25519-sha256 already first; fix.sh writes the lists filtered with ssh -Q; a UMAC client is refused; SSH by key of a non-root user accepted on localhost and port 22 reachable from the lab host after the fix and after reboot. |
| Introduced in | v0.1.0 |
| Created, updated | 2026-10-19, 2026-10-19 |
| Translations | fr |