Remediation Guides

SSH Weak MAC Algorithms Enabled: How to Disable MD5, 96-bit and SHA-1 MACs in sshd

26 September 2026 9 min read

SSH Weak MAC Algorithms Enabled means your SSH server still offers MACs that scanners treat as weak: MD5, 96-bit truncated MACs and, in newer checks, SHA-1 and umac-64. On Debian, Ubuntu and other hosts without crypto-policies, fix it with an explicit MACs line in sshd_config that allows only SHA-2 HMACs (ETM preferred) and umac-128-etm, validate with sshd -t, reload sshd and rescan. On RHEL-family systems that use crypto-policies, remove HMAC-SHA1 with a crypto-policy module (mac@SSH = -HMAC-SHA1) instead, because a MACs line in sshd_config has no effect there.

What the scanner is actually detecting

All of these checks are remote and configuration based. The scanner reads the MAC list the server advertises during the SSH handshake and compares it with its own list of weak names. The OpenSSH version and the MAC clients actually negotiate do not matter: if a weak name is advertised, the finding fires. The scanners disagree on what counts as weak:

Scanner Finding title ID What it flags
Nessus SSH Weak MAC Algorithms Enabled 71049 (Low) MD5 and 96-bit MACs, such as hmac-md5 and hmac-sha1-96
Nessus SSH SHA-1 HMAC Algorithms Enabled 153588 (Info) SHA-1 based HMACs, such as hmac-sha1 and hmac-sha1-etm@openssh.com
Greenbone / OpenVAS Weak MAC Algorithm(s) Supported (SSH) 1.3.6.1.4.1.25623.1.0.105610 MD5, 96-bit and 64-bit (umac-64*) MACs and ‘none’
Rapid7 InsightVM SSH Weak Message Authentication Code Algorithms ssh-weak-message-authentication-code-algorithms MD5 and 96-bit MACs; since January 2022 also umac-64, umac-64-etm, hmac-sha1 and hmac-sha1-etm
Qualys SHA1 deprecated setting for SSH QID 38909 SHA-1 anywhere in the SSH offer, including MACs, key exchange and host key algorithms

Qualys may also report MD5 and 96-bit MACs under QID 38739 (Deprecated SSH Cryptographic Settings). A stock OpenSSH server with no MACs line usually passes Nessus 71049, because upstream defaults no longer include MD5 or 96-bit MACs. It still trips Nessus 153588, Rapid7, Greenbone and the MAC part of Qualys 38909, because the default list still includes hmac-sha1, hmac-sha1-etm@openssh.com, umac-64@openssh.com and umac-64-etm@openssh.com.

How serious is it?

Honestly, not very. A MAC protects the integrity of each SSH packet, and HMAC does not depend on the hash being collision resistant. Tenable’s description of plugin 153588 states that SHA-1 is still considered secure for HMAC, and there is no known practical forgery attack on HMAC-MD5 either. The 96-bit and 64-bit variants shorten the tag, but exploiting that needs an active man-in-the-middle who beats the tag per packet before the connection drops.

The real reasons to fix it are hygiene and audit: weak entries widen what a downgrade can reach, appear in compliance baselines and bury more important findings. It is a low-risk, low-effort change; do not let it jump ahead of exploitable issues.

How to confirm it on the host

Check what sshd will actually use after all config files and includes are merged (run as root):

sudo sshd -T | grep -i '^macs'
grep -rin '^s*macs' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/ 2>/dev/null

On Debian, Ubuntu and other distributions without crypto-policies, an empty grep means sshd runs the compiled-in default list. On RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Fedora and CentOS Stream, the list comes from the system-wide crypto policy, which that grep never reads:

update-crypto-policies --show
cat /etc/crypto-policies/back-ends/opensshserver.config

On RHEL 9 and later, sshd -T already reflects the policy, because it is included through /etc/ssh/sshd_config.d/50-redhat.conf. On RHEL 8 the service passes the policy on the command line through $CRYPTO_POLICY, so a plain sshd -T prints the compiled-in defaults, not what the daemon runs. Load both environment files in the order the service does:

sudo bash -c 'set -a; . /etc/crypto-policies/back-ends/opensshserver.config; . /etc/sysconfig/sshd; /usr/sbin/sshd -T $CRYPTO_POLICY' | grep -i '^macs'

This stays correct after the CRYPTO_POLICY= opt-out in /etc/sysconfig/sshd described below, where a plain sudo sshd -T | grep -i '^macs' also works. Either way, confirm what the server advertises from another machine:

nmap -p 22 --script ssh2-enum-algos <host>

Any hmac-md5*, *-96, umac-64* or hmac-sha1* entry in the mac_algorithms block explains the finding. For a credentialed scan, see this guide to an authenticated Linux scan over SSH with sudo.

How to fix it

Debian, Ubuntu and other hosts that do not use crypto-policies

Back up the config and check whether it uses drop-ins:

sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
grep -n '^Include' /etc/ssh/sshd_config

If the file starts with Include /etc/ssh/sshd_config.d/*.conf, put the allow list in a drop-in. This single line removes hmac-md5*, every -96 variant, umac-64* and hmac-sha1*:

# /etc/ssh/sshd_config.d/10-macs.conf
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256

Drop-ins are read in lexical order before the rest of sshd_config, and sshd_config(5) keeps the first value it reads for each keyword. Make sure no lower-numbered drop-in (for example from a hardening role) also sets MACs; a MACs line later in the main file will be ignored.

If there is no Include line, add the same line to /etc/ssh/sshd_config above any Match block and comment out any older MACs line. Prefer this explicit list over the removal syntax (MACs -hmac-sha1*): auditors can read it, and it does not shift when a package update changes the defaults.

Validate and apply:

sudo sshd -t && sudo systemctl reload ssh     # Debian/Ubuntu service name
sudo sshd -t && sudo systemctl reload sshd    # most other distributions

sshd -t prints nothing when the config is valid. Keep a second root session open until a fresh login works. On Ubuntu 22.10 and later, sshd is socket activated: if ssh.service is not active, the reload fails harmlessly and the next connection uses the new config.

RHEL and other distributions that use crypto-policies

This covers RHEL 8, 9 and 10, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream and Fedora. Here sshd takes its algorithm lists from the crypto policy, so a MACs line in the main sshd_config has no effect: RHEL 8 passes the policy on the command line, and RHEL 9 and later read it first through 50-redhat.conf, and the first value wins.

A common suggestion is update-crypto-policies --set DEFAULT:NO-SHA1. That will not clear this finding: Red Hat documents that the NO-SHA1 module removes SHA-1 from signatures but still allows it in HMAC. Remove hmac-sha1 and hmac-sha1-etm@openssh.com with a small custom module scoped to SSH (scoped directives need RHEL 8.5 or later):

update-crypto-policies --show     # note the current value, for example DEFAULT
echo 'mac@SSH = -HMAC-SHA1' | sudo tee /etc/crypto-policies/policies/modules/NO-SSH-SHA1-MAC.pmod
sudo update-crypto-policies --set DEFAULT:NO-SSH-SHA1-MAC     # put your current value in place of DEFAULT
sudo systemctl restart sshd

Build the --set value from what --show printed, appending the module, for example DEFAULT:NO-SHA1:NO-SSH-SHA1-MAC or LEGACY:NO-SSH-SHA1-MAC. The module filename must be upper case. LEGACY and DEFAULT allow the same MACs, so the module alone clears this finding. Moving the base policy from LEGACY to DEFAULT is a separate, system-wide change: on RHEL 8 it also disables TLS 1.0/1.1, 3DES, RC4, DSA and RSA/DH below 2048 bits, and on RHEL 9 and later it mainly removes SHA-1 signatures and CBC ciphers in SSH. Test that on its own. Red Hat recommends a reboot after a policy change; for sshd alone, a restart is enough.

If you must manage sshd separately from the policy, Red Hat documents an opt-out. On RHEL 9 and later, put the MACs line above in a drop-in numbered below 50, such as /etc/ssh/sshd_config.d/49-crypto-policy-override.conf; it is read from the config files, so sshd -t and a reload apply it. On RHEL 8, uncomment CRYPTO_POLICY= in /etc/sysconfig/sshd, add the MACs line to /etc/ssh/sshd_config, then run sudo sshd -t && sudo systemctl restart sshd. A reload is not enough there, because on SIGHUP sshd re-executes itself with its original command-line -o options from the old policy. This opt-out is also the route on RHEL 8.0 to 8.4, where the scoped mac@SSH form is not available.

Verify the fix and rescan

sudo sshd -T | grep -i '^macs'
nmap -p 22 --script ssh2-enum-algos <host>

On RHEL 8, use the command from the confirm section that loads both environment files instead of a plain sshd -T, or trust the nmap result.

Then prove that a client asking only for SHA-1 is refused. Force a non-AEAD cipher, because with aes-gcm or chacha20-poly1305 no separate MAC is negotiated and the test would pass falsely:

ssh -o Ciphers=aes128-ctr -o MACs=hmac-sha1 user@<host>
# expected: Unable to negotiate ... no matching MAC found
ssh -o Ciphers=aes128-ctr -o MACs=hmac-sha2-256 user@<host>
# expected: normal login

Finally, rescan with the same policy that raised the finding; closure is what the scanner reads, not the config file.

What can break and how to roll back

  • Old clients and libraries that only know hmac-sha1 or hmac-md5: appliance SSH stacks, older Java or Python SSH libraries in backup and file transfer tools, and legacy SFTP partners. Unless they negotiate an AEAD cipher, they fail with “no matching MAC”.
  • Automation at scale, such as configuration management and credentialed scanners. Test one host from each tool before a fleet rollout.
  • Lockout is the real danger, and sshd -t plus an open second session covers it.

Rollback is quick. On Debian/Ubuntu, remove the drop-in or restore the backup (sudo cp -a /etc/ssh/sshd_config.bak.DATE /etc/ssh/sshd_config), then sshd -t and reload. On RHEL, run sudo update-crypto-policies --set with the value --show printed before the change, delete the .pmod file and restart sshd. If one legacy system genuinely needs SHA-1, note that MACs cannot be set inside a Match block; use a separate sshd on another port, firewalled to that system, as a documented exception.

Why the finding may still show up

  • Wrong daemon or port. The scanner hit a different SSH service: a second sshd, a container, a BMC or iLO interface, or an appliance on the same IP.
  • Config not applied. The file is correct but sshd was never reloaded (or, after the RHEL 8 opt-out, never restarted), or an earlier drop-in still sets MACs. sshd -T will show it.
  • Qualys 38909 covers more than MACs. SHA-1 key exchange or ssh-rsa host keys keep it open; the result section shows which list it flagged.
  • Different definitions of weak. Nessus 71049 closes after MD5 and -96 are gone, while 153588 still fires on hmac-sha1*, Rapid7 on hmac-sha1* and umac-64*, and Greenbone on umac-64*. Removing everything in the recommended line satisfies all of them.
  • Stale results. The report predates the change. For more causes, see our write-up on why vulnerability scanners report false positives.

FAQ

Is hmac-sha1 actually broken?

No. SHA-1 collisions do not translate into HMAC forgeries. Remove it for policy compliance, not because of an active attack.

Should I also remove the -etm MACs because of Terrapin?

No. Terrapin (CVE-2023-48795) affects chacha20-poly1305, and CBC ciphers combined with -etm MACs. The proper fix is OpenSSH with strict key exchange on both ends, and sshd_config(5) itself recommends EtM MACs as safer.

Does this change affect SSH keys or users’ authorized_keys?

No. MACs only protect packets after the handshake. Keys, host keys and authentication methods are separate settings.

Will Nessus 71049 remediation also clear Qualys 38909?

No. A fix that only removes MD5 and -96 (enough for 71049) leaves hmac-sha1, which QID 38909 flags. The MACs line in this guide clears the MAC part of 38909, but SHA-1 key exchange (diffie-hellman-group14-sha1 and similar) and ssh-rsa/ssh-dss host key algorithms need their own changes.

Tracking this finding across many hosts

On a large fleet this finding arrives as hundreds of near-identical rows from several scanners. SITEY, a self-hosted vulnerability management platform, imports results from 16 scanners, merges duplicates within each scanner, and can have AI draft host-specific remediation scripts that run through its Linux agents only after human approval, then re-tests to confirm closure. Per-finding retest is available for Nessus results.

Sources

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing