Debian GNU/Linux · Network

Use only strong ciphers, MACs and key exchange algorithms in the SSH server

When it fails: The SSH server accepts weak or outdated cryptographic algorithms. Weak algorithms let an attacker who records or intercepts SSH sessions decrypt or tamper with them, now or later.

CB-DEB-NET-015mediumactiveautomatedautomated fix, lockout riskprofile core

As released in v0.1.1 beta · pre-release. Current state.

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.

Debian 12 (OpenSSH 9.2) and 13 (OpenSSH 10.0) already exclude weak ciphers and put a post-quantum key exchange first, but both still offer SHA-1 and UMAC MACs. The fix writes the three lists in /etc/ssh/sshd_config.d/00-cirsec.conf, keeping only the algorithms the installed OpenSSH supports (ssh -Q), so mlkem768x25519-sha256 is only set on Debian 13.

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`)
DefaultOpenSSH defaults, including hmac-sha1 and umac-64 MACs
RecommendedOnly the allowed algorithms, post-quantum key exchange first

Audit

Run sshd -T | grep -E '^(ciphers|macs|kexalgorithms) ' and check that:

  1. ciphers are among [email protected], [email protected], [email protected], aes256-ctr, aes192-ctr, aes128-ctr;
  2. MACs are among [email protected], [email protected], hmac-sha2-512, hmac-sha2-256;
  3. 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 is mlkem768x25519-sha256 or sntrup761x25519-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. Keep an open session until a new connection succeeds.

Restartservice: ssh
Disruptionlow
Lockout riskyes: 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-DEB-NET-015: set strong SSH server algorithms, keeping only those this OpenSSH version supports.
PATH="$PATH:/usr/sbin"
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

Mappings

FrameworkIDRelationNote
NIST SP 800-53 Rev. 55.1.1SC-8partial
NIST SP 800-53 Rev. 55.1.1SC-13partial

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-18 by Sn0wAlice on 12, Proxmox VM 921, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. fix.sh writes the lists filtered with ssh -Q; SSH by key accepted before and after the fix and after reboot.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM 931, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. fix.sh writes the lists filtered with ssh -Q; SSH by key accepted before and after the fix and after reboot.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr