TCP SYN Cookies Disabled
Checks that SYN cookies protect the server from SYN flood attacks.
- Why It Matters
- Without SYN cookies a simple flood of half-open connections can make every service unreachable.
- How It Detects
- Reads /proc/sys/net/ipv4/tcp_syncookies directly (no command is run) and compares it with the hardened value 1.
- How to Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.tcp_syncookies = 1 then apply with: sysctl --system
- How to Verify
sysctl net.ipv4.tcp_syncookies should print 1.- CVSS v3.1 Vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L- Control Category
- Secure Configuration: CIS Controls v8 4; NIST CSF 2.0 PR.PS
- Fix Effort
- Low
- CIS Controls v8 Safeguard
- 4.1
- NIST CSF 2.0 Subcategory
- PR.PS-01
- CWE
- CWE-770
- NIST SP 800-53 Rev. 5
- SC-5, CM-6
- Benchmark Topic
- Kernel parameters: net.ipv4.tcp_syncookies (topic only, no benchmark text)
- References
- Linux kernel documentation, IP sysctl
Source Code
The complete file that defines this check. Run it with openvapt scan --only HOST-KRN-008, or read it offline with openvapt explain HOST-KRN-008.
internal/checks/host/kernel.go · Lines 1-362View on GitHub at This Commit
| 1 | package host |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "fmt" |
| 7 | "io/fs" |
| 8 | "sort" |
| 9 | "strings" |
| 10 | |
| 11 | "github.com/openvapt/openvapt/internal/check" |
| 12 | "github.com/openvapt/openvapt/internal/checks/collect" |
| 13 | "github.com/openvapt/openvapt/internal/sys" |
| 14 | ) |
| 15 | |
| 16 | // sysctlRule describes one kernel parameter and its hardened value. |
| 17 | type sysctlRule struct { |
| 18 | id, title, key, want, summary, rationale string |
| 19 | sev check.Severity |
| 20 | cvss string |
| 21 | ref check.Ref |
| 22 | cwe string |
| 23 | allowed []string // values that also pass |
| 24 | } |
| 25 | |
| 26 | // One table, one loop: each row becomes its own registered check, so every |
| 27 | // kernel setting has its own catalogue page, id and result. |
| 28 | var sysctlRules = []sysctlRule{ |
| 29 | {"HOST-KRN-001", "Address Space Layout Randomisation Not Fully Enabled", "kernel.randomize_va_space", "2", |
| 30 | "Checks that the kernel randomises memory layout for stack, libraries, heap and VDSO.", |
| 31 | "ASLR makes memory-corruption exploits much harder because attackers cannot predict where code lives.", |
| 32 | check.Medium, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N", refKernelDocs, "CWE-344", nil}, |
| 33 | {"HOST-KRN-002", "Kernel Pointers Exposed to Unprivileged Users", "kernel.kptr_restrict", "1", |
| 34 | "Checks that kernel memory addresses are hidden from normal users.", |
| 35 | "Leaked kernel addresses defeat kernel ASLR and are the first step of most local kernel exploits.", |
| 36 | check.Low, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", refKernelDocs, "CWE-497", []string{"2"}}, |
| 37 | {"HOST-KRN-003", "Kernel Log Readable by Unprivileged Users", "kernel.dmesg_restrict", "1", |
| 38 | "Checks that only privileged users can read the kernel log (dmesg).", |
| 39 | "The kernel log can reveal addresses, hardware and driver details useful for local exploitation.", |
| 40 | check.Low, "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N", refKernelDocs, "CWE-497", nil}, |
| 41 | {"HOST-KRN-004", "Setuid Programs May Dump Core", "fs.suid_dumpable", "0", |
| 42 | "Checks that privileged programs do not write core dumps.", |
| 43 | "A core dump of a setuid program can contain password hashes or keys and may be readable by the user who crashed it.", |
| 44 | check.Low, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", check.Ref{Title: "Linux kernel documentation, /proc/sys/fs", URL: "https://docs.kernel.org/admin-guide/sysctl/fs.html"}, "CWE-528", nil}, |
| 45 | {"HOST-KRN-005", "IP Forwarding Enabled", "net.ipv4.ip_forward", "0", |
| 46 | "Checks that the server does not route packets between networks.", |
| 47 | "A server that forwards packets can be used to pivot between networks. Only routers, VPN gateways and container hosts need this.", |
| 48 | check.Low, "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N", refKernelNet, "CWE-1188", nil}, |
| 49 | {"HOST-KRN-006", "ICMP Redirects Accepted", "net.ipv4.conf.all.accept_redirects", "0", |
| 50 | "Checks that the kernel ignores ICMP redirect messages.", |
| 51 | "Forged ICMP redirects let an attacker on the local network reroute the server's traffic through themselves.", |
| 52 | check.Low, "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N", refKernelNet, "CWE-940", nil}, |
| 53 | {"HOST-KRN-007", "Source-Routed Packets Accepted", "net.ipv4.conf.all.accept_source_route", "0", |
| 54 | "Checks that the kernel drops packets that dictate their own route.", |
| 55 | "Source routing lets an attacker bypass network filtering and spoof trusted addresses.", |
| 56 | check.Low, "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N", refKernelNet, "CWE-940", nil}, |
| 57 | {"HOST-KRN-008", "TCP SYN Cookies Disabled", "net.ipv4.tcp_syncookies", "1", |
| 58 | "Checks that SYN cookies protect the server from SYN flood attacks.", |
| 59 | "Without SYN cookies a simple flood of half-open connections can make every service unreachable.", |
| 60 | check.Low, "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L", refKernelNet, "CWE-770", nil}, |
| 61 | {"HOST-KRN-009", "Unprivileged eBPF Allowed", "kernel.unprivileged_bpf_disabled", "1", |
| 62 | "Checks that normal users cannot load eBPF programs into the kernel.", |
| 63 | "Unprivileged eBPF has been the entry point for many local privilege-escalation bugs.", |
| 64 | check.Medium, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L", refKernelDocs, "CWE-749", []string{"2"}}, |
| 65 | {"HOST-KRN-010", "Process Tracing Not Restricted", "kernel.yama.ptrace_scope", "1", |
| 66 | "Checks that processes cannot attach a debugger to other processes of the same user.", |
| 67 | "Unrestricted ptrace lets any compromised process read the memory of others, for example to steal SSH agent keys or browser sessions.", |
| 68 | check.Low, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", check.Ref{Title: "Linux kernel documentation, Yama LSM", URL: "https://docs.kernel.org/admin-guide/LSM/Yama.html"}, "CWE-749", []string{"2", "3"}}, |
| 69 | {"HOST-KRN-011", "Symlink Protection Disabled", "fs.protected_symlinks", "1", |
| 70 | "Checks that the kernel blocks following symlinks owned by other users in world-writable sticky directories.", |
| 71 | "Without it, classic /tmp symlink races let local users trick root-run programs into overwriting files.", |
| 72 | check.Low, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", check.Ref{Title: "Linux kernel documentation, /proc/sys/fs", URL: "https://docs.kernel.org/admin-guide/sysctl/fs.html"}, "CWE-59", nil}, |
| 73 | {"HOST-KRN-012", "Hardlink Protection Disabled", "fs.protected_hardlinks", "1", |
| 74 | "Checks that users cannot create hard links to files they do not own.", |
| 75 | "Hard links to privileged files enable time-of-check races and keep vulnerable setuid binaries alive after updates.", |
| 76 | check.Low, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", check.Ref{Title: "Linux kernel documentation, /proc/sys/fs", URL: "https://docs.kernel.org/admin-guide/sysctl/fs.html"}, "CWE-59", nil}, |
| 77 | {"HOST-KRN-013", "Reverse Path Filtering Disabled", "net.ipv4.conf.all.rp_filter", "1", |
| 78 | "Checks that the kernel drops packets whose source address could not be routed back through the receiving interface.", |
| 79 | "Reverse path filtering blocks many spoofed-source packets used in attacks and amplification.", |
| 80 | check.Low, "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N", refKernelNet, "CWE-940", []string{"2"}}, |
| 81 | {"HOST-KRN-014", "Martian Packets Not Logged", "net.ipv4.conf.all.log_martians", "1", |
| 82 | "Checks that packets with impossible source addresses are logged.", |
| 83 | "Logging martian packets helps detect spoofing and misrouting attempts.", |
| 84 | check.Low, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N", refKernelNet, "CWE-778", nil}, |
| 85 | {"HOST-KRN-015", "Server Sends ICMP Redirects", "net.ipv4.conf.all.send_redirects", "0", |
| 86 | "Checks that the server does not send ICMP redirects, which only routers should do.", |
| 87 | "A non-router sending redirects can be abused to influence other hosts' routing on the local network.", |
| 88 | check.Low, "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N", refKernelNet, "CWE-1188", nil}, |
| 89 | {"HOST-KRN-016", "Broadcast ICMP Echo Answered", "net.ipv4.icmp_echo_ignore_broadcasts", "1", |
| 90 | "Checks that the server ignores ping requests sent to broadcast addresses.", |
| 91 | "Answering broadcast pings makes the server a participant in Smurf-style amplification attacks.", |
| 92 | check.Low, "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L", refKernelNet, "CWE-406", nil}, |
| 93 | {"HOST-KRN-017", "IPv6 ICMP Redirects Accepted", "net.ipv6.conf.all.accept_redirects", "0", |
| 94 | "Checks that the kernel ignores IPv6 ICMP redirect messages.", |
| 95 | "Forged IPv6 redirects let an attacker on the local network reroute traffic through themselves.", |
| 96 | check.Low, "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N", refKernelNet, "CWE-940", nil}, |
| 97 | {"HOST-KRN-018", "Performance Events Open to Unprivileged Users", "kernel.perf_event_paranoid", "2", |
| 98 | "Checks that unprivileged users cannot use kernel performance events to observe the system.", |
| 99 | "Unrestricted perf events expose kernel and other processes' activity and have been used in local exploits.", |
| 100 | check.Low, "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", refKernelDocs, "CWE-749", []string{"3", "4"}}, |
| 101 | } |
| 102 | |
| 103 | func init() { |
| 104 | for _, r := range sysctlRules { |
| 105 | registerSysctl(r) |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | // registerSysctl turns one kernel parameter rule into a registered check. |
| 110 | // kernel_depth.go registers its own table through the same function. |
| 111 | func registerSysctl(r sysctlRule) { |
| 112 | { |
| 113 | ok := append([]string{r.want}, r.allowed...) |
| 114 | check.Register(&check.Check{ |
| 115 | ID: r.id, Title: r.title, Domain: check.DomainHost, Severity: r.sev, CVSS: r.cvss, |
| 116 | Summary: r.summary, |
| 117 | Rationale: r.rationale, |
| 118 | Detection: sysctlDetection(r), |
| 119 | Fix: "Create /etc/sysctl.d/60-openvapt-hardening.conf containing: " + r.key + " = " + r.want + " then apply with: sysctl --system" + sysctlFixCaution[r.id], |
| 120 | Verify: "sysctl " + r.key + " should print " + r.want + ".", |
| 121 | Refs: []check.Ref{r.ref}, |
| 122 | Standards: check.Standards{CWE: []string{r.cwe}, NIST: sysctlNIST(r.id, r.key), CISTopic: "Kernel parameters: " + r.key}, |
| 123 | Run: func(ctx context.Context, s sys.System) []check.Result { |
| 124 | res := runSysctlRule(ctx, s, r, ok) |
| 125 | if note := sysctlPassNote[r.id]; note != nil && hasFail(res) { |
| 126 | if msg, ev, pass := note(ctx, s); pass { |
| 127 | return []check.Result{check.PassR(r.key, msg, append(failEvidence(res), ev...)...)} |
| 128 | } |
| 129 | } |
| 130 | return res |
| 131 | }, |
| 132 | }) |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | // runSysctlRule evaluates one kernel parameter rule. |
| 137 | func runSysctlRule(ctx context.Context, s sys.System, r sysctlRule, ok []string) []check.Result { |
| 138 | if combinedSysctl[r.id] != nil { |
| 139 | return runCombinedSysctl(s, r.id, r.key, r.want) |
| 140 | } |
| 141 | if perInterfaceSysctl[r.id] { |
| 142 | return runPerInterfaceSysctl(s, r.key, r.want, ok) |
| 143 | } |
| 144 | v, err := collect.Sysctl(s, r.key) |
| 145 | if err != nil { |
| 146 | return []check.Result{check.SkipR(r.key, "Parameter not available on this kernel")} |
| 147 | } |
| 148 | for _, good := range ok { |
| 149 | if v == good { |
| 150 | return []check.Result{check.PassR(r.key, r.key+" = "+v)} |
| 151 | } |
| 152 | } |
| 153 | if r.id == "HOST-KRN-005" { |
| 154 | return []check.Result{runIPForward(ctx, s, r.key, v)} |
| 155 | } |
| 156 | return []check.Result{check.FailR(r.key, r.key+" = "+v+" (hardened value: "+r.want+")")} |
| 157 | } |
| 158 | |
| 159 | func slash(k string) string { |
| 160 | b := []byte(k) |
| 161 | for i := range b { |
| 162 | if b[i] == '.' { |
| 163 | b[i] = '/' |
| 164 | } |
| 165 | } |
| 166 | return string(b) |
| 167 | } |
| 168 | |
| 169 | // perInterfaceSysctl lists the rules whose kernel parameter also exists per |
| 170 | // network interface. The kernel combines "all" with each interface value, so |
| 171 | // every one of all, default and each interface must hold the hardened value. |
| 172 | var perInterfaceSysctl = map[string]bool{"HOST-KRN-006": true, "HOST-KRN-015": true, "HOST-KRN-017": true, "HOST-KRN-023": true, "HOST-KRN-024": true, "HOST-KRN-025": true} |
| 173 | |
| 174 | // combinedSysctl lists IPv4 rules where the kernel combines the "all" value |
| 175 | // with each interface value in a rule-specific way (include/linux/inetdevice.h): |
| 176 | // rp_filter uses the larger of the two, log_martians is on when either is on, |
| 177 | // and accept_redirects needs both on when the interface forwards packets but |
| 178 | // either one otherwise. good reports whether the combined result is hardened. |
| 179 | var combinedSysctl = map[string]func(all, iface int, forwarding bool) bool{ |
| 180 | "HOST-KRN-006": func(all, iface int, fwd bool) bool { |
| 181 | if fwd { |
| 182 | return all == 0 || iface == 0 |
| 183 | } |
| 184 | return all == 0 && iface == 0 |
| 185 | }, |
| 186 | "HOST-KRN-013": func(all, iface int, _ bool) bool { m := max(all, iface); return m == 1 || m == 2 }, |
| 187 | "HOST-KRN-014": func(all, iface int, _ bool) bool { return all == 1 || iface == 1 }, |
| 188 | } |
| 189 | |
| 190 | var combinedDetection = map[string]string{ |
| 191 | "HOST-KRN-006": "The kernel ignores redirects on an interface when both values are 0 or, on an interface that forwards packets (net.ipv4.ip_forward or the interface's forwarding setting), when either one is 0; any interface where redirects remain accepted fails.", |
| 192 | "HOST-KRN-013": "The kernel uses the larger of the two values, so an interface passes when that larger value is 1 (strict) or 2 (loose).", |
| 193 | "HOST-KRN-014": "The kernel logs martians on an interface when either value is 1, so an interface passes when all or the interface value is 1.", |
| 194 | } |
| 195 | |
| 196 | func sysctlDetection(r sysctlRule) string { |
| 197 | return sysctlDetectionBase(r) + sysctlDetectionNote[r.id] |
| 198 | } |
| 199 | |
| 200 | func sysctlDetectionBase(r sysctlRule) string { |
| 201 | if r.id == "HOST-KRN-005" { |
| 202 | return "Reads /proc/sys/net/ipv4/ip_forward directly and compares it with the hardened value 0. When a container runtime or Kubernetes node is detected read-only (runtime sockets such as /var/run/docker.sock, /run/containerd/containerd.sock or /run/crio/crio.sock, /etc/kubernetes, or bridge interfaces such as docker0, cni0, cbr0 or flannel.1 in /sys/class/net), forwarding is required: the check then passes with context when the FORWARD path is filtered (iptables or nftables forward policy drop, or DROP/REJECT rules in DOCKER-USER), fails when forwarded traffic is accepted by default, and is incomplete when the policy cannot be read." |
| 203 | } |
| 204 | if d, ok := combinedDetection[r.id]; ok { |
| 205 | g := strings.Replace(slash(r.key), "/all/", "/*/", 1) |
| 206 | return "Reads /proc/sys/" + g + " directly (all, default for future interfaces, and every interface except loopback; no command is run) and combines the all value with each interface value as the kernel does. " + d |
| 207 | } |
| 208 | if perInterfaceSysctl[r.id] { |
| 209 | g := strings.Replace(slash(r.key), "/all/", "/*/", 1) |
| 210 | return "Reads /proc/sys/" + g + " directly (all, default and every interface; no command is run) and fails if any of them differs from the hardened value " + r.want + "." |
| 211 | } |
| 212 | return "Reads /proc/sys/" + slash(r.key) + " directly (no command is run) and compares it with the hardened value " + r.want + "." |
| 213 | } |
| 214 | |
| 215 | // sysctlNIST maps a kernel rule to NIST SP 800-53 Rev. 5 controls: SI-16 for |
| 216 | // memory protection, SC-7 for network boundary settings, SC-5 for denial of |
| 217 | // service protection and AC-6 for least privilege on local information. |
| 218 | func sysctlNIST(id, key string) []string { |
| 219 | switch id { |
| 220 | case "HOST-KRN-001", "HOST-KRN-002", "HOST-KRN-009", "HOST-KRN-018": |
| 221 | return []string{"CM-6", "SI-16"} |
| 222 | case "HOST-KRN-008", "HOST-KRN-016": |
| 223 | return []string{"SC-5", "CM-6"} |
| 224 | } |
| 225 | if strings.HasPrefix(key, "net.") { |
| 226 | return []string{"SC-7", "CM-6"} |
| 227 | } |
| 228 | return []string{"AC-6", "CM-6"} |
| 229 | } |
| 230 | |
| 231 | // runPerInterfaceSysctl evaluates a ".conf.all." parameter together with its |
| 232 | // "default" and per-interface siblings. |
| 233 | func runPerInterfaceSysctl(s sys.System, key, want string, ok []string) []check.Result { |
| 234 | base := "/proc/sys/" + slash(key) |
| 235 | pat := strings.Replace(base, "/all/", "/*/", 1) |
| 236 | paths, _ := s.Glob(pat) |
| 237 | seen := map[string]bool{} |
| 238 | for _, p := range paths { |
| 239 | seen[p] = true |
| 240 | } |
| 241 | for _, p := range []string{base, strings.Replace(base, "/all/", "/default/", 1)} { |
| 242 | if !seen[p] { |
| 243 | paths = append(paths, p) |
| 244 | seen[p] = true |
| 245 | } |
| 246 | } |
| 247 | sort.Strings(paths) |
| 248 | var bad []string |
| 249 | read, unreadable := 0, 0 |
| 250 | for _, p := range paths { |
| 251 | // Read the path directly: interface names may contain dots |
| 252 | // (VLANs such as eth0.100), which a dotted sysctl key cannot express. |
| 253 | k := strings.TrimPrefix(p, "/proc/sys/") |
| 254 | rr, err := s.ReadFile(context.Background(), p) |
| 255 | if err != nil || !rr.Complete { |
| 256 | if !errors.Is(err, fs.ErrNotExist) { |
| 257 | unreadable++ |
| 258 | } |
| 259 | continue |
| 260 | } |
| 261 | v := strings.TrimSpace(string(rr.Data)) |
| 262 | read++ |
| 263 | good := false |
| 264 | for _, g := range ok { |
| 265 | if v == g { |
| 266 | good = true |
| 267 | break |
| 268 | } |
| 269 | } |
| 270 | if !good { |
| 271 | bad = append(bad, k+" = "+v) |
| 272 | } |
| 273 | } |
| 274 | if read == 0 { |
| 275 | return []check.Result{check.SkipR(key, "Parameter not available on this kernel")} |
| 276 | } |
| 277 | if len(bad) > 0 { |
| 278 | return []check.Result{check.FailR(key, fmt.Sprintf("%d of %d setting(s) differ from the hardened value %s", len(bad), read, want), bad...)} |
| 279 | } |
| 280 | if unreadable > 0 { |
| 281 | return []check.Result{check.IncompleteR(key, fmt.Sprintf("%d setting(s) could not be read; the readable ones hold the hardened value", unreadable))} |
| 282 | } |
| 283 | return []check.Result{check.PassR(key, fmt.Sprintf("%s = %s for all, default and every interface (%d settings)", key, want, read))} |
| 284 | } |
| 285 | |
| 286 | // runCombinedSysctl evaluates an IPv4 ".conf.all." parameter the way the |
| 287 | // kernel applies it: the all value combined with each interface value (and |
| 288 | // with default, which new interfaces inherit). Loopback is skipped: these |
| 289 | // settings concern packets arriving from a network. |
| 290 | func runCombinedSysctl(s sys.System, id, key, want string) []check.Result { |
| 291 | good := combinedSysctl[id] |
| 292 | base := "/proc/sys/" + slash(key) |
| 293 | name := base[strings.LastIndex(base, "/")+1:] |
| 294 | read := func(p string) (int, bool, bool) { // value, ok, unreadable |
| 295 | rr, err := s.ReadFile(context.Background(), p) |
| 296 | if err != nil || !rr.Complete { |
| 297 | return 0, false, !errors.Is(err, fs.ErrNotExist) |
| 298 | } |
| 299 | var n int |
| 300 | if _, err := fmt.Sscan(strings.TrimSpace(string(rr.Data)), &n); err != nil { |
| 301 | return 0, false, true |
| 302 | } |
| 303 | return n, true, false |
| 304 | } |
| 305 | all, ok, _ := read(base) |
| 306 | if !ok { |
| 307 | return []check.Result{check.SkipR(key, "Parameter not available on this kernel")} |
| 308 | } |
| 309 | ipFwd, _, _ := read("/proc/sys/net/ipv4/ip_forward") |
| 310 | paths, _ := s.Glob(strings.Replace(base, "/all/", "/*/", 1)) |
| 311 | def := strings.Replace(base, "/all/", "/default/", 1) |
| 312 | seen := map[string]bool{base: true} |
| 313 | ifaces := []string{} |
| 314 | for _, p := range append(paths, def) { |
| 315 | dir := strings.TrimSuffix(p, "/"+name) |
| 316 | ifn := dir[strings.LastIndex(dir, "/")+1:] |
| 317 | if seen[p] || ifn == "lo" { |
| 318 | continue |
| 319 | } |
| 320 | seen[p] = true |
| 321 | ifaces = append(ifaces, p) |
| 322 | } |
| 323 | sort.Strings(ifaces) |
| 324 | var bad []string |
| 325 | checked, unreadable := 0, 0 |
| 326 | for _, p := range ifaces { |
| 327 | v, ok, unr := read(p) |
| 328 | if !ok { |
| 329 | if unr { |
| 330 | unreadable++ |
| 331 | } |
| 332 | continue |
| 333 | } |
| 334 | checked++ |
| 335 | dir := strings.TrimSuffix(p, "/"+name) |
| 336 | fwd := ipFwd == 1 |
| 337 | if f, ok, _ := read(dir + "/forwarding"); ok && f == 1 { |
| 338 | fwd = true |
| 339 | } |
| 340 | if !good(all, v, fwd) { |
| 341 | note := fmt.Sprintf(" (all = %d", all) |
| 342 | if id == "HOST-KRN-006" && fwd { |
| 343 | note += ", interface forwards packets" |
| 344 | } |
| 345 | bad = append(bad, strings.TrimPrefix(p, "/proc/sys/")+fmt.Sprintf(" = %d", v)+note+")") |
| 346 | } |
| 347 | } |
| 348 | if checked == 0 && unreadable == 0 { |
| 349 | // No interface or default value is visible: judge all by itself. |
| 350 | if !good(all, all, ipFwd == 1) { |
| 351 | return []check.Result{check.FailR(key, fmt.Sprintf("%s = %d (hardened value: %s)", key, all, want))} |
| 352 | } |
| 353 | return []check.Result{check.PassR(key, fmt.Sprintf("%s = %d", key, all))} |
| 354 | } |
| 355 | if len(bad) > 0 { |
| 356 | return []check.Result{check.FailR(key, fmt.Sprintf("%d interface setting(s) are not hardened once combined with all (hardened value: %s)", len(bad), want), bad...)} |
| 357 | } |
| 358 | if unreadable > 0 { |
| 359 | return []check.Result{check.IncompleteR(key, fmt.Sprintf("%d setting(s) could not be read; the readable ones are hardened", unreadable))} |
| 360 | } |
| 361 | return []check.Result{check.PassR(key, fmt.Sprintf("%s = %d; hardened on every interface once combined (%d checked)", key, all, checked))} |
| 362 | } |
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.
OpenVAPT. (2026). HOST-KRN-008 TCP SYN Cookies Disabled (Version 0.1.0-alpha.6). OpenVAPT Check Catalogue. Retrieved October 16, 2026, from https://openvapt.com/checks/HOST-KRN-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.
@misc{openvapt_host_krn_008,
author = {{OpenVAPT}},
title = {{HOST-KRN-008 TCP SYN Cookies Disabled}},
year = {2026},
howpublished = {\url{https://openvapt.com/checks/HOST-KRN-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.