SSHole on OpenWrt: is your router affected?
Stock OpenWrt runs Dropbear and is safe from CVE-2026-123158. Added openssh-server without PAM can let LAN devices log in. Check your router and patch it.
Is a stock OpenWrt router affected by SSHole?
SSHole on OpenWrt is a narrow problem: a stock router is not affected, because stock OpenWrt runs Dropbear as its SSH server, not OpenSSH. The flaw, CVE-2026-123158, sits in OpenSSH's password check when OpenSSH is built against musl (the small C library OpenWrt uses) without PAM (pluggable authentication modules). A router is exposed only when someone added the openssh-server package and kept its default of allowing password logins. A root password must also be set. On the current stable release, OpenWrt 25.12.6, the fixed build is openssh-server 10.6_p2-r1. It was already in the x86_64 package feed when this guide was checked on 9 November 2026.
If you run OpenSSH on a normal Linux server or VPS rather than a router, read whether the SSHole flaw affects your server instead. Everything below is specific to OpenWrt: its default SSH server, its package feeds, its account file and its firewall.
What SSHole is
The OpenSSH 10.6p2 release notes, published on 5 November 2026, describe "a critical security workaround" for Linux systems that use musl libc with PAM disabled. The CVE (Common Vulnerabilities and Exposures) record gives it a CVSS 3.1 score of 8.1, rated High, and covers OpenSSH before 10.6p2 on Linux. Özgün Kültekin of Wakefield reported it. The CVE record also lists public proof-of-concept repositories, so assume working exploit code exists.
The researcher's write-up at sshhole.com lists five conditions. The sshd server runs on musl. It does not use PAM. Password logins are on, which is the OpenSSH default. One account has just * as its password field. Some other account has a real password hash. When all five hold, the * account accepts any password between 257 and 1,024 characters long.
Why a long password opens a locked account
A * in the password field of /etc/shadow means "no password can ever match". sshd does not treat it as a special value. It hashes whatever the client sent and compares the result with the stored string.
A one-character stored value is too short to act as a salt, so sshd borrows one. Its pick_salt() function walks the accounts in /etc/passwd and takes the salt from the first shadow entry that starts with $. It does this so that a login attempt against a locked account takes as long as a real one.
musl's SHA-256 and SHA-512 crypt code refuses keys longer than 256 bytes (#define KEY_MAX 256 in its source). On that error it returns the string *. sshd then compares * with the stored *, and they match. The 1,024-byte upper limit comes from sshd itself, which rejects any password longer than MAX_PASSWORD_LEN, set to 1024.
The OpenSSH team says the root cause is outside sshd, but sshd can avoid it. The 10.6p2 fix adds MIN_PASSWORD_HASH_LEN, set to 4, and refuses any stored hash shorter than that. A * field can then never match.
Why Dropbear is not affected
The researcher's list of unaffected systems has four entries: glibc-based systems, anything that authenticates through PAM, Dropbear and OpenBSD. Dropbear's source shows why it is on that list. It rejects any password longer than DROPBEAR_MAX_PASSWORD_LEN, which is 100 bytes, before it calls crypt(). A 257-byte password never reaches musl's crypt code, so the * error string is never produced.
The OpenWrt 25.12.6 x86-64 image manifest lists dropbear - 2025.89-r3 and no OpenSSH package. Its C library is musl (libc - 1.2.5-r5), and its package manager is apk. If you never installed OpenSSH, your router is not affected by SSHole.
What a stock OpenWrt /etc/shadow contains
The account file comes from OpenWrt's base-files package. On the 25.12 branch it holds exactly this:
root:::0:99999:7:::
daemon:*:0:0:99999:7:::
ftp:*:0:0:99999:7:::
network:*:0:0:99999:7:::
nobody:*:0:0:99999:7:::Four service accounts carry the * value. Root starts with an empty field, which means no password at all. Packages that create their own service user through the user_add helper in /lib/functions.sh write x into the field. An x is not *, so those accounts do not meet the condition.
Root gets a real hash as soon as you set the router password. LuCI's password page goes through rpcd, which runs /bin/passwd. BusyBox passwd on both the 24.10 and 25.12 branches defaults to the sha256 algorithm, so the new hash starts with $5$. Root is the first line of /etc/passwd, so its $5$ salt is the one sshd borrows.
Put together: a stock image, plus the openssh-server package, plus a root password set in LuCI, meets all five conditions. The vulnerable accounts are daemon, ftp, network and nobody.
One detail limits the damage. Those four accounts have /bin/false as their shell in /etc/passwd, so an attacker gets no command prompt. Treat it as a real login anyway. OpenSSH's AllowTcpForwarding option defaults to yes, and port forwarding does not need a shell. A logged-in session can use the router to open connections to other hosts.
If root's hash was set long ago with MD5, it starts with $1$. musl's MD5 code accepts keys up to 30,000 bytes, so a long password produces a normal hash and the trick does not fire. Do not rely on this. A later password change moves you to $5$.
Who can reach SSH on an OpenWrt router?
The default firewall, firewall4, sets the wan zone's input policy to REJECT and ships no rule that opens port 22 from the WAN (wide area network) side. The lan zone's input policy is ACCEPT. Both Dropbear and OpenSSH listen on all addresses by default.
So the realistic attacker is a device on your LAN (local area network), such as a guest's laptop or a cheap camera that is already compromised. The exposure becomes internet-wide only if someone added a firewall rule or a port forward for port 22. If you did that, treat this as urgent.
A fresh router has a bigger LAN risk than SSHole. OpenWrt patches Dropbear so that root may log in with an empty password while the root password field is empty. Setting the router password closes that window.
Which SSH server is listening on port 22?
Log in to the router and run:
netstat -lntp | grep ':22 'The last column shows the process ID and the program name. If it says dropbear, you are not affected and you can stop here. If it says sshd, OpenSSH is serving port 22, so continue with the next checks.
Which openssh-server package is installed?
OpenWrt changed its package manager between releases. The 25.12 series uses apk, and its feed holds .apk files. The 24.10 series uses opkg, and its feed holds .ipk files.
On 25.12:
apk list -I 'openssh*'On 24.10:
opkg list-installed | grep opensshThe package name tells you about PAM. openssh-server is built --without-pam, so it is the variant at risk. openssh-server-pam is built --with-pam, and its install step also writes UsePAM yes and PasswordAuthentication no into /etc/ssh/sshd_config.
The fixed versions differ by branch:
- 25.12:
openssh-server10.6_p2-r1or later. The x86_64 feed for 25.12.6 carried this build, dated 6 November 2026. - 24.10:
openssh-server9.9_p2-r2or later. The upstream version stays 9.9p2. The-r2package release adds the 10.6p2 fix as a backported patch, committed on 5 November 2026. The x86_64 feed for 24.10.8 carried it, dated 6 November 2026.
Only the x86_64 feeds were checked here. Other targets build from the same source, so confirm your own version with the command above. The method in checking a server for known CVEs by package version applies here too: compare the installed package release with the fixed one, not the upstream version alone.
Is password authentication on in sshd?
Ask sshd for its effective setting rather than reading the file:
/usr/sbin/sshd -T | grep -i '^passwordauthentication'OpenWrt's openssh-server package copies the upstream sshd_config and only uncomments the HostKey lines. Upstream leaves #PasswordAuthentication yes commented out, so the built-in default applies, which is yes. Unless you changed it, you will see passwordauthentication yes.
Then list the accounts that match the two password-field conditions:
awk -F: '$2 == "*" {print $1}' /etc/shadow
awk -F: '$2 ~ /^\$/ {print $1, substr($2, 1, 3)}' /etc/shadowThe first command prints the * accounts. On a stock image that is daemon, ftp, network and nobody. The second prints each account with a real hash and only its type prefix, such as root $5$, so no hash leaves the screen. Your router is vulnerable when all four checks agree: an sshd listener, the openssh-server package below the fixed version, passwordauthentication yes, and output from both awk commands.
How to fix SSHole on OpenWrt, in order
1. Update the package
On 25.12:
apk update
apk upgrade openssh-server
/etc/init.d/sshd restart
apk list -I 'openssh-server*'On 24.10:
opkg update
opkg upgrade openssh-server
/etc/init.d/sshd restart
opkg list-installed | grep openssh-serverName the package you actually have, openssh-server-pam if that is the one installed. The restart matters, because the old sshd process keeps running the old code until it exits. The last line should show 10.6_p2-r1 on 25.12 or 9.9_p2-r2 on 24.10. If the update offers nothing newer, your router points at a feed with no fixed build. Move to the newest point release of your series, which on 9 November 2026 was 25.12.6 or 24.10.8.
2. Turn password logins off
Do this even after the update. A router has one real user, root, and root can log in with a key. OpenSSH's default PermitRootLogin prohibit-password already allows root key logins and blocks root password logins.
OpenSSH reads root's keys from /root/.ssh/authorized_keys. OpenWrt's Dropbear reads them from /etc/dropbear/authorized_keys. If you used keys with Dropbear before, copy them across:
mkdir -p /root/.ssh
chmod 700 /root/.ssh
cp /etc/dropbear/authorized_keys /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keysFrom your computer, open a second terminal and confirm a key login works before you change anything. Replace 192.168.1.1, OpenWrt's default LAN address, if your router uses a different one:
ssh -o PasswordAuthentication=no root@192.168.1.1If that fails with Permission denied (publickey), fix it first, because the next step removes your fallback. The causes are the same as on a server, and fixing SSH Permission denied (publickey) walks through them. Then switch password logins off and check the result:
sed -i -r 's/^#?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
/usr/sbin/sshd -t
/etc/init.d/sshd restart
/usr/sbin/sshd -T | grep -i '^passwordauthentication'sshd -t prints nothing when the file is valid. The last command should print passwordauthentication no. The other settings worth changing on a box you reach over SSH are the same ones covered in hardening SSH on a VPS.
3. Or go back to Dropbear
If you installed OpenSSH for one feature you no longer need, removing it is the cleanest fix. Dropbear is still part of the stock image. Running OpenSSH on port 22 means Dropbear was disabled or moved to another port, because two servers cannot listen on the same port. Put Dropbear back on port 22 and make sure your keys are where it looks for them:
cp /root/.ssh/authorized_keys /etc/dropbear/authorized_keys
chmod 600 /etc/dropbear/authorized_keys
/etc/init.d/sshd stop
/etc/init.d/sshd disable
uci set dropbear.@dropbear[0].Port='22'
uci commit dropbear
/etc/init.d/dropbear enable
/etc/init.d/dropbear restartOpen a new SSH session and run the netstat check again. It should now show dropbear on port 22. Only then remove the package, with apk del openssh-server on 25.12 or opkg remove openssh-server on 24.10. Run these steps from a session you can afford to lose, or from the router's serial console if it has one.
FAQ
Is a stock OpenWrt router vulnerable to SSHole (CVE-2026-123158)?
No. Stock OpenWrt images ship Dropbear, not OpenSSH, and the 25.12.6 x86-64 image manifest lists no OpenSSH package. The researcher lists Dropbear as unaffected. Dropbear rejects passwords longer than 100 bytes before hashing them, and the bypass needs 257 bytes or more. Run netstat -lntp | grep ':22 ' to confirm dropbear is the program on port 22.
My scanner says OpenSSH 9.9p2 on my OpenWrt 24.10 router is vulnerable. Is it?
Check the package release, not only the upstream version. The CVE record covers OpenSSH before 10.6p2, so a scanner that reads only the version flags 9.9p2. OpenWrt 24.10 kept 9.9p2 and added the 10.6p2 fix as a patch in package release 9.9_p2-r2. Run opkg list-installed | grep openssh-server. If it shows 9.9_p2-r2 or later, the fix is in. If it shows 9.9_p2-r1, update.
Does the openssh-server-pam package on OpenWrt have the same problem?
The researcher lists anything that authenticates through PAM as unaffected. OpenWrt builds openssh-server-pam with --with-pam, and its install step sets UsePAM yes and PasswordAuthentication no. If you later set UsePAM no by hand, you are back to the vulnerable setup, so update the package anyway.
Can SSHole be exploited from the internet on an OpenWrt router?
Not with the default firewall. The wan zone rejects inbound connections and no default rule opens port 22, so the exposure is devices on your LAN. It becomes reachable from the internet only if someone added a firewall rule or a port forward for SSH. In that case, update the package and turn password logins off right away.