Skip to Content
OpenVAPTAlpha
Pre-release. Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. Free for your own use, 100% at your own risk. This website collects no data. Read MoreRead Less
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
Pre-release. OpenVAPT has no Stable release yet. Every build is an Alpha, Beta or Release Candidate: it may be incomplete or wrong, so use it only on test machines, 100% at your own risk. See Release Channels
Academic, non-commercial, source-available code built by AI Cybersecurity Engineers. These are AI systems, not people or registered engineers. Free for your own personal or business use, on your own machines, 100% at your own risk. Not for sale. Not for providing services. This website collects no data. Read the Acknowledgements
MediumHOST-SSH-002Identity and AuthenticationServer

SSH Password Authentication Enabled

Checks whether SSH accepts passwords instead of only keys.

Why It Matters
Internet-facing SSH receives constant automated password guessing. Public-key authentication cannot be guessed, phished as easily, or reused from another breached site.
How It Detects
Reads PasswordAuthentication and KbdInteractiveAuthentication (ChallengeResponseAuthentication on older versions) from the effective sshd configuration. Either set to 'yes' fails. A risky value set inside a Match block in the config files fails as a conditional finding, with the Match condition in the evidence.
How to Fix
Install your public key for each admin user (ssh-copy-id), confirm key login works in a second session, then set PasswordAuthentication no and KbdInteractiveAuthentication no in /etc/ssh/sshd_config and reload sshd.
How to Verify
sshd -T | grep -Ei 'passwordauthentication|kbdinteractive' should show 'no' for both.
CVSS v3.1 Vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N
Control Category
Identity and Authentication: CIS Controls v8 5, 6; NIST CSF 2.0 PR.AA
Fix Effort
Low
CIS Controls v8 Safeguard
4.1
NIST CSF 2.0 Subcategory
PR.PS-01
CWE
CWE-307, CWE-521
NIST SP 800-53 Rev. 5
IA-2(1), IA-5
Benchmark Topic
SSH server configuration: authentication methods (topic only, no benchmark text)
References
OpenBSD, sshd_config(5) manual page
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
Learn the theory behind this check: P2 SSH Security, P15 Access Control: Accounts, Sudo and Logins.

Source Code

The complete file that defines this check. Run it with openvapt scan --only HOST-SSH-002, or read it offline with openvapt explain HOST-SSH-002.

internal/checks/host/ssh_password_auth.go · Lines 1-72View on GitHub at This Commit
1package host
2
3import (
4 "context"
5
6 "github.com/openvapt/openvapt/internal/check"
7 "github.com/openvapt/openvapt/internal/checks/collect"
8 "github.com/openvapt/openvapt/internal/sys"
9)
10
11func init() {
12 check.Register(&check.Check{
13 ID: "HOST-SSH-002",
14 Title: "SSH Password Authentication Enabled",
15 Domain: check.DomainHost,
16 Severity: check.Medium,
17 CVSS: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N",
18 Summary: "Checks whether SSH accepts passwords instead of only keys.",
19 Rationale: "Internet-facing SSH receives constant automated password guessing. Public-key authentication cannot be guessed, phished as easily, or reused from another breached site.",
20 Detection: "Reads PasswordAuthentication and KbdInteractiveAuthentication (ChallengeResponseAuthentication on older versions) from the effective sshd configuration. Either set to 'yes' fails. A risky value set inside a Match block in the config files fails as a conditional finding, with the Match condition in the evidence.",
21 Fix: "Install your public key for each admin user (ssh-copy-id), confirm key login works in a second session, then set PasswordAuthentication no and KbdInteractiveAuthentication no in /etc/ssh/sshd_config and reload sshd.",
22 Verify: "sshd -T | grep -Ei 'passwordauthentication|kbdinteractive' should show 'no' for both.",
23 Refs: []check.Ref{refSSHDManual, refNIST63B},
24 Standards: check.Standards{CWE: []string{"CWE-307", "CWE-521"}, NIST: []string{"IA-2(1)", "IA-5"}, CISTopic: "SSH server configuration: authentication methods"},
25 Run: func(ctx context.Context, s sys.System) []check.Result {
26 cfg, ok := collect.SSHD(ctx, s)
27 if !ok {
28 return []check.Result{check.SkipR("sshd", "SSH daemon configuration not found")}
29 }
30 pw := cfg["passwordauthentication"]
31 kbd := cfg["kbdinteractiveauthentication"]
32 if kbd == "" {
33 kbd = cfg["challengeresponseauthentication"]
34 }
35 if pw == "yes" || pw == "" {
36 return []check.Result{check.FailR("sshd", "Password logins are accepted (PasswordAuthentication defaults to yes)", "passwordauthentication "+orDefault(pw))}
37 }
38 if kbd == "yes" {
39 return []check.Result{check.FailR("sshd", "Keyboard-interactive (password-style) logins are accepted", "kbdinteractiveauthentication yes")}
40 }
41 if r, bad := sshMatchFail(cfg, "Password logins are accepted", "passwordauthentication", "kbdinteractiveauthentication", "challengeresponseauthentication"); bad {
42 return []check.Result{r}
43 }
44 return []check.Result{check.PassR("sshd", "Only key-based SSH authentication is accepted")}
45 },
46 })
47}
48
49func orDefault(v string) string {
50 if v == "" {
51 return "(not set, default applies)"
52 }
53 return v
54}
55
56// sshMatchFail reports settings that are safe globally but turned back on
57// inside a Match block, as a conditional failure whose evidence names the
58// Match condition, for example "Match user deploy: passwordauthentication yes".
59func sshMatchFail(cfg map[string]string, what string, keys ...string) (check.Result, bool) {
60 var ev []string
61 for _, k := range keys {
62 v, ok := cfg["match:"+k]
63 if !ok || !collect.SSHDangerous(k, v) {
64 continue
65 }
66 ev = append(ev, "Match "+cfg["matchcond:"+k]+": "+k+" "+v)
67 }
68 if len(ev) == 0 {
69 return check.Result{}, false
70 }
71 return check.FailR("sshd", what+" for connections matching a Match block (conditional)", ev...), true
72}

Also available as plain Markdown for notes, scripts and AI tools. Same facts, same source, no styling.

Cite This Page

If this page helped your work, please cite it. The version and web address are filled in; the access date is today's date in your browser. Every other style, and when credit is required, is on How to Cite OpenVAPT.

APA 7
OpenVAPT. (2026). HOST-SSH-002 SSH Password Authentication Enabled (Version 0.1.0-alpha.6). OpenVAPT Check Catalogue. Retrieved October 16, 2026, from https://openvapt.com/checks/HOST-SSH-002.html

In text: (OpenVAPT, 2026). Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.

BibTeX
@misc{openvapt_host_ssh_002,
  author       = {{OpenVAPT}},
  title        = {{HOST-SSH-002 SSH Password Authentication Enabled}},
  year         = {2026},
  howpublished = {\url{https://openvapt.com/checks/HOST-SSH-002.html}},
  note         = {OpenVAPT Check Catalogue, version 0.1.0-alpha.6. Accessed 16 October 2026}
}

Accessed: the date shown is today's date from your own browser (the site's build date without JavaScript); change it to the day you read the page.

Citing OpenVAPT does not mean OpenVAPT endorses, approves or has reviewed your work.