Skip to main content

debian 11 cis

1.initial setup

1.1 filesystem configuration

1. seprate partition for various mount points

2. disable unnecessary file systems 

ls /usr/lib/modules/$(uname -r)/kernel/fs

kernel modules location 


configure  blacklist and install 


 that this directory
should not be used for user defined module loading. Ensure that all such entries resides
in /etc/modprobe.d/*.conf files

use /bin/false as the command in disabling a particular module 

load module with modprobe

3.Ensure mounting of  filesystems is disabled

squashfs(snap needs it),cramfs,udf,


4. ensure /tmp is seprate partition

make it noexec,nosuid, and nodev

either make /tmp a tmpfs or separte partition

size={size} parameter in the relevant entry in /etc/fstab

/tmp tmpfs tmpfs rw,nosuid,nodev,noexec,inode6


5.configure /var

 Since the /var directory may
contain world-writable files and directories, there is a risk of resource exhaustion. It will essentially have the whole disk available to fill up and impact the system as a whole.

ensure nodev and nosuid


6.configure /var/tmp

The /var/tmp directory is a world-writable directory used for temporary storage by all users and some applications. Temporary files residing in /var/tmp are to be preserved between reboots

ensure separate partition for /var/tmp

nosuid,nodev and noexec

7. Ensure separate partition exists for 






 /home     nodev,nosuid

8. Ensure nodev,noexec,nosuid option set on /dev/shm partition\

9. Disable Automounting 

autofs allows automatic mounting of devices, typically including CD/DVDs and USB

systemctl is-enabled autofs

apt purge autofs

if dependencies on autofs

systemctl stop autofs

systemctl mask autofs

10. Disable USB Storage

sudo /sbin/modprobe -n -v usb-storage 

insmod /lib/modules/6.1.0-10-amd64/kernel/drivers/usb/storage/usb-storage.ko

echo -e "install usb-storage /bin/false" >>/etc/modprobe.d/usb-storage.conf

modprobe -r usb-storage

echo -e "blacklist usb-storage" >> /etc/modprobe.d/usb-storage.conf 

another way to block usb is using usbguard


1.2 Configure Software Updates

1. Ensure package manager repositories are configured

apt-cache policy

2. Ensure GPG keys are configured

sudo apt install gnupg2

apt-key list

1.3. Filesystem Integrity Checking


Ensure AIDE is installed 

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' aide

apt install aide aide-common


2.Ensure filesystem integrity is regularly checked  

#systemctl is-enabled aidecheck.service
# systemctl is-enabled aidecheck.timer
# systemctl status aidecheck.timer


1.4.Secure Boot Setting

 1.Ensure bootloader password is set 

Requiring a boot password upon execution of the boot loader will prevent an
unauthorized user from entering boot parameters or changing the boot partition. This prevents users from weakening security (e.g. turning off AppArmor at boot time.


if password protection is enabled, only the designated superuser can edit a Grub 2
menu item by pressing "e" or access the GRUB 2 command line by pressing "c"


2. Ensure permissions on bootloader config are configured

stat /boot/grub/grub.cfg

Access: (0400/-r--------) 


chown root:root /boot/grub/grub.cfg

chmod u-wx,go-rwx /boot/grub/grub.cfg


3.Ensure authentication required for single user mode 


grep -Eq '^root:\$[0-9]' /etc/shadow || echo "root is locked"

passwd root

1.5.process hardening

1.Ensure address space layout randomization (ASLR) is enabled 

Address space layout randomization (ASLR) is an exploit mitigation technique which randomly arranges the address space of key data areas of a process


/sbin/sysctl kernel.randomize_va_space   
kernel.randomize_va_space = 2

if not 2 set it :

#printf "kernel.randomize_va_space = 2" >> /etc/sysctl.d/60-kernel_sysctl.conf

# sysctl -w kernel.randomize_va_space=2

default value is 2 nowdays.

Configuration files are read from directories in /etc/, /run/, /usr/local/lib/, and
/lib/, in order of precedence. Files must have the the ".conf" extension. Files in /etc/
override files with the same name in /run/, /usr/local/lib/, and /lib/. Files in /run/
override files with the same name under /usr/.
All configuration files are sorted by their filename in lexicographic order, regardless of which of the directories they reside in. If multiple files specify the same option, the entry in the file with the lexicographically latest name will take precedence. Thus, the configuration in a certain file may either be replaced completely (by placing a file with the same name in a directory with higher priority), or individual settings might be changed (by specifying additional settings in a file with a different name that is ordered later).

Packages should install their configuration files in /usr/lib/ (distribution packages) or /usr/local/lib/ (local installs). Files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages.
It is recommended to prefix all filenames with a two-digit number and a dash, to simplify the ordering of the files.
If the administrator wants to disable a configuration file supplied by the vendor, the
recommended way is to place a symlink to /dev/null in the configuration directory in /etc/, with the same filename as the vendor configuration file. If the vendor
configuration file is included in the initrd image, the image has to be regenerated.


2.Ensure prelink is not installed

prelink is a program that modifies ELF shared libraries and ELF dynamically linked
binaries in such a way that the time needed for the dynamic linker to perform relocations at startup significantly decreases

The prelinking feature can interfere with the operation of AIDE, because it changes
binaries. Prelinking can also increase the vulnerability of the system if a malicious user is able to compromise a common library such as libc.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' prelink

restore binaries

prelink -ua

apt purge prelink

 3.Ensure Automatic Error Reporting is not enabled

dpkg-query -s apport > /dev/null 2>&1 && grep -Psi -- '^\h*enabled\h*=\h*[^0]\b' /etc/default/apport

systemctl is-active apport.service | grep '^active'



systemctl stop apport.service

systemctl --now disable apport.service


apt purge apport

4.Ensure core dumps are restricted 

grep -Es '^(\*|\s).*hard.*core.*(\s+#.*)?$' /etc/security/limits.conf
* hard core 0

# /sbin/sysctl fs.suid_dumpable
fs.suid_dumpable = 0

# grep "fs.suid_dumpable" /etc/sysctl.conf /etc/sysctl.d/*
fs.suid_dumpable = 0


systemctl is-enabled coredump.service

If enabled, masked, or disabled is returned systemd-coredump is installed


Add the following line to /etc/security/limits.conf or a /etc/security/limits.d/*

* hard core 0

fs.suid_dumpable = 0

#sysctl -w fs.suid_dumpable=0

for systemd-coredump



systemctl daemon-reload

1.6. Mandatory Access Control

Mandatory Access Control (MAC) provides an additional layer of access restrictions to processes on top of the base Discretionary Access Controls. By restricting how
processes can access files and resources on a system the potential impact from
vulnerabilities in the processes can be reduced.

Impact: Mandatory Access Control limits the capabilities of applications and daemons on a system, while this can prevent unauthorized access the configuration of MAC can be complex and difficult to implement correctly preventing legitimate access from occurring.

  • Apparmor is the default MAC provided with Debian systems.
  •  Additional Mandatory Access Control systems to include SELinux exist.
 If a different Mandatory Access Control systems is used, please follow it's vendors guidance for proper implementation in place of the guidance provided in this section


Configure AppArmor
AppArmor provides a Mandatory Access Control (MAC) system that greatly augments the default Discretionary Access Control (DAC) model. Under AppArmor MAC rules are applied by file paths instead of by security contexts as in other MAC systems. As such it does not require support in the filesystem and can be applied to network mounted filesystems for example. AppArmor security policies define what system resources applications can access and what privileges they can do so with. This automatically limits the damage that the software can do to files accessible by the calling user. The user does not need to take any action to gain this benefit. For an action to occur, both the traditional DAC permissions must be satisfied as well as the AppArmor MAC rules.
The action will not be allowed if either one of these models does not permit the action. In this way, AppArmor rules can only make a system's permissions more restrictive and secure.
1. AppArmor Documentation:
2. Ubuntu AppArmor Documentation:
3. SUSE AppArmor Documentation:


1.Ensure AppArmor is installed 

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'
apparmor apparmor-utils

apt install apparmor apparmor-utils

2.Ensure AppArmor is enabled in the bootloader configuration

grep "^\s*linux" /boot/grub/grub.cfg | grep -v "apparmor=1"

grep "^\s*linux" /boot/grub/grub.cfg | grep -v "security=apparmor"

cat etc/default/grub

GRUB_CMDLINE_LINUX="apparmor=1 security=apparmor"


3.Ensure all AppArmor Profiles are in enforce or complain mode

apparmor_status | grep profiles

37 profiles are loaded.
35 profiles are in enforce mode.
2 profiles are in complain mode.
4 processes have profiles defined

apparmor_status | grep processes

4 processes have profiles defined.
4 processes are in enforce mode.
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.


4.set all profile to enforce mode

#aa-enforce /etc/apparmor.d/*

set all profile to complain mode 

#aa-complain /etc/apparmor.d/*

1.7.Command Line Warning Banners

Presenting a warning message prior to the normal user login may assist in the
prosecution of trespassers on the computer system. Changing some of these login
banners also has the side effect of hiding OS version information and other detailed
system information from attackers attempting to target specific exploits at a system. 

The/etc/motd, /etc/issue, and /etc/ files govern warning banners for standardvcommand line logins for both local and remote users.
Guidelines published by the US Department of Defense require that warning messagesvinclude at least the name of the organization that owns the system, the fact that thevsystem is subject to monitoring and that such monitoring is in compliance with localvstatutes, and that use of the system implies consent to such monitoring. It is importantvthat the organization's legal counsel review the content of all messages before anyvsystem modifications are made, as these warning messages are inherently site-specific.

More information (including citations of relevant case law) can be found at

Note: The text provided in the remediation actions for these items is intended as an
example only. Please edit to include the specific text for your organization as approved by your legal department

1.Ensure message of the day is configured properly

The contents of the /etc/motd file are displayed to users after login and function as a message of the day for authenticated users.

grep -Eis "(\\\v|\\\r|\\\m|\\\s|$(grep '^ID=' /etc/os-release | cut -d= -f2
| sed -e 's/"//g'))" /etc/motd

Edit the /etc/motd file with the appropriate contents according to your site policy,
remove any instances of \m(machine arch) , \r(os release , \s(os name) , \v(os version) or references to the OS platform OR if the motd is not used, this file can be removed.

# rm /etc/motd

2.Ensure local login warning banner is configured properly

The contents of the /etc/issue file are displayed to users prior to login for local

echo "Authorized uses only. All activity may be monitored and reported." >


3.Ensure remote login warning banner is configured properly 

The contents of the /etc/ file are displayed to users prior to login for remote connections from configured services.

4.Ensure permissions on /etc/motd are configured

un the following command and verify: Uid and Gid are both 0/root and Access is 644,or the file doesn't exist

  stat -L /etc/motd

# chown root:root $(readlink -e /etc/motd)
# chmod u-x,go-wx $(readlink -e /etc/motd)


# rm /etc/motd

5.Ensure permissions on /etc/issue are configured

stat -L /etc/issue

chown root:root $(readlink -e /etc/issue)
# chmod u-x,go-wx $(readlink -e /etc/issue)

6.Ensure permissions on /etc/ are configured

stat -L /etc/


1.8. GNOME Display Manager

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' gdm3

apt purge gdm3


Ensure GDM login b

anner is configured


Ensure GDM disable-user-list option is enabled






dconf update

 Ensure GDM screen locks when the user is idle

idle-delay=uint32 {n}

lock-delay=uint32 {n}


 idle-delay=uint32 900


lock-delay=uint32 5

idle-delay=uint32 Should be 900 seconds (15 minutes) or less, not 0 (disabled)
and follow local site policy

lock-delay=uint32 should be 5 seconds or less and follow local site policy



echo -e '\nuser-db:user\nsystem-db:local' >> /etc/dconf/profile/user

mkdir /etc/dconf/db/local.d

Create the key file `/etc/dconf/db/{NAME_OF_DCONF_DATABASE}./{FILE_NAME} to provide information for the {NAME_OF_DCONF_DATABASE} database



idle-delay=uint32 900


lock-delay=uint32 5


dconf update

Users must log out and back in again before the system-wide settings take effect.


Ensure GDM screen locks cannot be overridden

to lock down a dconf key or subpath, create a locks subdirectory in the keyfile directory.
The files inside this directory contain a list of keys or subpaths to lock. Just as with the keyfiles, you may add any number of files to this directory. 


Setting a lock-out value reduces the window of opportunity for unauthorized user access
to another user's session that has been left unattended.
Without locking down the system settings, user settings take precedence over the
system settings.

Ensure GDM automatic mounting of removable media is disabled

gsettings set automount false
gsettings set automount-open false 
systemctl restart gdm.service 
cat /etc/dconf/db/local.d/00-media-automount
dconf update
Ensure GDM disabling automatic mounting of removable media is not overridden  


Ensure GDM autorun-never is enabled

cat /etc/dconf/db/local.d/00-media-autorun



dconf update

lock file

Lock desktop media-handling settings




Ensure XDCMP is not enabled

X Display Manager Control Protocol (XDMCP) is designed to provide authenticated
access to display management services for remote displays

XDMCP is inherently insecure.

XDMCP is not a ciphered protocol. This may allow an attacker to capture
keystrokes entered by a user

XDMCP is vulnerable to man-in-the-middle attacks. This may allow an attacker to
steal the credentials of legitimate users by impersonating the XDMCP server.

grep -Eis '^\s*Enable\s*=\s*true' /etc/gdm3/custom.conf

remove line Enable=true from /etc/gdm3/custom.conf


9.Ensure updates, patches, and additional security software are installed

apt -s upgrade

apt upgrade

upgrade - is used to install the newest versions of all packages currently installed
on the system from the sources enumerated in /etc/apt/sources.list. Packages
currently installed with new versions available are retrieved and upgraded; under
no circumstances are currently installed packages removed, or packages not
already installed retrieved and installed. New versions of currently installed
packages that cannot be upgraded without changing the install status of another
package will be left at their current version. An update must be performed first so
that apt knows that new versions of packages are available.

apt dist-upgrade

dist-upgrade - in addition to performing the function of upgrade, also intelligently
handles changing dependencies with new versions of packages; apt has a
"smart" conflict resolution system, and it will attempt to upgrade the most
important packages at the expense of less important ones if necessary. So, dist-
upgrade command may remove some packages. The /etc/apt/sources.list file
contains a list of locations from which to retrieve desired package files. See also
apt_preferences(5) for a mechanism for overriding the general settings for
individual packages.

2. Services

2.1. Configure Time Synchronization

it is recommended that physical systems and virtual guests lacking direct access to the physical host's clock be configured to synchronize their time using a service such as systemd-timesyncd, chrony, or ntp

Time synchronization is important to support time sensitive security mechanisms and ensures log files have consistent time records across the enterprise, which aids in forensic investigations.

One of the three time synchronization daemons should be available; chrony, systemd-timesyncd, or ntp

apt purge ntp chrony 

grep -Pr --include=*.{sources,conf} '^\h*(server|pool)\h+\H+' /etc/chrony/

pool iburst maxsources 4 #The maxsources option is unique to
the pool directive

server iburst
server iburst
server iburst

Edit /etc/chrony/chrony.conf or a file ending in .sources in /etc/chrony/sources.d/

 systemctl restart chronyd

chronyc reload sources

Ensure chrony is running as user _chrony

ps -ef | awk '(/[c]hronyd/ && $1!="_chrony") { print $1 }'

add or edit the user line to /etc/chrony/chrony.conf or a file ending in .conf in

user _chrony

systemctl is-enabled chrony.service

systemctl is-active chrony.service


 Configure systemd-timesyncd

/usr/lib/systemd/*.conf.d/, /usr/local/lib/systemd/*.conf.d/, and


The systemd-timesyncd service specifically implements only SNTP

find /etc/systemd -type f -name '*.conf' -exec grep -Ph '^\h*(NTP|FallbackNTP)=\H+' {} +


[Time] # Uses the generic name for NIST's time servers
-AND/OR- # Space
separated list of NIST time servers

systemctl try-reload-or-restart systemd-timesyncd

systemctl is-enabled systemd-timesyncd.service


ntp Access Control Commands:
restrict address [mask mask] [ippeerlimit int] [flag ...]

The address argument expressed in dotted-quad form is the address of a host or
network. Alternatively, the address argument can be a valid host DNS name.

The mask argument expressed in dotted-quad form defaults to,
meaning that the address is treated as the address of an individual host. A default entry (address, mask is always included and is always the first entry in the list. 

Note: the text string default, with no mask option, may be used to indicate the
default entry.

The ippeerlimit directive limits the number of peer requests for each IP to int, where a value of -1 means "unlimited", the current default. A value of 0 means "none". There would usually be at most 1 peering request per IP, but if the remote peering requests are behind a proxy there could well be more than 1 per IP. 

In the current implementation, flag always restricts access, i.e., an entry with no flags indicates that free access to the server is to be given. The flags are not orthogonal, in that more restrictive flags will often make less restrictive ones redundant. The flags can generally be classed into two categories, those which
restrict time service and those which restrict informational queries and attempts to do run-time reconfiguration of the server.

cat /etc/ntp.conf 

restrict -4 default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery

Ensure ntp is running as user ntp

grep -P -- '^\h*RUNASUSER=' /etc/init.d/ntp


ps -ef | awk '(/[n]tpd/ && $1!="ntp") { print $1 }'

2.2.Special Purpose Services

1. Ensure X Window System is not installed

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'
xserver-xorg* | grep -Pi '\h+installed\b'

apt purge xserver-xorg*

2.  Ensure Avahi Server is not installed

Avahi is a free zeroconf implementation, including a system for multicast DNS/DNS-SD service discovery. Avahi allows programs to publish and discover services and hosts running on a local network with no specific configuration. 

For example, a user can plug a computer into a network and Avahi automatically finds printers to print to, files to look at and people to talk to, as well as network services running on the machine.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'

# systemctl stop avahi-daaemon.service
# systemctl stop avahi-daemon.socket
# apt purge avahi-daemon


3. Ensure CUPS is not installed

The Common Unix Print System (CUPS) provides the ability to print to both local and network printers. A system running CUPS can also accept print jobs from remote systems and print them to local printers. It also provides a web based remote administration capability.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' cups

apt purge cups


4. Ensure DHCP Server is not installed 

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' isc-

apt purge isc-dhcp-server


5. Ensure LDAP server is not installed 

The Lightweight Directory Access Protocol (LDAP) was introduced as a replacement for NIS/YP. It is a service that provides a method for looking up information from a central database.


dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'

apt purge slapd


 6. Ensure NFS is not installed 

The Network File System (NFS) is one of the first and most widely distributed file
systems in the UNIX environment. It provides the ability for systems to mount file
systems of other servers through the network.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' nfs-

apt purge nfs-kernel-server


7. Ensure DNS Server is not installed

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'

apt purge bind9


 8. Ensure FTP Server is not installed

TP does not protect the confidentiality of data or authentication credentials. It is
recommended SFTP be used if file transfer is required. Unless there is a need to run the system as a FTP server (for example, to allow anonymous downloads), it is
recommended that the package be deleted to reduce the potential attack surface


 dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'

apt purge vsftpd

9. Ensure HTTP server is not installed

HTTP or web servers provide the ability to host web site content.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'

apt purge apache2 nginx

 10. Ensure IMAP and POP3 server are not installed

dovecot-imapd and dovecot-pop3d are an open source IMAP and POP3 server for Linux based systems.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'
dovecot-imapd dovecot-pop3d

courier-imap and cyrus-imap


11. Ensure Samba is not installed

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'

apt purge samba

12. Ensure HTTP Proxy Server is not installed

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'


13. Ensure SNMP Server is not installed

Simple Network Management Protocol (SNMP) is a widely used protocol for monitoring the health and welfare of network equipment, computer equipment and devices like UPSs.
Net-SNMP is a suite of applications used to implement SNMPv1 (RFC 1157), SNMPv2 (RFCs 1901-1908), and SNMPv3 (RFCs 3411-3418) using both IPv4 and IPv6. Support for SNMPv2 classic (a.k.a. "SNMPv2 historic" - RFCs 1441-1452) was dropped
with the 4.0 release of the UCD-snmp package. The Simple Network Management Protocol (SNMP) server is used to listen for SNMP commands from an SNMP management system, execute the commands or collect the information and then send results back to the requesting system.

SNMPv1, which transmits data in the clear and does not require authentication to execute commands. 

SNMPv3 replaces the simple/clear text password sharing used in SNMPv2 with more securely encoded parameters. 

If the the SNMP service is not required, the net-snmp package should be removed to reduce the attack surface of the system

Note: If SNMP is required:

The server should be configured for SNMP v3 only. User Authentication and
Message Encryption should be configured.

If SNMP v2 is absolutely necessary, modify the community strings' values.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' snmp

apt purge snmp

14. Ensure NIS Server is not installed

The Network Information Service (NIS) (formally known as Yellow Pages) is a client- server directory service protocol for distributing system configuration files. The NIS server is a collection of programs that allow for the distribution of configuration files.

The NIS service is inherently an insecure system that has been vulnerable to DOS
attacks, buffer overflows and has poor authentication for querying NIS maps. NIS
generally has been replaced by such protocols as Lightweight Directory Access
Protocol (LDAP). It is recommended that the service be removed and other, more
secure services be used

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' nis

apt purge nis

15. Ensure mail transfer agent is configured for local-only mode

Mail Transfer Agents (MTA), such as sendmail and Postfix, are used to listen for
incoming mail and transfer the messages to the appropriate user or mail server. If the system is not intended to be a mail server, it is recommended that the MTA be
configured to only process local mail.

ss -lntu | grep -E ':25\s' | grep -E -v '\s(|::1):25\s'


inet_interfaces = loopback-only

# systemctl restart postfix

16. Ensure rsync service is either not installed or masked

The rsync service can be used to synchronize files between systems over network

The rsync service presents a security risk as it uses unencrypted protocols for
communication. The rsync package should be removed to reduce the attack area of the system.

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' rsync

apt purge rsync 

systemctl stop rsync

systemctl mask rsync

2.3.  Service Clients

Ensure NIS,rsh,talk,telnet,ldap,RPC  client is not installed

rsh :

these legacy clients contain numerous security exposures and have been replaced withthe more secure SSH package. Even if the server is removed, it is best to ensure the clients are also removed to prevent users from inadvertently attempting to use these commands and therefore exposing their credentials. Note that removing the rsh package removes the clients for rsh , rcp and rlogin . 


The talk software makes it possible for users to send and receive messages across
systems through a terminal session. The talk client, which allows initialization of talk sessions, is installed by default


The telnet protocol is insecure and unencrypted. The use of an unencrypted
transmission medium could allow an unauthorized user to steal credentials. The ssh
package provides an encrypted session and stronger security and is included in most Linux distributions.



Remote Procedure Call (RPC) is a method for creating low level client server
applications across different system architectures. It requires an RPC compliant client listening on a network port. The supporting package is rpcbind."

apt purge nis rsh-client talk telnet  ldap-utils rpcbind 

 2.4. Ensure nonessential services are removed or masked

A network port is identified by its number, the associated IP address, and the type of the communication protocol such as TCP or UDP.
A listening port is a network port on which an application or process listens on, acting as a communication endpoint.
Each listening port can be open or closed (filtered) using a firewall. In general terms, an open port is a network port that accepts incoming packets from remote locations.

Services listening on the system pose a potential risk as an attack vector. These
services should be reviewed, and if not required, the service should be stopped, and the package containing the service should be removed. If required packages have a dependency, the service should be stopped and masked to reduce the attack surface of the system.

ss -plntu

apt purge <package_name>

# systemctl stop <service_name>.socket
# systemctl stop <service_name>.service
# systemctl mask <service_name>.socket
# systemctl mask <service_name>.service

3. Network Configuration

sysctl settings are defined through files in /usr/lib/sysctl.d/, /run/sysctl.d/,
and /etc/sysctl.d/.
Files must have the ".conf" extension.
 Vendors settings live in /usr/lib/sysctl.d/
To override a whole file, create a new file with the same name in /etc/sysctl.d/
and put new settings there.
To override only specific settings, add a file with a lexically later name in
/etc/sysctl.d/ and put new settings there.
The paths where sysctl preload files usually exist
> /run/sysctl.d/*.conf
> /usr/lib/sysctl.d/*.conf 
 On systems with Uncomplicated Firewall, additional settings may be configured
in /etc/ufw/sysctl.conf
 The settings in /etc/ufw/sysctl.conf will override settings in
 This behavior can be changed by updating the IPT_SYSCTL parameter in

3.1.Disable unused network protocols and devices

1. Ensure system is checked to determine if IPv6 is enabled

Internet Protocol Version 6 (IPv6) is the most recent version of Internet Protocol (IP). It's designed to supply IP addressing and additional security to support the predicted growth of connected devices. IPv6 is based on 128-bit addressing and can support 340 undecillion, which is 340 trillion3 addresses.

Features of IPv6
  • Hierarchical addressing and routing infrastructure
  • Stateful and Stateless configuration
  • Support for quality of service (QoS)
  • An ideal protocol for neighboring node interaction
pass ipv6.disable=1 to kernel cmdline

# printf "
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
" >> /etc/sysctl.d/60-disable_ipv6.conf

sysctl -w net.ipv6.conf.all.disable_ipv6=1
sysctl -w net.ipv6.conf.default.disable_ipv6=1
sysctl -w net.ipv6.route.flush=1

2. Ensure wireless interfaces are disabled 

If wireless is not to be used, wireless devices can be disabled to reduce the potential attack surface.

find /sys/class/net/*/ -type d -name wireless

find wireless driver module name 
for driverdir in $(find /sys/class/net/*/ -type d -name wireless | xargs -0 dirname); do basename "$(readlink -f "$driverdir"/device/driver/module)";done | sort -u


install ath10k_pci /bin/true

3. Ensure DCCP is disabled

The Datagram Congestion Control Protocol (DCCP) is a transport layer protocol that supports streaming media and telephony. DCCP provides a way to gain access to congestion control, without having to do it at the application layer, but does not provide in-sequence delivery.

# Check how module will be loaded
/sbin/modprobe -n -v dccp
insmod /lib/modules/6.1.0-10-amd64/kernel/net/dccp/dccp.ko 

cat /etc/modprobe.d/ddcp.conf
install dccp /bin/false

lsmod | grep dccp
modprobe -r dccp

blacklist dccp 

4. Ensure SCTP is disabled 

The Stream Control Transmission Protocol (SCTP) is a transport layer protocol used to support message oriented communication, with several streams of messages in one connection. It serves a similar function as TCP and UDP, incorporating features of both. It is message-oriented like UDP, and ensures reliable in-sequence transport of messages with congestion control like TCP  
same for dccp with module name sctp

5. Ensure RDS is disabled

The Reliable Datagram Sockets (RDS) protocol is a transport layer protocol designed to provide low-latency, high-bandwidth communications between cluster nodes. It was developed by the Oracle Corporation

module name rds blacklist and install to /bin/false

6.  Ensure TIPC is disabled 
The Transparent Inter-Process Communication (TIPC) protocol is designed to provide communication between cluster nodes.

kernel module name tipc

3.2.Network Parameters (Host Only)

Ensure packet redirect sending is disabled

iCMP Redirects are used to send routing information to other hosts. As a host itself
does not act as a router (in a host only configuration), there is no need to send

An attacker could use a compromised host to send invalid ICMP redirects to other
router devices in an attempt to corrupt routing and have users access a system set up by the attacker as opposed to a valid system.

net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

/sbin/sysctl net.ipv4.conf.all.send_redirects  net.ipv4.conf.default.send_redirects
net.ipv4.conf.default.send_redirects = 0
with ufw /etc/ufw/sysctl.conf 
Ensure IP forwarding is disabled
Ensures that a system with multiple interfaces (for example, a hard proxy), will never be able to forward packets, and therefore, never serve as a router.
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0 

/sbin/sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding 

3.3. Network Parameters (Host and Router)

1.Ensure source routed packets are not accepted

in networking, source routing allows a sender to partially or fully specify the route
packets take through a network. In contrast, non-source routed packets travel a path determined by routers in the network. In some cases, systems may not be routable or reachable from some locations (e.g. private addresses vs. Internet routable), and so source routed packets would need to be used.

net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
Disables the system from accepting source routed packets. Assume this system was
capable of routing packets to Internet routable addresses on one interface and private addresses on another interface. Assume that the private addresses were not routable to the Internet routable addresses and vice versa. Under normal routing circumstances, an attacker from the Internet routable addresses could not use the system as a way to reach the private address systems. If, however, source routed packets were allowed, they could be used to gain access to the private address systems as the route could be specified, rather than rely on routing protocols that did not allow this routing. 

2. Ensure ICMP redirects are not accepted 

CMP redirect messages are packets that convey routing information and tell your host (acting as a router) to send packets via an alternate path. It is a way of allowing an outside routing device to update your system routing tables.
 Attackers could use bogus ICMP redirect messages to maliciously alter the system
routing tables and get them to send packets to incorrect networks and allow your
system packets to be captured.
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0 

/sbin/sysctl  net.ipv4.conf.all.accept_redirects net.ipv4.conf.default.accept_redirects net.ipv6.conf.all.accept_redirects net.ipv6.conf.default.accept_redirects
default is all 1  

3. Ensure secure ICMP redirects are not accepted

Secure ICMP redirects are the same as ICMP redirects, except they come from
gateways listed on the default gateway list. It is assumed that these gateways are
known to your system, and that they are likely to be secure.

it is still possible for even known gateways to be compromised.
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.secure_redirects = 0 

default is all 1

4. Ensure suspicious packets are logged

When enabled, this feature logs packets with un-routable source addresses to the
kernel log.
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

allows an administrator to investigate the possibility that an attacker is sending spoofed packets to their system.

default is zero

/sbin/sysctl net.ipv4.conf.all.log_martians net.ipv4.conf.default.log_martians

5.  Ensure broadcast ICMP requests are ignored  

setting net.ipv4.icmp_echo_ignore_broadcasts = 1 
will cause the system to ignore all
ICMP echo and timestamp requests to broadcast and multicast addresses.
Accepting ICMP echo and timestamp requests with broadcast or multicast destinations for your network could be used to trick your host into starting (or participating) in a Smurf attack. A Smurf attack relies on an attacker sending large amounts of ICMP broadcast messages with a spoofed source address. All hosts receiving this message and responding would send echo-reply messages back to the spoofed address, which is probably not routable. If many hosts respond to the packets, the amount of traffic on the network could be significantly multiplied.
/sbin/sysctl net.ipv4.icmp_echo_ignore_broadcasts 
default is 1 

6. Ensure bogus ICMP responses are ignored 

Setting :: net.ipv4.icmp_ignore_bogus_error_responses = 1 
prevents the kernel from logging
bogus responses (RFC-1122 non-compliant) from broadcast reframes, keeping file
systems from filling up with useless log messages.
Some routers (and some attackers) will send responses that violate RFC-1122 and
attempt to fill up a log file system with many useless error messages.
/sbin/sysctl net.ipv4.icmp_ignore_bogus_error_responses

 7.Ensure Reverse Path Filtering is enabled 

Setting net.ipv4.conf.all.rp_filter and net.ipv4.conf.default.rp_filter to 1
forces the Linux kernel to utilize reverse path filtering on a received packet to determine if the packet was valid. Essentially, with reverse path filtering, if the return packet does not go out the same interface that the corresponding source packet came from, the packet is dropped (and logged if log_martians is set).

net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

is a good way to deter attackers from sending your system bogus packets that cannot be responded to. One instance where this feature breaks down is if asymmetrical routing is employed. This would occur when using dynamic routing protocols (bgp, ospf, etc) on your system.

If you are using asymmetrical routing on your system, you will not be able to enable this feature without breaking the routing.

/sbin/sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.default.rp_filter
default both 0

8. Ensure TCP SYN Cookies is enabled

When tcp_syncookies is set, the kernel will handle TCP SYN packets normally until thehalf-open connection queue is full, at which time, the SYN cookie functionality kicks in.SYN cookies work by not using the SYN queue at all. Instead, the kernel simply repliesto the SYN with a SYN|ACK, but will include a specially crafted TCP sequence numberthat encodes the source and destination IP address and port number and the time thepacket was sent. A legitimate connection would send the ACK packet of the three wayhandshake with the specially crafted sequence number. This allows the system to verifythat it has received a valid response to a SYN cookie and allow the connection, eventhough there is no corresponding SYN in the queue.

Attackers use SYN flood attacks to perform a denial of service attacked on a system bysending many SYN packets without completing the three way handshake. This willquickly use up slots in the kernel's half-open connection queue and prevent legitimateconnections from succeeding. Setting net.ipv4.tcp_syncookies = 1 enables SYNcookies, allowing the system to keep accepting valid connections, even if under a denialof service attack

net.ipv4.tcp_syncookies = 1

/sbin/sysctl net.ipv4.tcp_syncookies

default is 1 

9. Ensure IPv6 router advertisements are not accepted

This setting disables the system's ability to accept IPv6 router advertisements.

It is recommended that systems do not accept router advertisements as they could be tricked into routing traffic to compromised machines. Setting hard routes within the system (usually a single default route to a trusted router) protects the system from bad routes.

net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0

/sbin/sysctl net.ipv6.conf.all.accept_ra net.ipv6.conf.default.accept_ra 
 default is all 1 

3.5. Firewall Configuration

A firewall is a set of rules. When a data packet moves into or out of a protected network space, its contents (in particular, information about its origin, target, and the protocol it plans to use) are tested against the firewall rules to see if it should be allowed through To provide a Host Based Firewall, the Linux kernel includes support for:
Netfilter - A set of hooks inside the Linux kernel that allows kernel modules to
register callback functions with the network stack. A registered callback function
is then called back for every packet that traverses the respective hook within the
network stack. Includes the ip_tables, ip6_tables, arp_tables, and ebtables kernel
modules. These modules are some of the significant parts of the Netfilter hook
nftables - A subsystem of the Linux kernel providing filtering and classification of
network packets/datagrams/frames. nftables is supposed to replace certain parts
of Netfilter, while keeping and reusing most of it. nftables utilizes the building
blocks of the Netfilter infrastructure, such as the existing hooks into the
networking stack, connection tracking system, userspace queueing component,
and logging subsystem. Is available in Linux kernels 3.13 and newer.
In order to configure firewall rules for Netfilter or nftables, a firewall utility needs to be installed. 
Guidance has been included for the following firewall utilities:
UncomplicatedFirewall (ufw) - Provides firewall features by acting as a front-end
for the Linux kernel's netfilter framework via the iptables backend. ufw supports
both IPv4 and IPv6 networks
nftables - Includes the nft utility for configuration of the nftables subsystem of the
Linux kernel
iptables - Includes the iptables, ip6tables, arptables and ebtables utilities for
configuration Netfilter and the ip_tables, ip6_tables, arp_tables, and ebtables
kernel modules.

1.  Configure UncomplicatedFirewall

Uncomplicated Firewall (UFW) is a program for managing a netfilter firewall designed to be easy to use.
Uses a command-line interface consisting of a small number of simple
Uses iptables for configuration
Rules are processed until first matching rule. The first matching rule will be

Rules should be ordered so that ALLOW rules come before DENY rules

dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n' ufw

apt install ufw

dpkg-query -s iptables-persistent
apt purge iptables-persistent

systemctl is-enabled ufw.service
ufw status

Ensure ufw loopback traffic is configured

Configure the loopback interface to accept traffic. Configure all other interfaces to deny traffic to the loopback network ( for IPv4 and ::1/128 for IPv6).

oopback traffic is generated between processes on machine and is typically critical to operation of the system. The loopback interface is the only place that loopback network ( for IPv4 and ::1/128 for IPv6) traffic should be seen, all other interfaces should ignore traffic on this network as an anti-spoofing measure.

ufw status verbose

# ufw allow in on lo
# ufw allow out on lo
# ufw deny in from
# ufw deny in from ::1

Ensure ufw outbound connections are configured

If rules are not in place for new outbound connections all packets will be dropped by the default policy preventing network usage.

ufw allow out on all

Ensure ufw firewall rules exist for all open ports

#!/usr/bin/env bash
ufw_out="$(ufw status verbose)"
ss -tuln | awk '($5!~/%lo:/ && $5!~/ && $5!~/::1/) {split($5, a,
":"); print a[2]}' | sort | uniq | while read -r lpn; do
! grep -Pq "^\h*$lpn\b" <<< "$ufw_out" && echo "- Port: \"$lpn\" is
missing a firewall rule"

ufw allow in <port>/<tcp or udp protocol>

Ensure ufw default deny firewall policy 

ufw allow git
ufw allow in http
ufw allow out http <- required for apt to connect to repository
ufw allow in https
ufw allow out https
ufw allow out 53
ufw logging on

ufw status verbose | grep Default:

# ufw default deny incoming
# ufw default deny outgoing
# ufw default deny routed

2.  Configure nftables

nftables is a subsystem of the Linux kernel providing filtering and classification ofnetwork packets/datagrams/frames and is the successor to iptables. The biggestchange with the successor nftables is its simplicity. With iptables, we have to configureevery single rule and use the syntax which can be compared with normal commands.With nftables, the simpler syntax, much like BPF (Berkely Packet Filter) means shorterlines and less repetition. Support for nftables should also be compiled into the kernel,together with the related nftables modules. Please ensure that your kernel supportsnf_tables before choosing this option.


#!/sbin/nft -f
# This nftables.rules config should be saved as /etc/nftables.rules
# flush nftables rulesset
flush ruleset
# Load nftables ruleset
# nftables config with inet table named filter

nft -f /etc/nftables.rules

All changes in the nftables subsections are temporary.
To make these changes permanent:
Run the following command to create the nftables.rules file

nft list ruleset > /etc/nftables.rules
Add the following line to /etc/nftables.conf
include "/etc/nftables.rules"

Ensure nftables is installed
dpkg-query -s nftables | grep 'Status: install ok installed'

apt install nftables

apt purge ufw
ufw disable 

Ensure iptables are flushed with nftables

nftables is a replacement for iptables, ip6tables, ebtables and arptables

It is possible to mix iptables and nftables. However, this increases complexity and also the chance to introduce errors. For simplicity flush out all iptables rules, and ensure it is not loaded

iptables -L
ip6tables -L

No rules should be returned

iptables -F
ip6tables -F
Ensure a nftables table exists 
Tables hold chains. Each table only has one address family and only applies to packets of this family. Tables can have one of five families.

nftables doesn't have any default tables. Without a table being build, nftables will not filter network traffic.

nft list tables

nft create table inet <table name>
nft create table inet filter

Ensure nftables base chains exist 

Chains are containers for rules. They exist in two kinds, base chains and regular chains. A base chain is an entry point for packets from the networking stack, a regular chain may be used as jump target and is used for better rule organization.

if a base chain doesn't exist with a hook for input, forward, and delete, packets that
would flow through those chains will not be touched by nftables.
nft list ruleset | grep 'hook input'
nft list ruleset | grep 'hook forward'
nft list ruleset | grep 'hook output'
nft create chain inet <table name> <base chain name> { type filter hook
<(input|forward|output)> priority 0 \; }
nft create chain inet filter input { type filter hook input priority 0 \; }
nft create chain inet filter forward { type filter hook forward priority 0\; }
nft create chain inet filter output { type filter hook output priority 0 \;}
Ensure nftables loopback traffic is configured 
nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept'
nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr'
 nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr'
nft add rule inet filter input iif lo accept
 nft create rule inet filter input ip saddr counter drop
nft add rule inet filter input ip6 saddr ::1 counter drop

Ensure nftables outbound and established connections are configured 

nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
# nft add rule inet filter input ip protocol tcp ct state established accept
# nft add rule inet filter input ip protocol udp ct state established accept
# nft add rule inet filter input ip protocol icmp ct state established accept
# nft add rule inet filter output ip protocol tcp ct state
new,related,established accept
# nft add rule inet filter output ip protocol udp ct state
new,related,established accept
# nft add rule inet filter output ip protocol icmp ct state
new,related,established accept
Ensure nftables default deny firewall policy
# nft chain inet filter input { policy drop \; }
# nft chain inet filter forward { policy drop \; }
# nft chain inet filter output { policy drop \; }
Ensure nftables service is enabled
systemctl is-enabled nftables
systemctl enable nftables
Ensure nftables rules are permanent
[ -n "$(grep -E '^\s*include' /etc/nftables.conf)" ] && awk '/hook input/,/}/' $(awk '$1 ~ /^\s*include/ { gsub("\"","",$2);print $2 }' /etc/nftables.conf)
vi /etc/nftables.conf
include "/etc/nftables.rules"

3. configure iptables

iptables applies to IPv4, ip6tables to IPv6, arptables to ARP, and
ebtables to Ethernet frames.
apt install iptables iptables-persistent
apt purge nftables ufw

# iptables -P INPUT DROP
# iptables -P OUTPUT DROP
# iptables -P FORWARD DROP

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A OUTPUT -o lo -j ACCEPT
# iptables -A INPUT -s -j DROP

# iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -p udp -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
# iptables -A INPUT -p udp -m state --state ESTABLISHED -j ACCEPT
# iptables -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT

open ports determine 
ss -4tuln

iptables -L INPUT -v -n

iptables -A INPUT -p <protocol> --dport <port> -m state --state NEW -j

# ip6tables -P INPUT DROP
# ip6tables -P OUTPUT DROP
# ip6tables -P FORWARD DROP

# ip6tables -A INPUT -i lo -j ACCEPT
# ip6tables -A OUTPUT -o lo -j ACCEPT
# ip6tables -A INPUT -s ::1 -j DROP

# ip6tables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT
# ip6tables -A OUTPUT -p udp -m state --state NEW,ESTABLISHED -j ACCEPT
# ip6tables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED -j ACCEPT
# ip6tables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
# ip6tables -A INPUT -p udp -m state --state ESTABLISHED -j ACCEPT
# ip6tables -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT

determine open ports 
ss -6tuln

ip6tables -L INPUT -v -n

ip6tables -A INPUT -p <protocol> --dport <port> -m state --state NEW -j

4. Logging and Auditing

t is recommended that rsyslog be used for logging (with logwatch providing
summarization) and auditd be used for auditing (with aureport providing
summarization) to automatically monitor logs for intrusion attempts and other suspicious system behavior.

 4.1. Configure System Accounting (auditd)

 The Linux Auditing System operates on a set of rules that collects certain types of
system activity to facilitate incident investigation, detect unauthorized access or
modification of data. By default events will be logged to /var/log/audit/audit.log,
which can be configured in /etc/audit/auditd.conf.
The following types of audit rules can be specified:
Control rules: Configuration of the auditing system.
File system rules: Allow the auditing of access to a particular file or a directory.
Also known as file watches.
System call rules: Allow logging of system calls that any specified program
Audit rules can be set:
On the command line using the auditctl utility. These rules are not persistent
across reboots.
In /etc/audit/audit.rules. These rules have to be merged and loaded before
they are active.
 awk '/^\s*UID_MIN/{print $2}' /etc/login.defs
dpkg-query -W -f='${binary:Package}\t${Status}\t${db:Status-Status}\n'
auditd audispd-plugins

apt install auditd audispd-plugins

systemctl is-enabled auditd
systemctl is-active auditd

systemctl --now enable auditd

audit=1 kernel parameter to allow auditing processes started prior to audit

Ensure audit_backlog_limit is sufficient
In the kernel-level audit subsystem, a socket buffer queue is used to hold audit events. Whenever a new audit event is received, it is logged and prepared to be added to this queue. The kernel boot parameter audit_backlog_limit=N, with N representing the amount of messages, will ensure that a queue cannot grow beyond a certain size. If an audit event is logged which would grow the queue beyond this limit, then a failure occurs and is handled according to the system configuration
audit_backlog_limit=8192 kernel parameter

Configure Data Retention

When auditing, it is important to carefully configure the storage requirements for audit logs. By default, auditd will max out the log files at 5MB and retain only 4 copies of them. Older versions will be deleted. It is possible on a system that the 20 MBs of audit logs may fill up the system causing loss of audit data. While the recommendations here provide guidance, check your site policy for audit storage requirements.

max_log_file = <MB>

Ensure audit logs are not automatically deleted

max_log_file_action = keep_logs

Ensure system is disabled when audit logs are full

In high security contexts, the risk of detecting unauthorized access or nonrepudiation exceeds the benefit of the system's availability.

space_left_action = email
action_mail_acct = root
admin_space_left_action = halt  or single

Configure auditd rules

files ending in .riles in /etc/audit/audit.d/ 

Ensure changes to system administration scope (sudoers) is collected 
# printf "
-w /etc/sudoers -p wa -k scope
-w /etc/sudoers.d -p wa -k scope
" >> /etc/audit/rules.d/50-scope.rules
merge and reload rules
# augenrules --load
if [[ $(auditctl -s | grep "enabled") =~ "2" ]]; then printf "Reboot
required to load rules\n"; fi
Ensure actions as another user are always logged
# printf "
-a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k
-a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S execve -k
" >> /etc/audit/rules.d/50-user_emulation.rules
# augenrules --load
# if [[ $(auditctl -s | grep "enabled") =~ "2" ]]; then printf "Reboot
required to load rules\n"; fi
man 7 audit.rules
Ensure events that modify the sudo log file are collected
# {
SUDO_LOG_FILE=$(grep -r logfile /etc/sudoers* | sed -e 's/.*logfile=//;s/,?
.*//' -e 's/"//g')
[ -n "${SUDO_LOG_FILE}" ] && printf "
-w ${SUDO_LOG_FILE} -p wa -k sudo_log_file
" >> /etc/audit/rules.d/50-sudo.rules || printf "ERROR: Variable
'SUDO_LOG_FILE_ESCAPED' is unset.\n"
Ensure events that modify date and time information are collected 

# printf "
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-
-a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -k time-
-w /etc/localtime -p wa -k time-change
" >> /etc/audit/rules.d/50-time-change.rules

Ensure events that modify the system's network environment are collected
# printf "
-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale
-a always,exit -F arch=b32 -S sethostname,setdomainname -k system-locale
-w /etc/issue -p wa -k system-locale
-w /etc/ -p wa -k system-locale
-w /etc/hosts -p wa -k system-locale
-w /etc/networks -p wa -k system-locale
-w /etc/network/ -p wa -k system-locale
" >> /etc/audit/rules.d/50-system_local.rules
Ensure use of privileged commands are collected
# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
for PARTITION in $(findmnt -n -l -k -it $(awk '/nodev/ { print $2 }'
/proc/filesystems | paste -sd,) | grep -Pv "noexec|nosuid" | awk '{print
$1}'); do
readarray -t DATA < <(find "${PARTITION}" -xdev -perm /6000 -type f | awk
-v UID_MIN=${UID_MIN} '{print "-a always,exit -F path=" $1 " -F perm=x -F
auid>="UID_MIN" -F auid!=unset -k privileged" }')
for ENTRY in "${DATA[@]}"; do
readarray &> /dev/null -t OLD_DATA < "${AUDIT_RULE_FILE}"
printf '%s\n' "${COMBINED_DATA[@]}" | sort -u > "${AUDIT_RULE_FILE}"
 Ensure unsuccessful file access attempts are collected
# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-
EACCES -F auid>=${UID_MIN} -F auid!=unset -k access
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-
EPERM -F auid>=${UID_MIN} -F auid!=unset -k access
-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-
EACCES -F auid>=${UID_MIN} -F auid!=unset -k access
-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-
EPERM -F auid>=${UID_MIN} -F auid!=unset -k access
" >> /etc/audit/rules.d/50-access.rules || printf "ERROR: Variable 'UID_MIN'
is unset.\n"
Ensure events that modify user/group information are collected

# printf "
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity
" >> /etc/audit/rules.d/50-identity.rules

Ensure discretionary access control permission modification events are collected

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=${UID_MIN} -F
auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F
auid>=${UID_MIN} -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=${UID_MIN} -F
auid!=unset -F key=perm_mod
-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F
auid>=${UID_MIN} -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S
setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F
auid>=${UID_MIN} -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b32 -S
setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F
auid>=${UID_MIN} -F auid!=unset -F key=perm_mod
" >> /etc/audit/rules.d/50-perm_mod.rules || printf "ERROR: Variable
'UID_MIN' is unset.\n"

Ensure successful file system mounts are collected

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F arch=b32 -S mount -F auid>=$UID_MIN -F auid!=unset -k
-a always,exit -F arch=b64 -S mount -F auid>=$UID_MIN -F auid!=unset -k
" >> /etc/audit/rules.d/50-mounts.rules || printf "ERROR: Variable 'UID_MIN'
is unset.\n"

Ensure session initiation information is collected

# printf "
-w /var/run/utmp -p wa -k session
-w /var/log/wtmp -p wa -k session
-w /var/log/btmp -p wa -k session
" >> /etc/audit/rules.d/50-session.rules

Ensure login and logout events are collected

# printf "
-w /var/log/lastlog -p wa -k logins
-w /var/run/faillock -p wa -k logins
" >> /etc/audit/rules.d/50-login.rules

Ensure file deletion events by users are collected

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F
auid>=${UID_MIN} -F auid!=unset -F key=delete
-a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F
auid>=${UID_MIN} -F auid!=unset -F key=delete
" >> /etc/audit/rules.d/50-delete.rules || printf "ERROR: Variable 'UID_MIN'
is unset.\n"

 Ensure events that modify the system's Mandatory Access Controls are collected

# printf "
-w /etc/apparmor/ -p wa -k MAC-policy
-w /etc/apparmor.d/ -p wa -k MAC-policy
" >> /etc/audit/rules.d/50-MAC-policy.rules

 Ensure successful and unsuccessful attempts to use the chcon command are recorded

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>=${UID_MIN} -F
auid!=unset -k perm_chng
" >> /etc/audit/rules.d/50-perm_chng.rules || printf "ERROR: Variable
'UID_MIN' is unset.\n"

Ensure successful and unsuccessful attempts to use the setfacl command are recorded

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>=${UID_MIN} -F
auid!=unset -k perm_chng
" >> /etc/audit/rules.d/50-perm_chng.rules || printf "ERROR: Variable
'UID_MIN' is unset.\n"

Ensure successful and unsuccessful attempts to use the chacl command are recorded

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>=${UID_MIN} -F
auid!=unset -k perm_chng
" >> /etc/audit/rules.d/50-perm_chng.rules || printf "ERROR: Variable
'UID_MIN' is unset.\n"

 Ensure successful and unsuccessful attempts to use the usermod command are recorded 

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>=${UID_MIN} -F
auid!=unset -k usermod
" >> /etc/audit/rules.d/50-usermod.rules || printf "ERROR: Variable 'UID_MIN'
is unset.\n"

Ensure kernel module loading unloading and modification is collected

# {
UID_MIN=$(awk '/^\s*UID_MIN/{print $2}' /etc/login.defs)
[ -n "${UID_MIN}" ] && printf "
-a always,exit -F arch=b64 -S
init_module,finit_module,delete_module,create_module,query_module -F
auid>=${UID_MIN} -F auid!=unset -k kernel_modules
-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>=${UID_MIN} -F
auid!=unset -k kernel_modules
" >> /etc/audit/rules.d/50-kernel_modules.rules || printf "ERROR: Variable
'UID_MIN' is unset.\n"

Ensure the audit configuration is immutable
et system audit so that audit rules cannot be modified with auditctl . Setting the flag "-e 2" forces audit to be put in immutable mode. Audit changes can only be made on system reboot.
grep -Ph -- '^\h*-e\h+2\b' /etc/audit/rules.d/*.rules | tail -1

printf -- "-e 2
" >> /etc/audit/rules.d/99-finalize.rules

Ensure the running and on disk configuration is the same

augenrules --check
/usr/sbin/augenrules: No change

augenrules --load

if [[ $(auditctl -s | grep "enabled") =~ "2" ]]; then echo "Reboot required
to load rules"; fi

Configure auditd file access

Ensure audit log files are mode 0640 or less permissive

# [ -f /etc/audit/auditd.conf ] && find "$(dirname $(awk -F "="
'/^\s*log_file/ {print $2}' /etc/audit/auditd.conf | xargs))" -type f \( ! -
perm 600 -a ! -perm 0400 -a ! -perm 0200 -a ! -perm 0000 -a ! -perm 0640 -a !
-perm 0440 -a ! -perm 0040 \) -exec chmod u-x,g-wx,o-rwx {} +

Ensure only authorized users own audit log files

# [ -f /etc/audit/auditd.conf ] && find "$(dirname $(awk -F "="
'/^\s*log_file/ {print $2}' /etc/audit/auditd.conf | xargs))" -type f ! -user
root -exec chown root {} +

Ensure only authorized groups are assigned ownership of
audit log files

# find $(dirname $(awk -F"=" '/^\s*log_file/ {print $2}'
/etc/audit/auditd.conf | xargs)) -type f \( ! -group adm -a ! -group root \)
-exec chgrp adm {} +

chgrp adm /var/log/audit/

sed -ri 's/^\s*#?\s*log_group\s*=\s*\S+(\s*#.*)?.*$/log_group = adm\1/'

systemctl restart auditd

 Ensure the audit log directory is 0750 or more restrictive

chmod g-w,o-rwx "$(dirname $(awk -F"=" '/^\s*log_file/ {print $2}'

Ensure audit configuration files are 640 or more restrictive

find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) -exec
chmod u-x,g-wx,o-rwx {} +

Ensure audit configuration files are owned by root

find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) ! -user

find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) ! -user
root -exec chown root {} +

 Ensure audit configuration files belong to group root

find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) ! -group root

find /etc/audit/ -type f \( -name '*.conf' -o -name '*.rules' \) ! -group
root -exec chgrp root {} +
  Ensure audit tools are 755 or more restrictive
chmod go-w /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace
/sbin/auditd /sbin/augenrules
Ensure audit tools are owned by root 
stat -c "%n %U" /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace
/sbin/auditd /sbin/augenrules | grep -Pv -- '^\h*\H+\h+root\h*$'
chown root /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace
/sbin/auditd /sbin/augenrules
 Ensure audit tools belong to group root 
stat -c "%n %a %U %G" /sbin/auditctl /sbin/aureport /sbin/ausearch
/sbin/autrace /sbin/auditd /sbin/augenrules | grep -Pv -- '^\h*\H+\h+([0-

chmod go-w /sbin/auditctl /sbin/aureport /sbin/ausearch /sbin/autrace
/sbin/auditd /sbin/augenrules

 Ensure cryptographic mechanisms are used to protect
the integrity of audit tools

grep -Ps -- '(\/sbin\/(audit|au)\H*\b)' /etc/aide/aide.conf.d/*.conf

/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512

etc/aide/aide.conf.d/ or to /etc/aide/aide.conf to protect the integrity of the audit

# Audit Tools
/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512

4.2.Configure Logging

Logging services should be configured to prevent information leaks and to aggregate
logs on a remote server so that they can be reviewed in the event of a system
compromise. A centralized log server provides a single point of entry for further
analysis, monitoring and filtering.
Security principals for logging
Ensure transport layer security is implemented between the client and the log
Ensure that logs are rotated as per the environment requirements.
Ensure all locally generated logs have the appropriate permissions.
Ensure all security logs are sent to a remote log server.
Ensure the required events are logged.
What is covered
This section will cover the minimum best practices for the usage of either rsyslog or journald. The recommendations are written such that each is wholly independent of each other and only one is implemented.
Configure journald
Included in the systemd suite is a journaling service called systemd-journald.service
for the collection and storage of logging data. It creates and maintains structured,
indexed journals based on logging information that is received from a variety of sources such as:
  • Classic RFC3164 BSD syslog via the /dev/log socket
  •  STDOUT/STDERR of programs via StandardOutput=journal +StandardError= journal in service files (both of which are default settings)
  • Kernel log messages via the /dev/kmsg device node
  •  Audit records via the kernel’s audit subsystem
  •  Structured log messages via journald’s native protocol
Any changes made to the systemd-journald configuration will require a re-start of
Ensure journald is configured to send logs to a remote log host
apt install systemd-journal-remote
systemctl restart systemd-journal-upload
 Ensure journald is not configured to recieve logs from a
remote client
systemctl is-enabled systemd-journal-remote.socket
systemctl --now disable systemd-journal-remote.socket
Ensure journald service is enabled 
systemctl is-enabled systemd-journald.service
 Ensure journald is configured to compress large log files
 Ensure journald is configured to write logfiles to persistent
Ensure journald is not configured to send logs to rsyslog
grep ^\s*ForwardToSyslog /etc/systemd/journald.conf
Ensure journald log rotation is configured per site policy
man 5 journald.conf 
Ensure journald default file permissions configured
First see if there is an override file /etc/tmpfiles.d/systemd.conf. If so, this file will
override all default settings as defined in /usr/lib/tmpfiles.d/systemd.conf and
should be inspected.
If there is no override file, inspect the default /usr/lib/tmpfiles.d/systemd.conf
against the site specific requirements.
Ensure that file permissions are 0640.
Should a site policy dictate less restrictive permissions, ensure to follow said policy.
NOTE: More restrictive permissions such as 0600 is implicitly sufficient.
 copy /usr/lib/tmpfiles.d/systemd.conf to /etc/tmpfiles.d/systemd.conf and modify as
required. Requirements is either 0640 or site policy if that is less restrictive

man 5 tmpfiles.d

configure rsyslog

sudo apt install rsyslog


 /etc/rsyslog.conf or a dedicated .conf file in /etc/rsyslog.d/ and set
$FileCreateMode to 0640 or more restrictive:
/etc/rsyslog.conf and /etc/rsyslog.d/*.conf files as
appropriate for your environment.
*.emerg :omusrmsg:*
auth,authpriv.* /var/log/secure
mail.* -/var/log/mail -/var/log/
mail.warning -/var/log/mail.warn
mail.err /var/log/mail.err
cron.* /var/log/cron
*.=warning;*.=err -/var/log/warn
*.crit /var/log/warn
*.*;mail.none;news.none -/var/log/messages
local0,local1.* -/var/log/localmessages
local2,local3.* -/var/log/localmessages
local4,local5.* -/var/log/localmessages
local6,local7.* -/var/log/localmessages
systemctl restart rsyslog
Edit the /etc/rsyslog.conf and /etc/rsyslog.d/*.conf files and add the following line (where is the name of your central log host). The target directive may either be a fully qualified domain name or an IP address.
*.* action(type="omfwd" target="" port="514" protocol="tcp"
queue.type="LinkedList" queue.size="1000")
/etc/rsyslog.conf or /etc/rsyslog.d/*.conf.
Old format
$ModLoad imtcp
New format
input(type="imtcp" port="514")
Configure time-based job schedulers
cron is a time-based job scheduler used to schedule jobs, commands or shell scripts, to
run periodically at fixed times, dates, or intervals.
at provides the ability to execute a command or shell script at a specified date and
hour, or after a given interval of time.
 Other methods exist for scheduling jobs, such as systemd timers. If another
method is used, it should be secured in accordance with local site policy
 systemd timers are systemd unit files whose name ends in .timer that control
.service files or events
  • Timers can be used as an alternative to cron and at
  • Timers have built-in support for calendar time events, monotonic time
events, and can be run asynchronously
 If cron and at are not installed, this section can be skipped

 5.2 Configure SSH Server

SSH is a secure, encrypted replacement for common login services such as telnet, ftp, rlogin, rsh, and rcp. It is strongly recommended that sites abandon older clear- text login protocols and use SSH to prevent session hijacking and sniffing of sensitive data off the network
 apt purge openssh-server
 Ensure permissions on /etc/ssh/sshd_config

# chown root:root /etc/ssh/sshd_config
# chmod og-rwx /etc/ssh/sshd_config

Ensure permissions on SSH private host key files are

Ensure permissions on SSH public host key files are

find /etc/ssh -xdev -type f -name 'ssh_host_*' -exec chmod u-x,go-
wx {} \;
# find /etc/ssh -xdev -type f -name 'ssh_host_*' -exec chown
root:root {} \;

Ensure SSH access is limited

AllowUsers <userlist>
AllowGroups <grouplist>
DenyUsers <userlist>
DenyGroups <grouplist>

 Ensure SSH LogLevel is appropriate


LogLevel INFO

Ensure SSH PAM is enabled 

The UsePAM directive enables the Pluggable Authentication Module (PAM) interface. Ifset to yes this will enable PAM authentication using ChallengeResponseAuthenticationand PasswordAuthentication directives in addition to PAM account and session moduleprocessing for all authentication types.
When usePAM is set to yes, PAM runs through account and session types properly. Thisis important if you want to restrict access to services based off of IP, time or otherfactors of the account. Additionally, you can make sure users inherit certainenvironment variables on login or disallow access to the server

UsePAM yes

PermitRootLogin no

Ensure SSH HostbasedAuthentication is disabled

HostbasedAuthentication no

Ensure SSH PermitEmptyPasswords is disabled

PermitEmptyPasswords no

 Ensure SSH PermitUserEnvironment is disabled
PermitUserEnvironment n

Ensure SSH IgnoreRhosts is enabled
IgnoreRhosts yes

Ensure SSH X11 forwarding is disabled 
x11forwarding no

 Ensure only strong Ciphers are used 
The only "strong" ciphers currently FIPS 140-2 compliant are:

Ciphers [email protected],[email protected],aes128-
[email protected],aes256-ctr,aes192-ctr,aes128-ctr


Ensure only strong MAC algorithms are used 

This variable limits the types of MAC algorithms that SSH can use during
 Some organizations may have stricter requirements for approved MACs.
 Ensure that MACs used are in compliance with site policy.
 The only "strong" MACs currently FIPS 140-2 approved are:
MACs [email protected],[email protected],hmac-sha2-512,hmac-sha2-256

Ensure only strong Key Exchange algorithms are used
The only Key Exchange Algorithms currently FIPS 140-2 approved are:
o ecdh-sha2-nistp256
o ecdh-sha2-nistp384
o ecdh-sha2-nistp521
o diffie-hellman-group-exchange-sha256
o diffie-hellman-group16-sha512
o diffie-hellman-group18-sha512
o diffie-hellman-group14-sha256

Key exchange is any method in cryptography by which cryptographic keys are exchanged between two parties, allowing use of a cryptographic algorithm. If the sender and receiver wish to exchange encrypted messages, each must be equipped to encrypt messages to be sent and decrypt messages received

KexAlgorithms curve25519-sha256,[email protected],diffie-hellman-

Ensure SSH AllowTcpForwarding is disabled 

AllowTcpForwarding no

Ensure SSH warning banner is configured

Banner /etc/

Ensure SSH MaxAuthTries is set to 4 or less

MaxAuthTries 4

 Ensure SSH MaxStartups is configured
The MaxStartups parameter specifies the maximum number of concurrent
unauthenticated connections to the SSH daemon

MaxStartups 10:30:60
Ensure SSH MaxSessions is set to 10 or less 
MaxSessions 10
Ensure SSH LoginGraceTime is set to one minute or less
LoginGraceTime 60
Ensure SSH Idle Timeout Interval is configured
ClientAliveInterval 15
ClientAliveCountMax 3

5.3.Configure privilege escalation

The invoking user's real (not effective) user ID is used to determine the user name withwhich to query the security policy.sudo supports a plug-in architecture for security policies and input/output logging. Thirdparties can develop and distribute their own policy and I/O logging plug-ins to workseamlessly with the sudo front end. The default security policy is sudoers, which isconfigured via the file /etc/sudoers and any entries in /etc/sudoers.d.
pkexec documentation
pkexec allows an authorized user to execute PROGRAM as another user. If usernameis not specified, then the program will be executed as the administrative super user,root.
First determine is LDAP functionality is required. If so, then install sudo-ldap, else install sudo.

Edit the file /etc/sudoers with visudo or a file in /etc/sudoers.d/ with visudo -f <PATH TO FILE> and add the following line:
Defaults use_pty

Ensure sudo log file exists

Defaults logfile="/var/log/sudo.log"

Ensure users must provide password for privilege escalation

grep -r "^[^#].*NOPASSWD" /etc/sudoers*

 Ensure re-authentication for privilege escalation is not
disabled globally

grep -r "^[^#].*\!authenticate" /etc/sudoers*

Remove any occurrences of !authenticate tags in the file(s).

Ensure sudo authentication timeout is configured correctly

Defaults env_reset, timestamp_timeout=15
Defaults timestamp_timeout=15
Defaults env_reset

Ensure access to the su command is restricted 

groupadd sugroup
Add the following line to the /etc/pam.d/su file, specifying the empty group:
auth required use_uid group=sugroup

5.4. configure PAM

PAM (Pluggable Authentication Modules) is a service that implements modular
authentication modules on UNIX systems. PAM is implemented as a set of shared
objects that are loaded and executed when a program needs to authenticate a user.
Files for PAM are typically located in the /etc/pam.d directory. PAM must be carefully
configured to secure system authentication. While this section covers some of PAM,
please consult other PAM resources to fully understand the configuration capabilities.
Note: The usage of pam-auth-update:
 As of this writing, the management of PAM via pam-auth-update does not offer all
the required functionality implemented by the benchmark. As such, the usage of
pam-auth-update is not recommended at present.

Ensure password creation requirements are configured

The module checks the strength of passwords. It performs checks such as making sure a password is not a dictionary word, it is a certain length, contains a mix of characters (e.g. alphabet, numeric, other) and more.
The following options are set in the /etc/security/pwquality.conf file:
Password Length:
minlen = 14 - password must be 14 characters or more
Password complexity:
minclass = 4 - The minimum number of required classes of characters for
the new password (digits, uppercase, lowercase, others)
dcredit = -1 - provide at least one digit
ucredit = -1 - provide at least one uppercase character
ocredit = -1 - provide at least one special character
lcredit = -1 - provide at least one lowercase character

apt install libpam-pwquality

minlen = 14
minclass = 4
dcredit = -1
ucredit = -1
ocredit = -1
lcredit = -1

NOTE: As of this writing it is not possible to customize the maximum number of retriesfor the creation of a password within recommended methods. The command pam-auth-update is used to manage certain PAM configurations via profiles, such as/etc/pam.d/common-password. Making a manual change to this file will cause pam-auth-update to overwrite it on the next run and is thus against recommendations.Alternatively, pam_pwquality (via /etc/security/pwquality.conf) fully supports theconfiguration of the maximum number of retries for a password change with theconfiguration entry retry = XXX. The issue is that the template /usr/share/pam-configs/pwquality contains retry=3 which will override any retry setting in/etc/security/pwquality.conf as PAM entries takes precedence. This template fileshould not be modified as any package update will overwrite the change. Thus it is notpossible, in any recommended way, to modify password retries.

Ensure lockout for failed password attempts is configured

grep "" /etc/pam.d/common-auth
grep "" /etc/pam.d/common-account

Edit /etc/security/faillock.conf
deny = 4
fail_interval = 900
unlock time = 600

If a user has been locked out because they have reached the maximum consecutive failure count defined by deny= in the module, the user can be unlocked by issuing the command /usr/sbin/faillock --user username --reset. This command sets the failed count to 0, effectively unlocking the user.

Ensure password reuse is limited

Edit the /etc/pam.d/common-password file to include the remember= option of 5 or more

password required use_authtok remember=5

Ensure password hashing algorithm is up to date with the
latest standards

/etc/pam.d/common-password file and ensure that no hashing algorithm option
for is set:

password [success=1 default=ignore] obscure use_authtok
try_first_pass remember=5

Edit /etc/login.defs and ensure that ENCRYPT_METHOD is set to yescrypt.

grep -i "^\s*ENCRYPT_METHOD\s*yescrypt\s*$" /etc/login.defs

 Ensure all current passwords uses the configured hashing

5.5. User Accounts and Environment

 Set Shadow Password Suite Parameters

While a majority of the password control parameters have been moved to PAM, some parameters are still available through the shadow password suite. Any changes made to /etc/login.defs will only be applied if the usermod command is used. If user IDs are added a different way, use the chage command to effect changes to individual user IDs.

Ensure minimum days between password changes is


Ensure password expiration is 365 days or less


Ensure password expiration warning days is 7 or more


Ensure inactive password lock is 30 days or less

useradd -D | grep INACTIVE

awk -F: '(/^[^:]+:[^!*]/ && ($7~/(\\s*$|-1)/ || $7>30)){print $1 " " $7}'

useradd -D -f 30

chage --inactive 30 <user>

Ensure all users last password change date is in the past

awk -F: '/^[^:]+:[^!*]/{print $1}' /etc/shadow | while read -r usr; \
do change=$(date -d "$(chage --list $usr | grep '^Last password change' | cut
-d: -f2 | grep -v 'never$')" +%s); \
if [[ "$change" -gt "$(date +%s)" ]]; then \
echo "User: \"$usr\" last password change was \"$(chage --list $usr | grep
'^Last password change' | cut -d: -f2)\""; fi; done

Ensure system accounts are secured

# awk -F: '$1!~/(root|sync|shutdown|halt|^\+)/ && $3<'"$(awk
'/^\s*UID_MIN/{print $2}' /etc/login.defs)"' &&
$7!~/((\/usr)?\/sbin\/nologin)/ && $7!~/(\/bin)?\/false/ {print}' /etc/passwd

# awk -F: '($1!~/(root|^\+)/ && $3<'"$(awk '/^\s*UID_MIN/{print $2}'
/etc/login.defs)"') {print $1}' /etc/passwd | xargs -I '{}' passwd -S '{}' |
awk '($2!~/LK?/) {print $1}'

usermod -s $(which nologin) <user>
usermod -L <user>

awk -F: '$1!~/(root|sync|shutdown|halt|^\+)/ && $3<'"$(awk
'/^\s*UID_MIN/{print $2}' /etc/login.defs)"' &&
$7!~/((\/usr)?\/sbin\/nologin)/ && $7!~/(\/bin)?\/false/ {print $1}'
/etc/passwd | while read -r user; do usermod -s "$(which nologin)" "$user";

awk -F: '($1!~/(root|^\+)/ && $3<'"$(awk '/^\s*UID_MIN/{print $2}'
/etc/login.defs)"') {print $1}' /etc/passwd | xargs -I '{}' passwd -S '{}' |
awk '($2!~/LK?/) {print $1}' | while read -r user; do usermod -L "$user";

 Ensure default group for the root account is GID 0

grep "^root:" /etc/passwd | cut -f4 -d:

usermod -g 0 root

Ensure default user umask is 027 or more restrictive

The user file-creation mode mask (umask) is use to determine the file permission for newly created directories and files. In Linux, the default permissions for any newly created directory is 0777 (rwxrwxrwx), and for any newly created file it is 0666 (rw-rw- rw-). The umask modifies the default Linux permissions by restricting (masking) these permissions. The umask is not simply subtracted, but is processed bitwise. Bits set in the umask are cleared in the resulting file mode.

umask can be set with either octal or Symbolic values

 Octal (Numeric) Value - Represented by either three or four digits. ie umask 0027
or umask 027. If a four digit umask is used, the first digit is ignored. The remaining
three digits effect the resulting permissions for user, group, and world/other
 Symbolic Value - Represented by a comma separated list for User u, group g,
and world/other o. The permissions listed are not masked by umask. ie a umask
set by umask u=rwx,g=rx,o= is the Symbolic equivalent of the Octal umask 027.
This umask would set a newly created directory with file mode drwxr-x--- and a
newly created file with file mode rw-r-----.
Setting the default umask:
 pam_umask module:
o will set the umask according to the system default in /etc/login.defs and
user settings, solving the problem of different umask settings with different
shells, display managers, remote sessions etc.
o umask=<mask> value in the /etc/login.defs file is interpreted as Octal
o Setting USERGROUPS_ENAB to yes in /etc/login.defs (default):
 will enable setting of the umask group bits to be the same as owner
bits. (examples: 022 -> 002, 077 -> 007) for non-root users, if the
uid is the same as gid, and username is the same as the primary
group name
 userdel will remove the user's group if it contains no more
members, and useradd will create by default a group with the name
of the user

System Wide Shell Configuration File:
o /etc/profile - used to set system wide environmental variables on users
shells. The variables are sometimes the same ones that are in the
.profile, however this file is used to set an initial PATH or PS1 for all
shell users of the system. is only executed for interactive login shells, or
shells executed with the --login parameter
o /etc/profile.d - /etc/profile will execute the scripts within
/etc/profile.d/*.sh. It is recommended to place your configuration in a
shell script within /etc/profile.d to set your own system wide
environmental variables.
o /etc/bash.bashrc - System wide version of .bashrc. etc/bashrc also
invokes /etc/profile.d/*.sh if non-login shell, but redirects output to
/dev/null if non-interactive. Is only executed for interactive shells or
if BASH_ENV is set to /etc/bash.bashrc

User Shell Configuration Files
 ~/.profile - Is executed to configure your shell before the initial command
prompt. Is only read by login shells
 ~/.bashrc - Is executed for interactive shells. only read by a shell that's both
interactive and non-login

etting a very secure default value for umask ensures that users make a conscious
choice about their file permissions. A default umask setting of 077 causes files and
directories created by users to not be readable by any other user on the system. A
umask of 027 would make files and directories readable by users in the same Unix group, while a umask of 022 would make files readable by every user on the system.

Setting USERGROUPS_ENAB no in /etc/login.defs may change the expected behavior of
useradd and userdel.
Setting USERGROUPS_ENAB yes in /etc/login.defs
userdel will remove the user's group if it contains no more members
useradd will create by default a group with the name of the user

grep -RPi '(^|^[^#]*)\s*umask\s+([0-7][0-7][01][0-7]\b|[0-7][0-7][0-7][0-
,o=[rwx]{0,3})?\b)' /etc/login.defs /etc/profile* /etc/bash.bashrc*


session optional

Configure umask in one of the following files:
A file in the /etc/profile.d/ directory ending in .sh
Example: /etc/profile.d/
umask 027

this method only applies to bash and shell. If other shells are supported on the
system, it is recommended that their configuration files also are checked.

Ensure default user shell timeout is 900 seconds or less

TMOUT is an environmental setting that determines the timeout of a shell in seconds.

readonly TMOUT=900 ; export TMOUT

6. System Maintenance

6.1 System File Permissions

 Ensure permissions on /etc/passwd are configured
stat -Lc "%n %a %u/%U %g/%G" /etc/passwd

# chmod u-x,go-wx /etc/passwd
# chown root:root /etc/passwd

Ensure permissions on /etc/passwd- are configured

# chmod u-x,go-wx /etc/passwd-
# chown root:root /etc/passwd-

 Ensure permissions on /etc/group are configured

stat -Lc "%n %a %u/%U %g/%G" /etc/group

# chmod u-x,go-wx /etc/group
# chown root:root /etc/group

Ensure permissions on /etc/group- are configured

Ensure permissions on /etc/shadow are configured

Run the following command to verify /etc/shadow is mode 640 or more restrictive, Uid is
0/root and Gid is 0/root

 chown root:shadow /etc/shadow
# chown root:root /etc/shadow

chmod u-x,g-wx,o-rwx /etc/shadow

 Ensure permissions on /etc/gshadow are configured

chown root:shadow /etc/gshadow
# chown root:root /etc/gshadow

chmod u-x,g-wx,o-rwx /etc/gshadow

Ensure permissions on /etc/gshadow- are configured

Ensure no world writable files exist

 df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev
-type f -perm -0002

find <partition> -xdev -type f -perm -0002

 Ensure no unowned files or directories exist 

df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev

find <partition> -xdev -nouser

Ensure no ungrouped files or directories exist 

df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev

Audit SUID executables

df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev
-type f -perm -4000

find <partition> -xdev -type f -perm -4000

Audit SGID executables

df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev
-type f -perm -2000

find <partition> -xdev -type f -perm -2000

Ensure accounts in /etc/passwd use shadowed passwords

awk -F: '($2 != "x" ) { print $1 " is not set to shadowed passwords "}'

sed -e 's/^\([a-zA-Z0-9_]*\):[^:]*:/\1:x:/' -i /etc/passwd

 Ensure /etc/shadow password fields are not empty

awk -F: '($2 == "" ) { print $1 " does not have a password "}' /etc/shadow

Ensure all groups in /etc/passwd exist in /etc/group
for i in $(cut -s -d: -f4 /etc/passwd | sort -u ); do
grep -q -P "^.*?:[^:]*:$i:" /etc/group
if [ $? -ne 0 ]; then
echo "Group $i is referenced by /etc/passwd but does not exist in

Ensure shadow group is empty

# awk -F: '($1=="shadow") {print $NF}' /etc/group
# awk -F: -v GID="$(awk -F: '($1=="shadow") {print $3}' /etc/group)"
'($4==GID) {print $1}' /etc/passwd

# sed -ri 's/(^shadow:[^:]*:[^:]*:)([^:]+$)/\1/' /etc/group

# usermod -g <primary group> <user>

Ensure no duplicate UIDs exist 

 Ensure no duplicate GIDs exist 

Ensure no duplicate user names exist

Ensure no duplicate group names exist 

Ensure root PATH Integrity 

RPCV="$(sudo -Hiu root env | grep '^PATH' | cut -d= -f2)"
echo "$RPCV" | grep -q "::" && echo "root's path contains a empty directory
echo "$RPCV" | grep -q ":$" && echo "root's path contains a trailing (:)"
for x in $(echo "$RPCV" | tr ":" " "); do
if [ -d "$x" ]; then
ls -ldH "$x" | awk '$9 == "." {print "PATH contains current working
directory (.)"}
$3 != "root" {print $9, "is not owned by root"}
substr($1,6,1) != "-" {print $9, "is group writable"}
substr($1,9,1) != "-" {print $9, "is world writable"}'
echo "$x is not a directory"
 Ensure root is the only UID 0 account

awk -F: '($3 == 0) { print $1 }' /etc/passwd

Ensure local interactive user home directories exist

Ensure local interactive users own their home directories

 Ensure local interactive user home directories are mode
750 or more restrictive

#!/usr/bin/env bash
maxperm="$( printf '%o' $(( 0777 & ~$perm_mask)) )"
valid_shells="^($( sed -rn '/^\//{s,/,\\\\/,g;p}' /etc/shells | paste -s -
d '|' - ))$"
awk -v pat="$valid_shells" -F: '$(NF) ~ pat { print $1 " " $(NF-1) }'
/etc/passwd | (while read -r user home; do
mode=$( stat -L -c '%#a' "$home" )
if [ $(( $mode & $perm_mask )) -gt 0 ]; then
echo -e "- modifying User $user home directory: \"$home\"\n-
removing excessive permissions from current mode of \"$mode\""
chmod g-w,o-rwx "$home"

Ensure no local interactive user has .netrc files

 Ensure no local interactive user has .forward files

Ensure no local interactive user has .rhosts files

Ensure local interactive user dot files are not group or
world writable

#!/usr/bin/env bash
valid_shells="^($( sed -rn '/^\//{s,/,\\\\/,g;p}' /etc/shells | paste -s -
d '|' - ))$"
awk -v pat="$valid_shells" -F: '$(NF) ~ pat { print $1 " " $(NF-1) }'
/etc/passwd | while read -r user home; do
find "$home" -type f -name '.*' | while read -r dfile; do
mode=$( stat -L -c '%#a' "$dfile" )
if [ $(( $mode & $perm_mask )) -gt 0 ]; then
echo -e "\n- Modifying User \"$user\" file: \"$dfile\"\n-
removing group and other write permissions"
chmod go-w "$dfile"

#!/usr/bin/env bash
maxperm="$( printf '%o' $(( 0777 & ~$perm_mask)) )"
valid_shells="^($( sed -rn '/^\//{s,/,\\\\/,g;p}' /etc/shells | paste -s -
d '|' - ))$"
awk -v pat="$valid_shells" -F: '$(NF) ~ pat { print $1 " " $(NF-1) }'
/etc/passwd | (while read -r user home; do
for dfile in $(find "$home" -type f -name '.*'); do
mode=$( stat -L -c '%#a' "$dfile" )
[ $(( $mode & $perm_mask )) -gt 0 ] && output="$output\n- User $user
file: \"$dfile\" is too permissive: \"$mode\" (should be: \"$maxperm\" or
more restrictive)"
if [ -n "$output" ]; then
echo -e "\n- Failed:$output"
echo -e "\n- Passed:\n- All user home dot files are mode: \"$maxperm\"
or more restrictive"

auto harden scripts


Popular posts from this blog

sxhkd volume andbrightness config for dwm on void

xbps-install  sxhkd ------------ mkdir .config/sxhkd cd .config/sxhkd nano/vim sxhkdrc -------------------------------- XF86AudioRaiseVolume         amixer -c 1 -- sset Master 2db+ XF86AudioLowerVolume         amixer -c 1 -- sset Master 2db- XF86AudioMute         amixer -c 1 -- sset Master toggle alt + shift + Escape         pkill -USR1 -x sxhkd XF86MonBrightnessUp          xbacklight -inc 20 XF86MonBrightnessDown          xbacklight -dec 20 ------------------------------------------------------------- amixer -c card_no -- sset Interface volume run alsamixer to find card no and interface names xbps-install -S git git clone xbps-install -S base-devel libX11-devel libXft-devel libXinerama-devel  vim # FREETYPEINC = ${X11INC}/freetype2 #comment for non-bsd make clean install   cp config.def.h config.h vim config.h xbps-install -S font-symbola #for emoji on statusbar support     void audio config xbps-i

download office 2021 and activate

get office from here open powershell as admin (win+x and a ) type cmd  goto insall dir 1.         cd /d %ProgramFiles(x86)%\Microsoft Office\Office16 2.           cd /d %ProgramFiles%\Microsoft Office\Office16 try 1 or 2 depending on installation  install volume license  for /f %x in ('dir /b ..\root\Licenses16\ProPlus2021VL_KMS*.xrm-ms') do cscript ospp.vbs /inslic:"..\root\Licenses16\%x" activate using kms cscript ospp.vbs /setprt:1688 cscript ospp.vbs /unpkey:6F7TH >nul cscript ospp.vbs /inpkey:FXYTK-NJJ8C-GB6DW-3DYQT-6F7TH cscript ospp.vbs / cscript ospp.vbs /act Automatic script (windefender may block it) ------------------------------------------------------------------------------------------------------------------- @echo off title Activate Microsoft Office 2021 (ALL versions) for FREE - =====================================================================================&

Hidden Wiki

Welcome to The Hidden Wiki New hidden wiki url 2015 http://zqktlwi4fecvo6ri.onion Add it to bookmarks and spread it!!! Editor's picks Bored? Pick a random page from the article index and replace one of these slots with it. The Matrix - Very nice to read. How to Exit the Matrix - Learn how to Protect yourself and your rights, online and off. Verifying PGP signatures - A short and simple how-to guide. In Praise Of Hawala - Anonymous informal value transfer system. Volunteer Here are five different things that you can help us out with. Plunder other hidden service lists for links and place them here! File the SnapBBSIndex links wherever they go. Set external links to HTTPS where available, good certificate, and same content. Care to start recording onionland's history? Check out Onionland's Museum Perform Dead Services Duties. Introduction Points - Clearnet search engine for Tor Hidden Services (allows you