refactor(systemModule:security): split into modules and add kernel hardening
This commit is contained in:
		
							parent
							
								
									2c25c8c762
								
							
						
					
					
						commit
						3a91848085
					
				
					 6 changed files with 322 additions and 53 deletions
				
			
		
							
								
								
									
										18
									
								
								system/modules/security/1password/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								system/modules/security/1password/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | { lib, config, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   inherit (lib) mkIf; | ||||||
|  |   host = config.systemModules.host; | ||||||
|  | in | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  |   config = mkIf (host.type != "phone") { | ||||||
|  |     programs = { | ||||||
|  |       _1password.enable = true; | ||||||
|  |       _1password-gui = { | ||||||
|  |         enable = true; | ||||||
|  |         polkitPolicyOwners = [ "${host.admin.name}" ]; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | @ -1,55 +1,9 @@ | ||||||
| { lib, config, pkgs, ... }: |  | ||||||
| 
 |  | ||||||
| let |  | ||||||
|   cfg = config.systemModules.security; |  | ||||||
| in |  | ||||||
| 
 |  | ||||||
| { | { | ||||||
|   config = lib.mkIf cfg.enable { |   import = [ | ||||||
| 
 |     ./1password | ||||||
|     environment.systemPackages = with pkgs; [ |     ./kernel | ||||||
|       polkit_gnome |     ./pam | ||||||
|     ]; |     ./polkit | ||||||
| 
 |     ./sudo | ||||||
|     programs = { |   ]; | ||||||
|       gnupg.agent = { |  | ||||||
|         enable = true; |  | ||||||
|         enableSSHSupport = true; |  | ||||||
|       }; |  | ||||||
|       _1password = { |  | ||||||
|         enable = true; |  | ||||||
|       }; |  | ||||||
|       _1password-gui = { |  | ||||||
|         enable = true; |  | ||||||
|         polkitPolicyOwners = [ "ooks" ]; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|     security = { |  | ||||||
|       polkit = { |  | ||||||
|         enable = true; |  | ||||||
|       }; |  | ||||||
|       sudo = { |  | ||||||
|         enable = true; |  | ||||||
|         wheelNeedsPassword = false; |  | ||||||
|       }; |  | ||||||
|       rtkit.enable = true; |  | ||||||
|       pam.services.hyprlock = {}; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     systemd = { |  | ||||||
|       user.services.polkit-gnome-authentication-agent-1 = { |  | ||||||
|         description = "polkit-gnome-authentication-agent-1"; |  | ||||||
|         wantedBy = [ "graphical-session.target" ]; |  | ||||||
|         wants = [ "graphical-session.target" ]; |  | ||||||
|         after = [ "graphical-session.target" ]; |  | ||||||
|         serviceConfig = { |  | ||||||
|           Type = "simple"; |  | ||||||
|           ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1"; |  | ||||||
|           Restart = "on-failure"; |  | ||||||
|           RestartSec = 1; |  | ||||||
|           TimeoutStopSec = 10; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										195
									
								
								system/modules/security/kernel/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								system/modules/security/kernel/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,195 @@ | ||||||
|  | { lib, config, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   inherit (lib) optionals mkForce concatLists; | ||||||
|  |   inherit (builtins) elem; | ||||||
|  |   features = config.systemModules.host.hardware.features; | ||||||
|  | in | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  |   security = { | ||||||
|  |     # Protects the kernel from being tampered with at runtime. prevents the ability to hibernate. | ||||||
|  |     protectKernelImage = true;  | ||||||
|  | 
 | ||||||
|  |     # page table isolation (PTI) is a kernel option designed to protect against | ||||||
|  |     # side-channel attacks, including Meltdown & Spectre vunerabilities.   | ||||||
|  |     forcePageTableIsolation = true; | ||||||
|  | 
 | ||||||
|  |     # locking kernel modules during runtime breaks certain services by stopping them from being | ||||||
|  |     # loaded at runtime. we use some of these services, so we disable this kernel option. | ||||||
|  |     lockKernelModules = false; | ||||||
|  | 
 | ||||||
|  |     # we enable simultaneous multithreading (SMT) because while it increases our attack surface | ||||||
|  |     # disabling it comes at a large perfomance loss. | ||||||
|  |     allowSimultaneousMultithreading = true; | ||||||
|  | 
 | ||||||
|  |     # slight increase in attack surface, but allows for sandboxing | ||||||
|  |     allowUserNamespaces = true; | ||||||
|  | 
 | ||||||
|  |     # we don't need unpivileged user namespaces unless we are messing with containers so we disable | ||||||
|  |     unprivilegedUsernsClone = false; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   boot = { | ||||||
|  |     kernel = { | ||||||
|  |       sysctl = { | ||||||
|  |         # obfuscate kernel pointers to protect against attacks that rely on memory layout of the kernel | ||||||
|  |         "kernel.kptr_restrict" = 2; | ||||||
|  | 
 | ||||||
|  |         # we don't make use of sysrq so we disable it to protect ourselves against potential physical attacks | ||||||
|  |         "kernel.sysrq" = mkForce 0; | ||||||
|  | 
 | ||||||
|  |         # limits the exposer of the kernel memory address via dmesg | ||||||
|  |         "kernel.dmesg_restrict" = 1; | ||||||
|  |          | ||||||
|  |         # we are not a kernel developer so we disable this to prevent potential information leaks & attacks | ||||||
|  |         "kernel.ftrace_enabled" = false; | ||||||
|  | 
 | ||||||
|  |         # disables performance events for all non-root users, root can only acess events that are explicitly | ||||||
|  |         # enabled. | ||||||
|  |         "kernel.perf_event_paranoid" = 3; | ||||||
|  | 
 | ||||||
|  |         # disables the use of berkeley packet filter (BPF) to unpriviliged users. | ||||||
|  |         "kernel.unprivileged_bpf_disabled" = 1; | ||||||
|  | 
 | ||||||
|  |         # prevents potentially leaking sensitive information from the boot console kernel log. | ||||||
|  |         "kernel.printk" = "3 3 3 3"; | ||||||
|  | 
 | ||||||
|  |         # just-in-time (JIT) compiler for the berkeley packet filter (BPF). disable this as we dont make use | ||||||
|  |         # of it and reduces potential security risks. | ||||||
|  |         "net.core.bpf_jit_enable" = false; | ||||||
|  | 
 | ||||||
|  |         # disables core dumps for SUID and SGID this reduces the risk of exposing sensitive information | ||||||
|  |         # that might reside in the memory at the time of a crash | ||||||
|  |         "fs.suid_dumpable" = 0; | ||||||
|  | 
 | ||||||
|  |         # enforces strict access to files only allows the user or root to write regular files | ||||||
|  |         "fs.protected_regular" = 2; | ||||||
|  |         "fs.protected_fifos" = 2; | ||||||
|  | 
 | ||||||
|  |         # disables the automatic loading of TTY line disciplines | ||||||
|  |         "dev.tty.ldisc_autoload" = "0"; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     # https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html | ||||||
|  |     kernelParams = [ | ||||||
|  |       # kernel errors can trigger something known as an "oops", by settings oops=panic we add a fail-safe | ||||||
|  |       # mechanism to ensure that in the advent of an oops the system reboots, preventing the system from running | ||||||
|  |       # in a potentially compromised state. | ||||||
|  |       "oops=panic" | ||||||
|  | 
 | ||||||
|  |       # enforces signature checking on all kernel modules before they are loaded. | ||||||
|  |       "module.sig_enforce=1" | ||||||
|  | 
 | ||||||
|  |       # enables memory page poisoning, increasing the difficulty for attackers to exploit | ||||||
|  |       # use-after-free vulnerabillities. | ||||||
|  |       "page_poison=on" | ||||||
|  | 
 | ||||||
|  |       # enables kernel adress space layout randomization (KASLR) which mitigates memory exploits | ||||||
|  |       # & increases system entropy. | ||||||
|  |       "page_alloc.shuffle=1" | ||||||
|  | 
 | ||||||
|  |       # randomizes the kernel stack offset, mitigating stack-based attacks. | ||||||
|  |       "randomize_kstack_offset=on" | ||||||
|  | 
 | ||||||
|  |       # lockdown aims to restrict certain kernel functionality that could be exploited by an attacker with | ||||||
|  |       # user space code. | ||||||
|  |       "lockdown=confidentiality" | ||||||
|  | 
 | ||||||
|  |       # disables a common interface that contains sensitive info on the kernel | ||||||
|  |       "debugfs=off" | ||||||
|  | 
 | ||||||
|  |       # prevent kernel from blanking plymouth out of the frame buffer console  | ||||||
|  |       "fbcon=nodefer" | ||||||
|  | 
 | ||||||
|  |       # enables auditing of integrity measurement events | ||||||
|  |       "integrity_audit=1" | ||||||
|  | 
 | ||||||
|  |       # increases memory safety by modifying the state of the memory objects more closely & helps detecting | ||||||
|  |       # & identifying bugs | ||||||
|  |       "slub_debug=FZP" | ||||||
|  | 
 | ||||||
|  |       # disables the legacy vyscall mechanism, reducing attack surface. | ||||||
|  |       "vsyscall=none" | ||||||
|  |        | ||||||
|  |       # reduce exposure to heap attacks by preventing different slab caches from being merged. | ||||||
|  |       "slab_nomerge" | ||||||
|  | 
 | ||||||
|  |        | ||||||
|  |       "rootflags=noatime" | ||||||
|  |       "lsm=landlock,lockdown,yama,integrity,apparmor,bpf,tomoyo,selinux" | ||||||
|  |     ]; | ||||||
|  |     blacklistedKernelModules = concatLists [ | ||||||
|  |       # Obscure network protocols | ||||||
|  |       [ | ||||||
|  |         "dccp" # Datagram Congestion Control Protocol | ||||||
|  |         "sctp" # Stream Control Transmission Protocol | ||||||
|  |         "rds" # Reliable Datagram Sockets | ||||||
|  |         "tipc" # Transparent Inter-Process Communication | ||||||
|  |         "n-hdlc" # High-level Data Link Control | ||||||
|  |         "netrom" # NetRom | ||||||
|  |         "x25" # X.25 | ||||||
|  |         "ax25" # Amatuer X.25 | ||||||
|  |         "rose" # ROSE | ||||||
|  |         "decnet" # DECnet | ||||||
|  |         "econet" # Econet | ||||||
|  |         "af_802154" # IEEE 802.15.4 | ||||||
|  |         "ipx" # Internetwork Packet Exchange | ||||||
|  |         "appletalk" # Appletalk | ||||||
|  |         "psnap" # SubnetworkAccess Protocol | ||||||
|  |         "p8022" # IEEE 802.3 | ||||||
|  |         "p8023" # Novell raw IEEE 802.3 | ||||||
|  |         "can" # Controller Area Network | ||||||
|  |         "atm" # ATM | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  |       # Old or rare or insufficiently audited filesystems | ||||||
|  |       [ | ||||||
|  |         "adfs" # Active Directory Federation Services | ||||||
|  |         "affs" # Amiga Fast File System | ||||||
|  |         "befs" # "Be File System" | ||||||
|  |         "bfs" # BFS, used by SCO UnixWare OS for the /stand slice | ||||||
|  |         "cifs" # Common Internet File System | ||||||
|  |         "cramfs" # compressed ROM/RAM file system | ||||||
|  |         "efs" # Extent File System | ||||||
|  |         "erofs" # Enhanced Read-Only File System | ||||||
|  |         "exofs" # EXtended Object File System | ||||||
|  |         "freevxfs" # Veritas filesystem driver | ||||||
|  |         "f2fs" # Flash-Friendly File System | ||||||
|  |         "vivid" # Virtual Video Test Driver (unnecessary, and a historical cause of escalation issues) | ||||||
|  |         "gfs2" # Global File System 2 | ||||||
|  |         "hpfs" # High Performance File System (used by OS/2) | ||||||
|  |         "hfs" # Hierarchical File System (Macintosh) | ||||||
|  |         "hfsplus" # " same as above, but with extended attributes | ||||||
|  |         "jffs2" # Journalling Flash File System (v2) | ||||||
|  |         "jfs" # Journaled File System - only useful for VMWare sessions | ||||||
|  |         "ksmbd" # SMB3 Kernel Server | ||||||
|  |         "minix" # minix fs - used by the minix OS | ||||||
|  |         "nfsv3" # " (v3) | ||||||
|  |         "nfsv4" # Network File System (v4) | ||||||
|  |         "nfs" # Network File System | ||||||
|  |         "nilfs2" # New Implementation of a Log-structured File System | ||||||
|  |         "omfs" # Optimized MPEG Filesystem | ||||||
|  |         "qnx4" # extent-based file system used by the QNX4 and QNX6 OSes | ||||||
|  |         "qnx6" # " | ||||||
|  |         "squashfs" # compressed read-only file system (used by live CDs) | ||||||
|  |         "sysv" # implements all of Xenix FS, SystemV/386 FS and Coherent FS. | ||||||
|  |         "udf" # https://docs.kernel.org/5.15/filesystems/udf.html | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  |       # Disable Thunderbolt and FireWire to prevent DMA attacks | ||||||
|  |       [ | ||||||
|  |         "thunderbolt" | ||||||
|  |         "firewire-core" | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  |       # if bluetooth is enabled, whitelist the module | ||||||
|  |       # necessary for bluetooth dongles to work | ||||||
|  |       (optionals (! (elem "bluetooth" features)) [ | ||||||
|  |         "bluetooth" # let bluetooth work | ||||||
|  |         "btusb" # let bluetooth dongles work | ||||||
|  |       ]) | ||||||
|  |     ]; | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								system/modules/security/pam/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								system/modules/security/pam/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | { | ||||||
|  |   security = { | ||||||
|  |     pam = { | ||||||
|  |       loginLimits = [ | ||||||
|  |         { | ||||||
|  |           domain = "@wheel"; | ||||||
|  |           item = "nofile"; | ||||||
|  |           type = "soft"; | ||||||
|  |           value = "524288"; | ||||||
|  |         } | ||||||
|  |         { | ||||||
|  |           domain = "@wheel"; | ||||||
|  |           item = "nofile"; | ||||||
|  |           type = "hard"; | ||||||
|  |           value = "1048576"; | ||||||
|  |         } | ||||||
|  |       ]; | ||||||
|  |       services = { | ||||||
|  |         hyprlock = {}; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								system/modules/security/polkit/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								system/modules/security/polkit/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | 
 | ||||||
|  | { lib, config, ... }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   inherit (lib) mkDefault mkIf; | ||||||
|  | in | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  |   security.polkit = { | ||||||
|  |     enable = true; | ||||||
|  |     debug = mkDefault true; | ||||||
|  |     extraConfig = mkIf config.security.polkit.debug '' | ||||||
|  |       /* Log authorization checks. */ | ||||||
|  |       polkit.addRule(function(action, subject) { | ||||||
|  |         polkit.log("user " +  subject.user + " is attempting action " + action.id + " from PID " + subject.pid); | ||||||
|  |       }); | ||||||
|  |     ''; | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										60
									
								
								system/modules/security/sudo/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								system/modules/security/sudo/default.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | ||||||
|  | { lib, ... }:  | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   inherit (lib) mkDefault mkForce; | ||||||
|  | in | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  |   # nyx module | ||||||
|  |   security = { | ||||||
|  |     sudo-rs.enable = mkForce false; # we don't want the rust sudo fork | ||||||
|  |     sudo = { | ||||||
|  |       enable = true; | ||||||
|  |       wheelNeedsPassword = mkDefault false; # only use false here if the extraRules below are enabled | ||||||
|  |       execWheelOnly = mkForce true; # only allow wheel to execute sudo | ||||||
|  |       extraConfig = /* shell */ '' | ||||||
|  |         Defaults lecture = never # disable sudo lecture | ||||||
|  |         Defaults pwfeedback # password feedback | ||||||
|  |         Defaults env_keep += "EDITOR PATH DISPLAY" # variables to be passes to root | ||||||
|  |         Defaults timestamp_timeout = 300 # asks for sudo password ever 300s | ||||||
|  |       ''; | ||||||
|  |       extraRules = [ | ||||||
|  |         { | ||||||
|  |           # allow wheel group to run nixos-rebuild without password | ||||||
|  |           groups = ["wheel"]; | ||||||
|  |           commands = let | ||||||
|  |             currentSystem = "/run/current-system/"; | ||||||
|  |             storePath = "/nix/store/"; | ||||||
|  |           in [ | ||||||
|  |             { | ||||||
|  |               command = "${storePath}/*/bin/switch-to-configuration"; | ||||||
|  |               options = ["SETENV" "NOPASSWD"]; | ||||||
|  |             } | ||||||
|  |             { | ||||||
|  |               command = "${currentSystem}/sw/bin/nix-store"; | ||||||
|  |               options = ["SETENV" "NOPASSWD"]; | ||||||
|  |             } | ||||||
|  |             { | ||||||
|  |               command = "${currentSystem}/sw/bin/nix-env"; | ||||||
|  |               options = ["SETENV" "NOPASSWD"]; | ||||||
|  |             } | ||||||
|  |             { | ||||||
|  |               command = "${currentSystem}/sw/bin/nixos-rebuild"; | ||||||
|  |               options = ["NOPASSWD"]; | ||||||
|  |             } | ||||||
|  |             { | ||||||
|  |               # let wheel group collect garbage without password | ||||||
|  |               command = "${currentSystem}/sw/bin/nix-collect-garbage"; | ||||||
|  |               options = ["SETENV" "NOPASSWD"]; | ||||||
|  |             } | ||||||
|  |             { | ||||||
|  |               # let wheel group interact with systemd without password | ||||||
|  |               command = "${currentSystem}/sw/bin/systemctl"; | ||||||
|  |               options = ["NOPASSWD"]; | ||||||
|  |             } | ||||||
|  |           ]; | ||||||
|  |         } | ||||||
|  |       ]; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue