Repository navigation
Add the sshole detector for the OpenSSH password bypass on musl - #6
Merged
Merged
Conversation
Finds OpenSSH servers exposed to *sshole (fixed in OpenSSH 10.6p2 and in Alpine's openssh packages of 2026-11-05) and plans verified fixes in source trees. - fs and image: judges each sshd by its C library, its release and the apk database (Alpine 3.16 to 3.24 and edge backports), then follows musl's shadow lookup, sshd's salt choice and musl's crypt failures, and sshd_config with Include and Match, to report which accounts a crafted password reaches. PAM-checked builds are inactive. - host: reads the banner and the offered login methods; never sends a password. engine.ErrNotApplicable lets a host scan skip a detector whose service is not on that address. - repo and fix: apk installs of an OpenSSH server on Alpine (base release read from the image when the tag does not name it) get the fixed floor, and password fields set to "*" become "*NP*". Each edit is rescanned in memory before it is written. - parity/sshole.py: eight fixture images, all matching. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fuse symlinked reads Also adds repo.Find and Options.Files for callers that rescan one finding or a pull request's changed files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves netguard from detectors/php2shell/internal to internal, unchanged, and adds image.OpenRegistry, which takes a transport and refuses local archives. Base images a source tree names are now checked against the address policy on every connection and redirect, not before them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…urce trees Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ee gaps - Images: sshd -o and -f from the container command and startup scripts (entrypoints, s6, cont-init.d, entrypoint.d) change the config judged; a startup script that turns password logins on, sets a "*" field or sets passwords with chpasswd makes an unfixed server exposed (high). The engine passes the image's Entrypoint and Cmd (TargetContext.Command). - OpenWrt's opkg database and its 23.05, 24.10 and 25.12 fixes. - Source trees: apk package lists in ARG and ENV (edited where the value is written), unresolved variables as notes, Ansible apk tasks (fix: state: latest), Buildroot, OpenWrt and Yocto configurations that build OpenSSH on musl, and an end-of-life alpine:3.N base moved to 3.16 as a labelled upgrade. - parity/sshole.py: ten images, all matching. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… flags; ignore disagreeing or test-mode sshd command lines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, retag and patch fixes - scan repo pulls the images a tree references through the guarded transport (engine Options.Guarded, at most 20) and judges them with the Compose entrypoint/command or Kubernetes command/args set for them (engine Options.Override; image.Opened keeps Entrypoint and Cmd). - fix: an end-of-life Alpine-suffixed base (python:3.9-alpine3.14) moves to the same tag on the nearest fixed Alpine release once that image is confirmed to be that release; Buildroot and Yocto builds get upstream commit 4353fdc43 as a patch scoped to OpenSSH 8.9p1 to 10.6p1 (applies cleanly to every release in that range; patched 8.9p1, 9.9p2 and 10.6p1 build on musl). Fixes can now add files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the
ssholedetector for *sshole, the OpenSSH password authentication bypass on musl libc, fixed in OpenSSH 10.6p2 (commit 4353fdc43) and in Alpine's openssh packages of 2026-11-05.On musl, sshd from 7.3p1 to 10.6p1 compares an account's password field of
*with the*that crypt returns when it fails. The donor salt sshd borrows decides which passwords make crypt fail: sha256 or sha512 above 256 bytes, bcrypt or a badrounds=value for every password.What it checks
UsePAM,sshd_configwith Include and Match (PasswordAuthentication, AuthenticationMethods, PermitRootLogin, Allow/Deny lists, ChrootDirectory), and the accounts read the way musl reads them.exposed(critical, or high when a Match decides) names the accounts;sshdcovers unfixed builds that today's accounts or settings do not expose, fixed builds and PAM-checked ones.engine.ErrNotApplicablelets a host scan skip a detector whose service is not on that address.apk addof an OpenSSH server on Alpine gets the fixed release floor for its branch (read from the base image through the guarded transport when the tag does not name it). Password fields set to*(usermod, chpasswd -e, sed on /etc/shadow, Ansible and cloud-init) become*NP*. Every edit is rescanned in memory first.Other changes
netguardmoves fromdetectors/php2shell/internaltointernal, unchanged (noted in SNAPSHOT).image.OpenRegistrytakes a transport and refuses local archives.Testing
go vet ./...,go test -race ./..., fuzzing of Inspect, accounts, config and the source-tree scanner.parity/sshole.py: 8/8 fixture images (unfixed, fixed, password logins off, UsePAM on, root with PermitRootLogin, Match on address, Alpine 3.24, Debian).fixon a sample tree, then a rebuild of the edited Dockerfile, gives an image the detector reports fixed.The Sensei port is in DefectDojo-Inc/defectdojo-scan-and-fix (branch
devgrega/sshole-sensei).Added after review: coverage gaps closed
sshd -o,-f, throughtini,sh -cand wrappers) and its startup scripts (the command's script, s6-overlay,cont-init.d,entrypoint.d,/etc/s6). A script that turns password logins on, sets a*field or sets passwords withchpasswdmakes an unfixed server exposed (high).UsePAM yesat start counts only for PAM builds; disagreeing or test-mode (sshd -t) command lines are not applied. The engine passes the image's Entrypoint and Cmd (TargetContext.Command).ARG/ENVpackage lists (fixed where the value is written; unset variables are notes), Ansible apk tasks (fix:state: latest), Buildroot, OpenWrt and Yocto musl builds (manual steps with the fixed release or the patch), andalpine:3.Nend-of-life bases moved to 3.16 as a labelled upgrade.sshd -oin the image command.Added in the second gap round
scan repopulls the images a tree references (guarded transport, at most 20) and judges them with the command a Compose service (entrypoint,command) or Kubernetes container (command,args) sets.fix: an Alpine-suffixed end-of-life base (python:3.9-alpine3.14) moves to the same tag on the nearest fixed Alpine release once that image is confirmed to be that release.fix: Buildroot and Yocto builds get upstream commit 4353fdc43 as a patch scoped to OpenSSH 8.9p1 to 10.6p1 (Buildroot versioned patch directories; a version-specific Yocto bbappend). The patch applies cleanly to every release in that range; patched 8.9p1, 9.9p2 and 10.6p1 build on musl. Fixes can add files.🤖 Generated with Claude Code