Initial commit
This commit is contained in:
commit
06036c89d9
29 changed files with 4891 additions and 0 deletions
157
README.md
Normal file
157
README.md
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# checker-ssh
|
||||
|
||||
Deep SSH security checker for [happyDomain](https://www.happydomain.org/).
|
||||
|
||||
Given an `abstract.Server` service (A / AAAA / SSHFP records), the checker
|
||||
connects to the advertised SSH port(s) and produces a comprehensive
|
||||
audit: reachability, banner-to-CVE matches, full algorithm posture
|
||||
(KEX / host-key / cipher / MAC / compression), observed host keys,
|
||||
SSHFP fingerprint validation, and authentication method exposure.
|
||||
|
||||
## What it checks
|
||||
|
||||
### Reachability
|
||||
- TCP connect to port 22 (and optionally extra ports) on every A/AAAA
|
||||
address of the service.
|
||||
- SSH-2.0 protocol banner read.
|
||||
|
||||
### Banner / CVE
|
||||
The banner is parsed into an `OpenSSH_X.Ypz` tuple and matched against
|
||||
a bundled subset of the [ssh-audit](https://github.com/jtesta/ssh-audit)
|
||||
vulnerability database, including:
|
||||
|
||||
| CVE | Issue |
|
||||
| --- | --- |
|
||||
| CVE-2024-6387 | regreSSHion - unauth RCE as root (8.5p1 <= v < 9.8p1) |
|
||||
| CVE-2023-38408 | ssh-agent PKCS#11 RCE (5.5 ≤ v < 9.3p2) |
|
||||
| CVE-2023-48795 | Terrapin prefix-truncation (v < 9.6p1) |
|
||||
| CVE-2021-41617 | AuthorizedKeysCommand privdrop (6.2 ≤ v < 8.8p1) |
|
||||
| CVE-2020-15778 | scp command injection (v < 8.4p1) |
|
||||
| CVE-2018-15473 | username enumeration (v < 7.8p1) |
|
||||
|
||||
### Algorithm posture
|
||||
A raw `SSH_MSG_KEXINIT` is exchanged with the server to enumerate every
|
||||
algorithm it advertises. Each entry is graded against a curated table
|
||||
inspired by ssh-audit:
|
||||
|
||||
- **crit**: `diffie-hellman-group1-sha1` (Logjam), `3des-cbc` (Sweet32),
|
||||
`arcfour*`, `hmac-md5*`, `hmac-sha1-96`, `ssh-dss`, `none`.
|
||||
- **warn**: `ssh-rsa` (RFC 8332 deprecated), `diffie-hellman-group14-sha1`,
|
||||
AES-CBC, non-ETM MACs, `hmac-sha1`, missing strict-KEX marker
|
||||
(CVE-2023-48795 mitigation).
|
||||
- **ok**: `curve25519-sha256`, `sntrup761x25519-sha512@openssh.com`,
|
||||
`mlkem768x25519-sha256`, `ssh-ed25519`, AES-GCM/ChaCha20-Poly1305,
|
||||
SHA-2 ETM MACs.
|
||||
|
||||
### SSHFP validation
|
||||
For each observed host key, the checker:
|
||||
|
||||
- computes SHA-1 and SHA-256 fingerprints,
|
||||
- matches them against the `abstract.Server.SSHFP` records declared in
|
||||
the zone,
|
||||
- flags `sshfp_missing`, `sshfp_not_covered`, `sshfp_only_sha1` or
|
||||
`sshfp_mismatch` as appropriate, with copy-pasteable fix snippets.
|
||||
|
||||
### Authentication methods
|
||||
A second connection is opened with a dummy user and no credentials. The
|
||||
server replies with the auth-method list, which is surfaced as
|
||||
`password`, `publickey`, `keyboard-interactive` chips. Password
|
||||
authentication triggers a `password_auth_enabled` warning.
|
||||
|
||||
## HTML report
|
||||
|
||||
The iframe report is structured for "fix me fast":
|
||||
|
||||
1. **Overall status** banner + SSHFP verdict chips.
|
||||
2. **What to fix**: top issues (crit -> warn), each with a
|
||||
copy-pasteable remediation snippet (sshd_config lines, SSHFP DNS
|
||||
records, ssh-keygen invocations).
|
||||
3. **SSHFP table** with per-record match status.
|
||||
4. **Per-endpoint details**: expandable sections with host-key
|
||||
fingerprints, algorithm tables (broken entries highlighted), and
|
||||
advertised auth methods.
|
||||
|
||||
## Usage
|
||||
|
||||
### Standalone HTTP server
|
||||
```bash
|
||||
make
|
||||
./checker-ssh -listen :8080
|
||||
```
|
||||
Endpoints:
|
||||
- `GET /health`
|
||||
- `GET /definition`
|
||||
- `POST /collect`
|
||||
- `POST /evaluate`
|
||||
- `POST /report`
|
||||
|
||||
### Docker
|
||||
```bash
|
||||
make docker
|
||||
docker run -p 8080:8080 happydomain/checker-ssh
|
||||
```
|
||||
|
||||
### happyDomain plugin
|
||||
```bash
|
||||
make plugin
|
||||
# produces checker-ssh.so, loadable as a Go plugin
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `ports` | string | `""` | Comma-separated extra ports (port 22 is always probed). |
|
||||
| `probeTimeoutMs` | number | `10000` | Per-endpoint dial + handshake timeout. |
|
||||
| `includeAuthProbe` | bool | `true` | Open a second connection to enumerate auth methods. |
|
||||
|
||||
## Observation key
|
||||
|
||||
Writes a single observation under `ssh`:
|
||||
```json
|
||||
{
|
||||
"domain": "...",
|
||||
"endpoints": [
|
||||
{
|
||||
"host": "...", "port": 22, "address": "...",
|
||||
"banner": "SSH-2.0-OpenSSH_9.3p1",
|
||||
"kex_algorithms": ["curve25519-sha256", "..."],
|
||||
"host_keys": [{"type": "ssh-ed25519", "sha256": "abc..."}],
|
||||
"auth_methods": ["publickey"],
|
||||
"issues": [ { "code": "...", "severity": "warn", ... } ]
|
||||
}
|
||||
],
|
||||
"sshfp": { "present": true, "records": [...] },
|
||||
"collected_at": "..."
|
||||
}
|
||||
```
|
||||
|
||||
## License & licensing roadmap
|
||||
|
||||
This project is currently licensed under the **GNU Affero General Public
|
||||
License v3.0** (see `LICENSE`), because it still imports
|
||||
`happydns.ServiceMessage` and `abstract.Server` from the happyDomain
|
||||
server module (`git.happydns.org/happyDomain/model` and
|
||||
`git.happydns.org/happyDomain/services/abstract`), which are themselves
|
||||
distributed under AGPL-3.0 and a commercial license.
|
||||
|
||||
The core checker types (`CheckerOptions`, `CheckerDefinition`,
|
||||
`ObservationProvider`, `CheckRule`, …) have already been migrated to
|
||||
[`checker-sdk-go`](https://git.happydns.org/checker-sdk-go); only the
|
||||
service-message types remain on the AGPL side.
|
||||
|
||||
**Planned relicensing:** as soon as the remaining `ServiceMessage` /
|
||||
`abstract.Server` dependency has been removed (moved into a dedicated
|
||||
permissively licensed module), this project will be relicensed under the
|
||||
**MIT License**, in line with the rest of the happyDomain checker
|
||||
ecosystem (see `checker-dummy` for the target shape).
|
||||
|
||||
**Contributors notice:** by submitting a contribution to this repository,
|
||||
you accept that your contribution will be relicensed from AGPL-3.0 to MIT
|
||||
at the time of the relicensing described above. If you do not agree with
|
||||
this, please do not submit contributions until the relicensing has taken
|
||||
place.
|
||||
|
||||
The third-party Apache-2.0 attributions for `checker-sdk-go` are recorded
|
||||
in `NOTICE` and must accompany any binary or source redistribution of this
|
||||
project.
|
||||
Loading…
Add table
Add a link
Reference in a new issue