Skip to content

Commit 28f1295

Browse files
committed
Merge branch 'cis'
Refers to #199.
2 parents ae44386 + 76821aa commit 28f1295

File tree

1 file changed

+57
-9
lines changed

1 file changed

+57
-9
lines changed

kernel_hardening_checker/checks.py

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@ def add_kconfig_checks(l: List[ChecklistObjType], arch: str) -> None:
6969
vmap_stack_is_set = KconfigCheck('self_protection', 'defconfig', 'VMAP_STACK', 'y')
7070
if arch in ('X86_64', 'ARM64', 'ARM', 'RISCV'):
7171
l += [vmap_stack_is_set]
72+
if arch in ('X86_64', 'X86_32', 'RISCV'):
73+
l += [KconfigCheck('self_protection', 'defconfig', 'LSM_MMAP_MIN_ADDR', '65536')]
7274
if arch in ('X86_64', 'X86_32'):
7375
l += [KconfigCheck('self_protection', 'defconfig', 'DEBUG_WX', 'y')]
7476
l += [KconfigCheck('self_protection', 'defconfig', 'WERROR', 'y')]
7577
l += [KconfigCheck('self_protection', 'defconfig', 'X86_MCE', 'y')]
76-
l += [KconfigCheck('self_protection', 'defconfig', 'SYN_COOKIES', 'y')] # another reason?
7778
microcode_is_set = KconfigCheck('self_protection', 'defconfig', 'MICROCODE', 'y')
7879
l += [microcode_is_set] # is needed for mitigating CPU bugs
7980
l += [OR(KconfigCheck('self_protection', 'defconfig', 'MICROCODE_INTEL', 'y'),
@@ -134,11 +135,15 @@ def add_kconfig_checks(l: List[ChecklistObjType], arch: str) -> None:
134135
VersionCheck((5, 9, 0))))] # HARDEN_EL2_VECTORS was included in RANDOMIZE_BASE in v5.9
135136
l += [OR(KconfigCheck('self_protection', 'defconfig', 'HARDEN_BRANCH_PREDICTOR', 'y'),
136137
VersionCheck((5, 10, 0)))] # HARDEN_BRANCH_PREDICTOR is enabled by default since v5.10
138+
l += [AND(KconfigCheck('self_protection', 'defconfig', 'LSM_MMAP_MIN_ADDR', '65536'),
139+
KconfigCheck('cut_attack_surface', 'kspp', 'COMPAT', 'is not set'))]
140+
# LSM_MMAP_MIN_ADDR for ARM64 requires disabled COMPAT (see security/Kconfig)
137141
if arch == 'ARM':
138142
l += [KconfigCheck('self_protection', 'defconfig', 'CPU_SW_DOMAIN_PAN', 'y')]
139143
l += [KconfigCheck('self_protection', 'defconfig', 'HARDEN_BRANCH_PREDICTOR', 'y')]
140144
l += [KconfigCheck('self_protection', 'defconfig', 'HARDEN_BRANCH_HISTORY', 'y')]
141145
l += [KconfigCheck('self_protection', 'defconfig', 'DEBUG_ALIGN_RODATA', 'y')]
146+
l += [KconfigCheck('self_protection', 'defconfig', 'LSM_MMAP_MIN_ADDR', '32768')]
142147
if arch == 'RISCV':
143148
l += [KconfigCheck('self_protection', 'defconfig', 'DEBUG_SG', 'y')]
144149
l += [OR(KconfigCheck('self_protection', 'defconfig', 'LIST_HARDENED', 'y'),
@@ -255,7 +260,6 @@ def add_kconfig_checks(l: List[ChecklistObjType], arch: str) -> None:
255260
l += [KconfigCheck('self_protection', 'kspp', 'DEFAULT_MMAP_MIN_ADDR', '65536')]
256261
l += [KconfigCheck('self_protection', 'kspp', 'HW_RANDOM_TPM', 'y')]
257262
if arch in ('ARM64', 'ARM', 'RISCV'):
258-
l += [KconfigCheck('self_protection', 'kspp', 'SYN_COOKIES', 'y')] # another reason?
259263
l += [KconfigCheck('self_protection', 'kspp', 'WERROR', 'y')]
260264
if arch in ('X86_64', 'ARM64'):
261265
l += [AND(cfi_clang_is_set,
@@ -505,6 +509,12 @@ def add_kconfig_checks(l: List[ChecklistObjType], arch: str) -> None:
505509
l += [OR(KconfigCheck('cut_attack_surface', 'a13xp0p0v', 'TRIM_UNUSED_KSYMS', 'y'),
506510
modules_not_set)]
507511

512+
# 'network_security'
513+
if arch in ('X86_64', 'X86_32'):
514+
l += [KconfigCheck('network_security', 'defconfig', 'SYN_COOKIES', 'y')]
515+
if arch in ('ARM64', 'ARM', 'RISCV'):
516+
l += [KconfigCheck('network_security', 'kspp', 'SYN_COOKIES', 'y')]
517+
508518
# 'harden_userspace'
509519
if arch == 'ARM64':
510520
l += [KconfigCheck('harden_userspace', 'defconfig', 'ARM64_PTR_AUTH', 'y')]
@@ -806,15 +816,10 @@ def add_sysctl_checks(l: List[ChecklistObjType], arch: StrOrNone) -> None:
806816
# Use an omnipresent kconfig symbol to see if we have a kconfig file for checking:
807817
have_kconfig = KconfigCheck('-', '-', 'LOCALVERSION', 'is present')
808818

819+
# 'self_protection', 'kspp'
809820
l += [OR(SysctlCheck('self_protection', 'kspp', 'net.core.bpf_jit_harden', '2'),
810821
AND(KconfigCheck('-', '-', 'BPF_JIT', 'is not set'),
811822
have_kconfig))]
812-
# Choosing a right value for 'kernel.oops_limit' and 'kernel.warn_limit' is not easy.
813-
# A small value (e.g. 1, which is recommended by KSPP) allows easy DoS.
814-
# A large value (e.g. 10000, which is default 'kernel.oops_limit') may miss the exploit attempt.
815-
# Let's choose 100 as a reasonable compromise.
816-
l += [SysctlCheck('self_protection', 'a13xp0p0v', 'kernel.oops_limit', '100')]
817-
l += [SysctlCheck('self_protection', 'a13xp0p0v', 'kernel.warn_limit', '100')]
818823
# Compatible with the 'DEFAULT_MMAP_MIN_ADDR' kconfig check by KSPP:
819824
if arch in ('X86_64', 'X86_32', 'RISCV'):
820825
l += [SysctlCheck('self_protection', 'kspp', 'vm.mmap_min_addr', '65536')]
@@ -825,6 +830,15 @@ def add_sysctl_checks(l: List[ChecklistObjType], arch: StrOrNone) -> None:
825830
if arch == 'ARM':
826831
l += [SysctlCheck('self_protection', 'kspp', 'vm.mmap_min_addr', '32768')]
827832

833+
# 'self_protection', 'a13xp0p0v'
834+
# Choosing a right value for 'kernel.oops_limit' and 'kernel.warn_limit' is not easy.
835+
# A small value (e.g. 1, which is recommended by KSPP) allows easy DoS.
836+
# A large value (e.g. 10000, which is default 'kernel.oops_limit') may miss the exploit attempt.
837+
# Let's choose 100 as a reasonable compromise.
838+
l += [SysctlCheck('self_protection', 'a13xp0p0v', 'kernel.oops_limit', '100')]
839+
l += [SysctlCheck('self_protection', 'a13xp0p0v', 'kernel.warn_limit', '100')]
840+
841+
# 'cut_attack_surface', 'kspp'
828842
l += [SysctlCheck('cut_attack_surface', 'kspp', 'kernel.dmesg_restrict', '1')]
829843
l += [SysctlCheck('cut_attack_surface', 'kspp', 'kernel.perf_event_paranoid', '3')]
830844
# Without the custom patch that adds CONFIG_SECURITY_PERF_EVENTS_RESTRICT,
@@ -850,28 +864,62 @@ def add_sysctl_checks(l: List[ChecklistObjType], arch: StrOrNone) -> None:
850864
have_kconfig))]
851865
# at first, it disabled unprivileged userfaultfd,
852866
# and since v5.11 it enables unprivileged userfaultfd for user-mode only
853-
854867
l += [OR(SysctlCheck('cut_attack_surface', 'kspp', 'kernel.modules_disabled', '1'),
855868
AND(KconfigCheck('cut_attack_surface', 'kspp', 'MODULES', 'is not set'),
856869
have_kconfig))]
857870
# kernel.modules_disabled=1 should be set (e.g. with systemd) after
858871
# the kernel startup, when all the required modules have loaded
859872

873+
# 'cut_attack_surface', 'grsec'
860874
l += [OR(SysctlCheck('cut_attack_surface', 'grsec', 'kernel.io_uring_disabled', '2'),
861875
AND(KconfigCheck('cut_attack_surface', 'grsec', 'IO_URING', 'is not set'),
862876
have_kconfig))] # compatible with the 'IO_URING' kconfig check by grsecurity
863877

878+
# 'cut_attack_surface', 'a13xp0p0v'
864879
l += [OR(SysctlCheck('cut_attack_surface', 'a13xp0p0v', 'kernel.sysrq', '0'),
865880
AND(KconfigCheck('cut_attack_surface', 'clipos', 'MAGIC_SYSRQ', 'is not set'),
866881
have_kconfig))]
867882

883+
# 'network_security', 'cis'
884+
l += [SysctlCheck('network_security', 'cis', 'net.ipv4.icmp_ignore_bogus_error_responses', '1')]
885+
l += [SysctlCheck('network_security', 'cis', 'net.ipv4.icmp_echo_ignore_broadcasts', '1')]
886+
l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.all.accept_redirects', '0')]
887+
l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.default.accept_redirects', '0')]
888+
l += [SysctlCheck('network_security', 'cis', 'net.ipv6.conf.all.accept_redirects', '0')]
889+
l += [SysctlCheck('network_security', 'cis', 'net.ipv6.conf.default.accept_redirects', '0')]
890+
l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.all.accept_source_route', '0')]
891+
l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.default.accept_source_route', '0')]
892+
l += [SysctlCheck('network_security', 'cis', 'net.ipv6.conf.all.accept_source_route', '0')]
893+
l += [SysctlCheck('network_security', 'cis', 'net.ipv6.conf.default.accept_source_route', '0')]
894+
l += [SysctlCheck('network_security', 'cis', 'net.ipv4.tcp_syncookies', '1')]
895+
l += [SysctlCheck('network_security', 'cis', 'net.ipv6.conf.all.accept_ra', '0')]
896+
l += [SysctlCheck('network_security', 'cis', 'net.ipv6.conf.default.accept_ra', '0')]
897+
# The following recommendations from the CIS Benchmark may impact normal network functionality:
898+
# CAUTION: without IP forwarding your system can not act as a router
899+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.ip_forward', '0')]
900+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv6.conf.all.forwarding', '0')]
901+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.all.send_redirects', '0')]
902+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.default.send_redirects', '0')]
903+
# CAUTION: it's strange to ignore ICMP redirects from your default gateway
904+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.all.secure_redirects', '0')]
905+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.default.secure_redirects', '0')]
906+
# CAUTION: rp_filter for network packets breaks asymmetrical routing (BGP, OSPF, etc) and some VPNs
907+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.all.rp_filter', '1')]
908+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.default.rp_filter', '1')]
909+
# CAUTION: messages about packets with un-routable source addresses may clog up the kernel log
910+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.all.log_martians', '1')]
911+
# l += [SysctlCheck('network_security', 'cis', 'net.ipv4.conf.default.log_martians', '1')]
912+
913+
# 'harden_userspace', 'kspp'
868914
l += [SysctlCheck('harden_userspace', 'kspp', 'fs.protected_symlinks', '1')]
869915
l += [SysctlCheck('harden_userspace', 'kspp', 'fs.protected_hardlinks', '1')]
870916
l += [SysctlCheck('harden_userspace', 'kspp', 'fs.protected_fifos', '2')]
871917
l += [SysctlCheck('harden_userspace', 'kspp', 'fs.protected_regular', '2')]
872918
l += [SysctlCheck('harden_userspace', 'kspp', 'fs.suid_dumpable', '0')]
873919
l += [SysctlCheck('harden_userspace', 'kspp', 'kernel.randomize_va_space', '2')]
874920
l += [SysctlCheck('harden_userspace', 'kspp', 'kernel.yama.ptrace_scope', '3')]
921+
922+
# 'harden_userspace', 'a13xp0p0v'
875923
l += [SysctlCheck('harden_userspace', 'a13xp0p0v', 'vm.mmap_rnd_bits', 'MAX')]
876924
# 'MAX' value is refined using ARCH_MMAP_RND_BITS_MAX
877925
l += [SysctlCheck('harden_userspace', 'a13xp0p0v', 'vm.mmap_rnd_compat_bits', 'MAX')]

0 commit comments

Comments
 (0)