From 6a875bc851cabba70200a156244a43d17abc3644 Mon Sep 17 00:00:00 2001 From: Claudio Maradonna Date: Mon, 21 Nov 2022 12:56:57 +0100 Subject: [PATCH] Better hardening-basic role --- handbook.yml | 6 +- roles/hardening-basic/defaults/main.yml | 14 +-- roles/hardening-basic/tasks/main.yml | 86 ++++++------------- roles/hardening-basic/tasks/modprobe.yml | 10 --- .../templates/etc/modprobe.d/hardening.conf | 7 ++ .../etc/ssh/sshd_config.d/99-hardening.conf | 58 +++++++++++++ .../templates/etc/sysctl.d/99-hardening.conf | 66 ++++++++++++++ 7 files changed, 168 insertions(+), 79 deletions(-) delete mode 100644 roles/hardening-basic/tasks/modprobe.yml create mode 100644 roles/hardening-basic/templates/etc/modprobe.d/hardening.conf create mode 100644 roles/hardening-basic/templates/etc/ssh/sshd_config.d/99-hardening.conf create mode 100644 roles/hardening-basic/templates/etc/sysctl.d/99-hardening.conf diff --git a/handbook.yml b/handbook.yml index a453060..b6b25b6 100644 --- a/handbook.yml +++ b/handbook.yml @@ -13,8 +13,10 @@ - role: iptables-ipfs tags: [firewall, ipfs] - - fail2ban-basic - - hardening-basic + - role: fail2ban-basic + tags: [hardening] + - role: hardening-basic + tags: [hardening] - yggdrasil - role: snort-community tags: snort diff --git a/roles/hardening-basic/defaults/main.yml b/roles/hardening-basic/defaults/main.yml index 4c0cb98..8445b7f 100644 --- a/roles/hardening-basic/defaults/main.yml +++ b/roles/hardening-basic/defaults/main.yml @@ -2,11 +2,15 @@ # defaults file for hardening-basic hardening_sshd_enabled: true +hardening_sshd_port: 22 +hardening_sshd_authorized_key_file: .ssh/authorized_keys hardening_sshd_tcp_forward: false +hardening_sshd_legal_banner: false hardening_sshd_permissions_set_sticky_bit: true -hardening_modprobe_files: - - /etc/modprobe.d/disable-network-filesystems.conf - - /etc/modprobe.d/disable-rare-filesystems.conf - - /etc/modprobe.d/disable-rare-protocols.conf - - /etc/modprobe.d/disable-vivid.conf +hardening_modprobe_disable_list: + ipv6: [ipv6] + network_filesystems: [cifs,nfs,nfsv3,nfsv4,gfs2] + rare_filesystems: [cramfs,freevxfs,jffs2,hfs,hfsplus,squashfs,udf] + rare_protocols: [dccp,sctp,rds,tipc,n-hdlc,ax25,netrom,x25,rose,decnet,econet,af_802154,ipx,appletalk,psnap,p8023,p8022,can,atm] + vivid: [vivid] diff --git a/roles/hardening-basic/tasks/main.yml b/roles/hardening-basic/tasks/main.yml index e36a0e7..6a5c355 100644 --- a/roles/hardening-basic/tasks/main.yml +++ b/roles/hardening-basic/tasks/main.yml @@ -3,71 +3,33 @@ - name: Basic Hardening block: + - name: Create and copy hardening files + ansible.builtin.template: + src: '{{ item.src }}' + dest: '/etc/{{ item.path }}' + with_community.general.filetree: '../templates/etc/' + when: item.state == 'file' + - name: Harden SSH Config when: 'hardening_sshd_enabled is true' block: - - name: Check if sshd_config/99-hardening exists - stat: - path: /etc/ssh/sshd_config.d/99-hardening.conf - register: file_name - - name: Download sshd_config - when: not file_name.stat.exists - ansible.builtin.get_url: - url: https://git.unitoo.it/unitoo/configurations/raw/branch/master/ssh/etc/ssh/sshd_config - dest: /etc/ssh/sshd_config.d/99-hardening.conf + - name: Give 1700 permissions to .ssh folder + ansible.builtin.file: + path: /root/.ssh + owner: root + group: root + mode: "{{ '1' if hardening_sshd_permissions_set_sticky_bit }}700" - - name: Enable TCP SSH Forwarding - when: 'hardening_sshd_tcp_forward is true' - replace: - path: /etc/ssh/sshd_config.d/99-hardening.conf - regexp: 'AllowTcpForwarding no' - replace: 'AllowTcpForwarding yes' - backup: yes + - name: Give 1600 permissions to .ssh/authorized_keys file + ansible.builtin.file: + path: /root/.ssh/authorized_keys + owner: root + group: root + mode: "{{ '1' if hardening_sshd_permissions_set_sticky_bit }}600" - - name: Give 1700 permissions to .ssh folder - ansible.builtin.file: - path: /root/.ssh - owner: root - group: root - mode: "{{ '1' if hardening_sshd_permissions_set_sticky_bit }}700" - - - name: Give 1600 permissions to .ssh/authorized_keys file - ansible.builtin.file: - path: /root/.ssh/authorized_keys - owner: root - group: root - mode: "{{ '1' if hardening_sshd_permissions_set_sticky_bit }}600" - - - name: Restart sshd - when: "is_docker is not true" - ansible.builtin.systemd: - state: restarted - name: sshd - - - name: Create if not exists /etc/modprobe.d - file: - path: /etc/modprobe.d - state: directory - - - name: modprobe.d setup - include_tasks: modprobe.yml - loop: "{{ hardening_modprobe_files }}" - loop_control: - loop_var: file - - - name: Create if not exists /etc/sysctl.d - file: - path: /etc/sysctl.d - state: directory - - - name: Check if sysctl/99-hardening exists - stat: - path: /etc/sysctl.d/99-hardening.conf - register: file_name - - - name: Download sysctl.conf - when: not file_name.stat.exists - ansible.builtin.get_url: - url: https://git.unitoo.it/unitoo/configurations/raw/branch/master/sysctl/etc/sysctl.conf - dest: /etc/sysctl.d/99-hardening.conf + - name: Restart sshd + when: "is_docker is not true" + ansible.builtin.systemd: + state: restarted + name: sshd diff --git a/roles/hardening-basic/tasks/modprobe.yml b/roles/hardening-basic/tasks/modprobe.yml deleted file mode 100644 index d85c378..0000000 --- a/roles/hardening-basic/tasks/modprobe.yml +++ /dev/null @@ -1,10 +0,0 @@ -- name: Check if {{ file }} exists - stat: - path: "{{ file }}" - register: file_name - -- name: Download {{ file }} - when: not file_name.stat.exists - ansible.builtin.get_url: - url: "https://git.unitoo.it/unitoo/configurations/raw/branch/master/modprobe/{{file}}" - dest: "{{ file }}" diff --git a/roles/hardening-basic/templates/etc/modprobe.d/hardening.conf b/roles/hardening-basic/templates/etc/modprobe.d/hardening.conf new file mode 100644 index 0000000..f3cdca3 --- /dev/null +++ b/roles/hardening-basic/templates/etc/modprobe.d/hardening.conf @@ -0,0 +1,7 @@ +{% for section in hardening_modprobe_disable_list %} +# Disable for {{ section }} +{% for item in hardening_modprobe_disable_list[section] %} +install {{ item }} /bin/false +{% endfor %} + +{% endfor %} diff --git a/roles/hardening-basic/templates/etc/ssh/sshd_config.d/99-hardening.conf b/roles/hardening-basic/templates/etc/ssh/sshd_config.d/99-hardening.conf new file mode 100644 index 0000000..cd08c15 --- /dev/null +++ b/roles/hardening-basic/templates/etc/ssh/sshd_config.d/99-hardening.conf @@ -0,0 +1,58 @@ +{% if hardening_sshd_enabled %} + +Protocol 2 # Protocol 1 is fundamentally broken +StrictModes yes # Protects from misconfiguration + +#ListenAddress [ip-here] # Listening address +Port {{ hardening_sshd_port }} # Listening port. Normal 22 + +AuthenticationMethods publickey # Only public key authentication allowed +AuthorizedKeysFile {{ hardening_sshd_authorized_key_file }} +PubkeyAuthentication yes # Allow public key authentication +HostKey /etc/ssh/ssh_host_ed25519_key # Only allow ECDSA pubic key authentication +HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519 # Host keys the client should accepts +KexAlgorithms curve25519-sha256 # Specifies the available KEX (Key Exchange) algorithms +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com # Specifies the ciphers allowed +MACs hmac-sha2-512-etm@openssh.com # Specifies the available MAC alg. + +#Only allow incoming ECDSA and ed25519 sessions: +HostbasedAcceptedKeyTypes ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519 +PubkeyAcceptedKeyTypes sk-ecdsa-sha2-nistp256@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,ssh-ed25519 +#CASignatureAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519 + +PermitRootLogin WITHOUT-PASSWORD # Enable/disable root login +#AllowUsers [username] # Authorized SSH users are inside the admin group +MaxAuthTries 5 # Maximum allowed authentication attempts +MaxSessions 2 # Maximum allowed sessions by the user + +PasswordAuthentication no # No username password authentication +PermitEmptyPasswords no # No empty password authentcation allowed +IgnoreRhosts yes # Dont read users rhost files +HostbasedAuthentication no # Disable host-based authentication +ChallengeResponseAuthentication no # Unused authentication scheme +X11Forwarding no # Disable X11 forwarding + +LogLevel VERBOSE # Fingerprint details of failed login attempts +SyslogFacility AUTH # Logging authentication and authorization related commands +UseDNS no # Client from a location without proper DNS generate a warning in the logs + +PermitTunnel no # Only SSH connection and nothing else +AllowTcpForwarding {{ 'yes' if hardening_sshd_tcp_forward else 'no' }} # Disablow tunneling out via SSH +AllowStreamLocalForwarding no # Disablow tunneling out via SSH +GatewayPorts no # Disablow tunneling out via SSH +AllowAgentForwarding no # Do not allow agent forwarding + +{% if hardening_sshd_legal_banner %} +Banner /etc/issue.net # Show legal login banner +{% endif %} +PrintLastLog yes # Show last login + +ClientAliveInterval 900 # Client timeout (15 minutes) +ClientAliveCountMax 0 # This way enforces timeouts on the server side +LoginGraceTime 30 # Authenticatin must happen within 30 seconds +MaxStartups 2 # Max concurrent SSH sessions +TCPKeepAlive yes # Do not use TCP keep-alive + +AcceptEnv LANG LC_* # Allow client to pass locale environment variables + +{% endif %} diff --git a/roles/hardening-basic/templates/etc/sysctl.d/99-hardening.conf b/roles/hardening-basic/templates/etc/sysctl.d/99-hardening.conf new file mode 100644 index 0000000..2350204 --- /dev/null +++ b/roles/hardening-basic/templates/etc/sysctl.d/99-hardening.conf @@ -0,0 +1,66 @@ +# Hardened sysctl conf + +fs.protected_regular = 2 +fs.protected_fifos = 2 +fs.protected_hardlinks = 1 +fs.protected_symlinks = 1 +fs.suid_dumpable = 0 + +kernel.core_uses_pid = 1 +kernel.ctrl-alt-del = 0 +kernel.dmesg_restrict = 1 +kernel.kptr_restrict = 2 +kernel.randomize_va_space = 2 +kernel.sysrq = 0 +kernel.unprivileged_bpf_disabled = 1 + + +net.core.bpf_jit_harden = 2 +net.ipv4.conf.all.accept_redirects = 0 +net.ipv4.conf.all.accept_source_route = 0 +net.ipv4.conf.all.bootp_relay = 0 +net.ipv4.conf.all.forwarding = 0 +net.ipv4.conf.all.log_martians = 1 +net.ipv4.conf.all.mc_forwarding = 0 +net.ipv4.conf.all.proxy_arp = 0 +net.ipv4.conf.all.rp_filter = 1 +net.ipv4.conf.all.send_redirects = 0 +net.ipv4.conf.all.secure_redirects=0 +net.ipv4.tcp_rfc1337=1 +net.ipv4.tcp_sack=0 +net.ipv4.tcp_dsack=0 +net.ipv4.tcp_fack=0 + +net.ipv4.conf.default.accept_redirects = 0 +net.ipv4.conf.default.accept_source_route = 0 +net.ipv4.conf.default.log_martians = 1 +net.ipv4.conf.default.rp_filter=1 +net.ipv4.conf.default.send_redirects=0 +net.ipv4.conf.default.secure_redirects=0 + +net.ipv4.icmp_echo_ignore_broadcasts = 1 +net.ipv4.icmp_ignore_bogus_error_responses = 1 +net.ipv4.tcp_syncookies = 1 +net.ipv4.tcp_timestamps = 1 + +dev.tty.ldisc_autoload=0 +vm.unprivileged_userfaultfd=0 +kernel.kexec_load_disabled=1 +kernel.perf_event_paranoid=2 +kernel.yama.ptrace_scope=2 + +vm.mmap_rnd_bits=32 +vm.mmap_rnd_compat_bits=16 + +# Uncomment do disable ipv6 +#net.ipv6.conf.all.disable_ipv6=1 +#net.ipv6.conf.default.disable_ipv6=1 +#net.ipv6.conf.lo.disable_ipv6=1 + +net.ipv6.conf.all.accept_redirects = 0 +net.ipv6.conf.all.accept_source_route = 0 + +net.ipv6.conf.default.accept_redirects = 0 +net.ipv6.conf.default.accept_source_route = 0 + +vm.swappiness = 15