Skip to navigation

Threat reportVulnerabilityTL-2026-5672

SSHole (CVE-2026-123158) - OpenSSH on musl-based Linux oversized password authentication bypass, exploited in the wild

criticalACTIVE

CVE-2026-123158 ('SSHole' / '*sshole') is an authentication bypass in OpenSSH sshd before 10.6p2 on musl libc systems without PAM (notably Alpine Linux): an oversized password (>256 bytes) authenticates to accounts whose shadow hash is '*'. Exploitation began within hours of the 2026-11-05 disclosure, GreyNoise has observed post-exploitation chains including SSH key implantation and a Python C2 agent ('TAC Agent'), and CISA added the CVE to KEV on 2026-11-09.

Key facts

IdentifiersTL-2026-5672, CVE-2026-123158
Also known asSSHole, *sshole, sshhole
SeverityCRITICAL
CVSS8.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H)
First disclosed
EPSSCVE-2026-123158: 0.9% (62.2th percentile)
Affected productsOpenBSD / OpenSSH OpenSSH portable (sshd) on musl libc without PAM; Alpine Linux openssh-server (non-PAM) / tiny-cloud images; Various Other musl-based Linux (OpenWrt, Buildroot, Yocto, musl-based container images)
Weaknesses (CWE)CWE-394
MalwareTAC Agent
MITRE ATT&CK techniquesT1003.008 /etc/passwd and /etc/shadow, T1033 System Owner/User Discovery, T1059.004 Unix Shell, T1059.006 Python, T1071.001 Web Protocols, T1078.003 Local Accounts, T1082 System Information Discovery, T1098.004 SSH Authorized Keys, T1136.001 Local Account, T1190 Exploit Public-Facing Application, T1543 Create or Modify System Process, T1548 Abuse Elevation Control Mechanism and 4 more in the attack flow
MotivationUNKNOWN
Target sectorscloud, technology, telecoms, embedded-iot
Target regionsGlobal
Detection rules9 (1 shown free)
Sources15 cited sources

Detection coverage

As of 2026-11-10, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-5672 across Splunk SPL, Microsoft KQL and Sigma, covering 21 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.

Free detection: SSHole CVE-2026-123158 - Password Login Accepted for Passwordless/Key-Only Account (sshd)

Detects the exploitation signature of CVE-2026-123158 (SSHole) on musl-based Linux (Alpine, OpenWrt, Buildroot): sshd logs 'Accepted password for' an account that normally has no usable password (alpine, root, key-only deploy users, the attacker-created server_manager). The oversized-password (>256 bytes) bypass succeeds only against accounts whose shadow hash is '*', so a password-based success for these accounts is a high-fidelity compromise indicator. Also flags sources matching GreyNoise/Previdian-reported SSHole attacker IPs.

  • Languages: Splunk SPL, Microsoft KQL, Sigma
  • ATT&CK: T1190, T1078.003
  • Data sources: linux_syslog (index=linux sourcetype=syslog), sshd authentication logs (/var/log/messages)
  • Severity: critical
  • Confidence: high

Splunk SPL

index=linux sourcetype=syslog sshd "Accepted password for" earliest=-24h
| rex field=_raw "Accepted password for (?<auth_user>[^ ]+) from (?<src_ip>[0-9.]+) port (?<src_port>[0-9]+)"
| where isnotnull(auth_user) AND in(auth_user,"alpine","root","server_manager")
| eval ioc_match=if(in(src_ip,"89.116.89.18","183.220.91.15","20.255.63.133","20.2.81.241","209.248.50.17","47.80.65.43","152.175.65.88","202.155.94.33","79.116.138.30","196.128.138.201","43.224.227.158","213.86.169.133","31.59.220.26"),"known_sshole_ip","none")
| stats count as logins min(_time) as first_seen max(_time) as last_seen values(auth_user) as auth_users values(ioc_match) as ioc_match by host src_ip
| convert ctime(first_seen) ctime(last_seen)
| table host src_ip auth_users logins ioc_match first_seen last_seen

Microsoft KQL

Syslog
| where TimeGenerated > ago(24h)
| where ProcessName =~ 'sshd' and SyslogMessage has 'Accepted password for'
| extend AuthUser = extract(@'Accepted password for ([^ ]+) from', 1, SyslogMessage), SrcIp = extract(@'from ([0-9.]+) port', 1, SyslogMessage)
| where AuthUser in~ ('alpine', 'root', 'server_manager')
| extend KnownAttackerIp = SrcIp in ('89.116.89.18','183.220.91.15','20.255.63.133','20.2.81.241','209.248.50.17','47.80.65.43','152.175.65.88','202.155.94.33','79.116.138.30','196.128.138.201','43.224.227.158','213.86.169.133','31.59.220.26')
| summarize Logins = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), Users = make_set(AuthUser) by Computer, SrcIp, KnownAttackerIp
| project Computer, SrcIp, Users, Logins, KnownAttackerIp, FirstSeen, LastSeen

Sigma

title: SSHole CVE-2026-123158 - Password Login Accepted for Passwordless Account
id: 3f7a9c1e-5b2d-4e68-9a41-7c0d8e2b6f11
status: experimental
description: Detects sshd accepting a password login for accounts that normally have no usable password (alpine, root, server_manager), the signature of the CVE-2026-123158 SSHole oversized-password authentication bypass on musl-based Linux.
references:
    - https://nvd.nist.gov/vuln/detail/CVE-2026-123158
    - https://www.greynoise.io/blog/global-event-sshole-cve-2026-123158-live-activity-report
author: Threadlinqs Team
date: 2026-11-10
tags:
    - attack.initial-access
    - attack.t1190
    - attack.t1078.003
    - cve.2026.123158
logsource:
    product: linux
    service: sshd
detection:
    keywords:
        - 'Accepted password for alpine from'
        - 'Accepted password for root from'
        - 'Accepted password for server_manager from'
    condition: keywords
falsepositives:
    - Administrators who legitimately set a password on root or alpine and log in with it
    - Break-glass console-style password access on lab systems
level: critical

Known false positives:

  • Accounts (root/alpine) that intentionally have a real password and use password login
  • Legacy automation that authenticates to root with a password

Tuning notes: Extend the account list with your key-only/service/deploy users and directory-service users that carry '*' in /etc/shadow. Add known-good admin source CIDRs to an exclusion. Any hit on a host running OpenSSH < 10.6p2 without PAM should be treated as compromise. Adjust the index/sourcetype to where Alpine /var/log/messages is ingested.

8 more detection rules (Splunk SPL, Microsoft KQL, Sigma) · unlock with TL Creds. Sign up free to unlock the detection rules or query them with the Threadlinqs MCP server (Purple)
  • SSHole CVE-2026-123158 - sshd Activity from Known SSHole Attacker Infrastructure · unlock with TL Creds
  • SSHole Post-Exploitation - server_manager Account Creation with Passwordless doas Rule · unlock with TL Creds
  • SSHole C2 - TAC Agent Python Implant Files and OpenRC Persistence · unlock with TL Creds
  • SSHole CVE-2026-123158 - Internet-Sourced Password Login to Default Cloud 'alpine' User · unlock with TL Creds
  • SSHole Post-Exploitation - Credential Access and Discovery (shadow, root SSH keys, cloud metadata, id/uname) · unlock with TL Creds
  • SSHole C2 - TAC Agent Spawning Shell Commands (/bin/sh -c) from Python Implant · unlock with TL Creds
  • SSHole Post-Exploitation - Attacker SSH Key Planted in authorized_keys (fleet-access / SSHHOLE-HIT) · unlock with TL Creds
  • SSHole C2 - TAC Agent Beacon to [indicator] (TAC-Agent/1.0, /agent/poll ~150s) · unlock with TL Creds

Indicators of compromise

As of 2026-11-10, Threadlinqs Intelligence tracks 21 indicators of compromise for TL-2026-5672.

Sample indicators (3 of 21)

  • IP address: 89.116.89[.]18
  • Domain: tac[.]vpnla[.]org
  • File hash: 55e6384f6d1648be9b48fb899e46623e9c05eb0df2cbf95f6701680d4e7cbc2a

Defanged, TLP:CLEAR. Full set of 21 indicators: unlock with TL Creds.

21 indicators of compromise · unlock with TL Creds. Compare plans

Technical analysis

CVE-2026-123158 is a logic flaw in the interaction between OpenSSH's password authentication and musl libc's crypt(). Accounts that must never accept a password store '*' in the /etc/shadow hash field. Since a 2016 change (to mitigate username enumeration, CVE-2016-6210), when the target account has no usable hash OpenSSH borrows the salt/settings of another account and hashes the supplied password anyway. musl's crypt() refuses SHA-256/SHA-512 inputs longer than 256 bytes and returns the failure string '*', which then string-compares equal to the locked account's stored '*' and sshd accepts the login. NVD describes the condition as any password of 256 to 1024 characters succeeding for some account configurations. The flaw is not memory corruption; it is an unexpected return-value handling issue (CWE-394).

Exploitation conditions: sshd built without PAM (or Alpine openssh-server-pam with UsePAM no), PasswordAuthentication enabled (the OpenSSH default), at least one account with '*' in its password field (root in the Alpine base image when PermitRootLogin permits it, key-only deploy users, directory-service users, or the default 'alpine' user in tiny-cloud images), and at least one other local account with a real $5$/$6$ hash. The attacker must know a valid password-disabled account name. Alpine's default cloud 'alpine' user has passwordless doas, so bypass of that account leads directly to root. Not affected: glibc systems (Debian, Ubuntu, Fedora), PAM-based password authentication, PasswordAuthentication no, accounts with '!' instead of '*', Dropbear, and OpenBSD. Other musl-based platforms named by researchers include OpenWrt, Buildroot, Yocto and many Docker base images. The issue was reported to OpenSSH by Ozgun Kultekin of Wakefield. Fixed in OpenSSH 10.6p2 (2026-11-05); Alpine backported fixes to branches 3.16 through edge.

Exploitation timeline (GreyNoise, UTC): a public exploit appeared on GitHub on 2026-11-05 13:16, about 3 hours before the NVD record was published; GreyNoise tagged the first CVE-specific exploit attempt on 2026-11-05 18:34 and the first successful exploitation on 2026-11-07 00:46. Previdian separately reported eight attempts from 89.116.89.18 beginning under nine hours after CVE publication, including root access on an Alpine honeypot followed by id/uname/hostname reconnaissance. By 2026-11-10 GreyNoise reported 23 confirmed post-exploitation chains from 7 attacker IPs against its sensors, against a background of roughly 41.2M TCP/22 SYN scans and 30.5M SSH connection attempts. Public proof-of-concept repositories exist and defenders are warned that unverified PoCs may contain malware.

Observed post-exploitation (GreyNoise sensor victims): discovery (id, uname, os-release, /etc/passwd, mount/container checks, route and interface enumeration, virtualization checks), credential access attempts (doas cat /etc/shadow, reading root authorized_keys and ssh keys), cloud metadata probing (169.254.169.254, 100.100.100.200), connectivity tests, planting SSH public keys in /root and /home/alpine authorized_keys (comments 'fleet-access' and 'SSHHOLE-HIT'), creating a 'server_manager' account with a passwordless doas rule, and staging a Python runtime plus the 'TAC Agent' implant with an OpenRC init script. GreyNoise groups two intrusions across seven addresses as cluster 'GT10'; no named threat actor is attributed in any source. TAC Agent is a single-file Python 3 (stdlib-only) implant (/opt/py3/tac_agent.py, 89,559 bytes, v0.1.1) that beacons over HTTPS to tac.vpnla.org (Cloudflare Worker, port 8443) with GET /agent/poll every ~150s, supports sysinfo recon, file preview/download/upload, unsigned self-update and arbitrary /bin/sh -c execution, and uses User-Agent TAC-Agent/1.0. Enrollment failed on the first victim and no tasking was observed. Note: Safe Security's 2026-11-06 write-up stated no confirmed exploitation, which predates GreyNoise's observations. BeaconBeagle lookups for 89.116.89.18 and tac.vpnla.org returned HTTP 502 and could not be completed.

MITRE ATT&CK techniques by tactic:

Credential Access

T1003.008 /etc/passwd and /etc/shadow; T1552.004 Private Keys; T1552.005 Cloud Instance Metadata API

Discovery

T1033 System Owner/User Discovery; T1082 System Information Discovery

Execution

T1059.004 Unix Shell; T1059.006 Python

Command and Control

T1071.001 Web Protocols

Initial Access

T1078.003 Local Accounts; T1190 Exploit Public-Facing Application

Persistence

T1098.004 SSH Authorized Keys; T1136.001 Local Account; T1543 Create or Modify System Process

Privilege Escalation

T1548 Abuse Elevation Control Mechanism

Reconnaissance

T1595.002 Vulnerability Scanning

defense-impairment

T1690 Prevent Command History Logging

Remediation

Patches

  • OpenSSH 10.6p2
  • Alpine fixed openssh: edge 10.6_p2-r0, 3.24 10.3_p1-r2, 3.23 10.2_p1-r1, 3.22 10.0_p1-r11, 3.21 9.9_p2-r1, 3.20 9.7_p1-r6, 3.19 9.6_p1-r3, 3.18 9.3_p2-r4, 3.17 9.1_p1-r7, 3.16 9.0_p1-r6
  • Alpine tiny-cloud images 3.21.10, 3.22.8, 3.23.8, 3.24.4 and later

Immediate actions

  • Upgrade OpenSSH to 10.6p2 or the distro-fixed package (Alpine: apk upgrade -U -a) and RESTART sshd (rc-service sshd restart); installing the package alone does not replace the running daemon
  • If patching is not immediately possible, verify key-based login works, then set PasswordAuthentication no (e.g. in /etc/ssh/sshd_config.d/) and restart sshd; this blocks the attack but is not a complete fix
  • Hunt logs (/var/log/messages) for 'Accepted password for' on accounts with no password (alpine, root, key-only users); treat any hit as a compromise
  • Review authorized_keys for all accounts, doas rules (/etc/doas.d/), new users such as server_manager, /etc/init.d/tac-agent, /opt/py3/ and ~/.config/tac/agent.json
  • Block tac.vpnla.org at DNS/proxy and alert on the TAC-Agent/1.0 user agent; do not block the shared Cloudflare IP 104.21.88.83 alone
  • Restrict internet exposure of TCP/22 and use VPN or bastion access

Workarounds

  • Set PasswordAuthentication no and restart sshd
  • Disable SSH on affected hosts until patched
  • Use PAM-enabled sshd (UsePAM yes)

Longer-term hardening

  • Rebuild Docker and cloud images from fixed base images
  • Prefer key-only authentication with PasswordAuthentication no as a baseline on all SSH servers
  • Enable PAM-based authentication (openssh-server-pam with UsePAM yes) where supported
  • Inventory musl-based systems (Alpine, OpenWrt, Buildroot, Yocto, embedded devices) running OpenSSH
  • Remove passwordless doas/sudo for default cloud users

Affected and fixed versions

  • OpenBSD / OpenSSH — OpenSSH portable (sshd) on musl libc without PAM
    Vulnerable versions: < 10.6p2
    Fixed in: 10.6p2
  • Alpine Linux — openssh-server (non-PAM) / tiny-cloud images
    Vulnerable versions: 3.16 through 3.24 and edge (openssh before per-branch fixed versions); tiny-cloud images 3.18.11 through 3.24.3
    Fixed in: edge 10.6_p2-r0; 3.24 10.3_p1-r2; 3.23 10.2_p1-r1; 3.22 10.0_p1-r11; 3.21 9.9_p2-r1; tiny-cloud 3.21.10, 3.22.8, 3.23.8, 3.24.4
  • Various — Other musl-based Linux (OpenWrt, Buildroot, Yocto, musl-based container images)
    Vulnerable versions: OpenSSH < 10.6p2 built without PAM
    Fixed in: OpenSSH 10.6p2 or vendor backport

Timeline

  • OpenSSH fix committed (not yet public) at 21:18 UTC
  • GreyNoise tags first CVE-2026-123158 exploit attempt (18:34 UTC); Previdian reports first attempt under nine hours after CVE publication from locked-ioc-16
  • CVE-2026-123158 reserved and published to NVD at 16:17 UTC with CVSS 3.1 base score 8.1
  • First public exploit appears on GitHub (13:16 UTC), before the CVE record was published
  • OpenSSH 10.6p2 released; fix published to public repo; Alpine publishes advisory and patched packages back to branch 3.16
  • GreyNoise publishes the SSHole live activity report; Help Net Security and others report in-the-wild exploitation
  • First successful exploitation observed by GreyNoise (00:46 UTC); GT10 intrusions begin on victims #1 (10:12 UTC) and #2 (19:41 UTC), staging Python and TAC Agent
  • 'fleet-access' SSH key planted in /home/alpine/.ssh/authorized_keys on a GreyNoise sensor host
  • CISA adds CVE-2026-123158 to the Known Exploited Vulnerabilities catalog (due date 2026-11-12)
  • locked-ioc-14 plants 'SSHHOLE-HIT' key for root and alpine; locked-ioc-6 creates server_manager account with passwordless doas; GreyNoise reports 23 post-exploitation chains from 7 attacker IPs

Sources cited

Other reports on CVE-2026-123158

Previous and next in vulnerability

Further reading

Drafted by the Threadlinqs research pipeline from 15 sources; published ; last updated —.

Threadlinqs Intelligence — Real-Time Threat Detection Platform

// threat_feed
$ sort --newest
Showing all threats

Live intelligence console

Threat level

Latest Threats