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
LowHOST-SSH-008Identity and AuthenticationServer

SSH Authentication Controls Too Permissive

Checks effective SSH authentication method and login grace settings.

Why It Matters
Long login windows and unconstrained single-factor authentication give online guessing and stolen credentials more opportunity.
How It Detects
Evaluates applicable Match contexts and flags LoginGraceTime over 60 seconds, or password or keyboard-interactive login enabled without an AuthenticationMethods list that requires a second method.
How to Fix
Set LoginGraceTime 60 or lower and choose AuthenticationMethods appropriate to the server, such as publickey, then restrict access with AllowUsers or AllowGroups where practical.
How to Verify
Use sshd -T -C for each allowed user and source context and inspect logingracetime, authenticationmethods, allowusers and allowgroups.
CVSS v3.1 Vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/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-308
NIST SP 800-53 Rev. 5
AC-7, IA-2
Benchmark Topic
SSH server configuration: authentication restrictions (topic only, no benchmark text)
References
OpenBSD, sshd_config(5) manual page
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-008, or read it offline with openvapt explain HOST-SSH-008.

internal/checks/host/ssh_forwarding.go · Lines 1-121View on GitHub at This Commit
1package host
2
3import (
4 "context"
5 "strconv"
6 "strings"
7
8 "github.com/openvapt/openvapt/internal/check"
9 "github.com/openvapt/openvapt/internal/checks/collect"
10 "github.com/openvapt/openvapt/internal/sys"
11)
12
13func init() {
14 check.Register(&check.Check{
15 ID: "HOST-SSH-007", Title: "SSH Forwarding Features Enabled", Domain: check.DomainHost, Severity: check.Medium,
16 CVSS: "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N",
17 Summary: "Checks effective SSH Match contexts for TCP, agent, tunnel and gateway forwarding.",
18 Rationale: "Forwarding can turn an SSH account into a route to protected services or expose a user's authentication agent.",
19 Detection: "Evaluates sshd -T for root and an unprivileged user from loopback and a representative remote address. Fails when TCP or agent forwarding is enabled (both default to yes), PermitTunnel is yes, point-to-point or ethernet, or GatewayPorts is yes or clientspecified (the defaults for the last two are no). A risky value set inside a Match block in the config files fails as a conditional finding, with the Match condition in the evidence.",
20 Fix: "Set AllowTcpForwarding no, AllowAgentForwarding no, PermitTunnel no and GatewayPorts no globally or in every applicable Match block, then reload sshd.",
21 Verify: "Run sshd -T -C user=nobody,host=localhost,addr=192.0.2.1 and confirm each forwarding option is no.",
22 Refs: []check.Ref{refSSHDManual}, Standards: check.Standards{CWE: []string{"CWE-441"}, NIST: []string{"AC-4", "CM-7"}, CISTopic: "SSH server configuration: forwarding"},
23 Run: func(ctx context.Context, s sys.System) []check.Result {
24 cfg, ok := collect.SSHD(ctx, s)
25 if !ok {
26 return []check.Result{check.SkipR("sshd", "SSH daemon configuration not found")}
27 }
28 // OpenSSH defaults: AllowTcpForwarding yes, AllowAgentForwarding
29 // yes, PermitTunnel no, GatewayPorts no.
30 bad := sshForwardingIssues(cfg)
31 if len(bad) > 0 {
32 return []check.Result{check.FailR("sshd", "SSH forwarding is enabled in at least one evaluated context", bad...)}
33 }
34 if r, bad := sshMatchFail(cfg, "SSH forwarding is enabled", "allowtcpforwarding", "allowagentforwarding", "permittunnel", "gatewayports", "x11forwarding"); bad {
35 return []check.Result{r}
36 }
37 return []check.Result{check.PassR("sshd", "SSH forwarding is disabled in all evaluated contexts")}
38 },
39 })
40 check.Register(&check.Check{
41 ID: "HOST-SSH-008", Title: "SSH Authentication Controls Too Permissive", Domain: check.DomainHost, Severity: check.Low,
42 CVSS: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
43 Summary: "Checks effective SSH authentication method and login grace settings.",
44 Rationale: "Long login windows and unconstrained single-factor authentication give online guessing and stolen credentials more opportunity.",
45 Detection: "Evaluates applicable Match contexts and flags LoginGraceTime over 60 seconds, or password or keyboard-interactive login enabled without an AuthenticationMethods list that requires a second method.",
46 Fix: "Set LoginGraceTime 60 or lower and choose AuthenticationMethods appropriate to the server, such as publickey, then restrict access with AllowUsers or AllowGroups where practical.",
47 Verify: "Use sshd -T -C for each allowed user and source context and inspect logingracetime, authenticationmethods, allowusers and allowgroups.",
48 Refs: []check.Ref{refSSHDManual}, Standards: check.Standards{CWE: []string{"CWE-307", "CWE-308"}, NIST: []string{"AC-7", "IA-2"}, CISTopic: "SSH server configuration: authentication restrictions"},
49 Run: func(ctx context.Context, s sys.System) []check.Result {
50 cfg, ok := collect.SSHD(ctx, s)
51 if !ok {
52 return []check.Result{check.SkipR("sshd", "SSH daemon configuration not found")}
53 }
54 grace := 120
55 if v := strings.TrimSuffix(cfg["logingracetime"], "s"); v != "" {
56 if n, err := strconv.Atoi(v); err == nil {
57 grace = n
58 }
59 }
60 var bad []string
61 if grace > 60 {
62 bad = append(bad, "logingracetime "+strconv.Itoa(grace))
63 }
64 if sshPasswordLike(cfg) && !sshMultiFactor(cfg["authenticationmethods"]) {
65 bad = append(bad, "password or keyboard-interactive login enabled without a second factor (authenticationmethods "+orDefault(cfg["authenticationmethods"])+")")
66 }
67 if len(bad) > 0 {
68 return []check.Result{check.FailR("sshd", "SSH authentication restrictions are too permissive", bad...)}
69 }
70 return []check.Result{check.PassR("sshd", "SSH authentication restrictions are configured")}
71 },
72 })
73}
74
75// sshForwardingIssues lists forwarding settings that are enabled, applying
76// OpenSSH defaults for unset keywords.
77func sshForwardingIssues(cfg map[string]string) []string {
78 var bad []string
79 for _, k := range []string{"allowtcpforwarding", "allowagentforwarding"} {
80 switch v := cfg[k]; v {
81 case "":
82 bad = append(bad, k+" default yes")
83 case "yes", "all", "local", "remote":
84 bad = append(bad, k+" "+v)
85 }
86 }
87 switch v := cfg["permittunnel"]; v {
88 case "yes", "point-to-point", "ethernet":
89 bad = append(bad, "permittunnel "+v)
90 }
91 switch v := cfg["gatewayports"]; v {
92 case "yes", "clientspecified":
93 bad = append(bad, "gatewayports "+v)
94 }
95 return bad
96}
97
98// sshPasswordLike reports whether password or keyboard-interactive
99// authentication is enabled (PasswordAuthentication defaults to yes).
100func sshPasswordLike(cfg map[string]string) bool {
101 kbd := cfg["kbdinteractiveauthentication"]
102 if kbd == "" {
103 kbd = cfg["challengeresponseauthentication"]
104 }
105 pw := cfg["passwordauthentication"]
106 return pw == "" || pw == "yes" || kbd == "yes"
107}
108
109// sshMultiFactor reports whether every AuthenticationMethods list requires at
110// least two methods, for example "publickey,keyboard-interactive".
111func sshMultiFactor(methods string) bool {
112 if methods == "" || methods == "any" {
113 return false
114 }
115 for _, list := range strings.Fields(methods) {
116 if !strings.Contains(list, ",") {
117 return false
118 }
119 }
120 return true
121}

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-008 SSH Authentication Controls Too Permissive (Version 0.1.0-alpha.6). OpenVAPT Check Catalogue. Retrieved October 16, 2026, from https://openvapt.com/checks/HOST-SSH-008.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_008,
  author       = {{OpenVAPT}},
  title        = {{HOST-SSH-008 SSH Authentication Controls Too Permissive}},
  year         = {2026},
  howpublished = {\url{https://openvapt.com/checks/HOST-SSH-008.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.