6 - System Maintenance#
6.1 - System File Permissions#
6.1.1 - Audit package permissions#
Running dpkg --list
or apt list --installed
shows a list of all installed packages on the system.
Note: apt list --installed
likely will output too many lines to view, in the terminal,
so apt list --installed > packages.txt
will output it to a file named packages.txt
.
Running dpkg --verify PACKAGE_NAME
verifies the files in a package.
The errors it returns are:
Code Meaning
S File size differs.
M File mode differs (includes permissions and file type).
5 The MD5 checksum differs.
D The major and minor version numbers differ on a device file.
L A mismatch occurs in a link.
U The file ownership differs.
G The file group owner differs.
T The file time (mtime) differs.
Verifying all packages can reveal security vulnerabilities, but is extremely time-consuming.
6.1.2 - 6.1.9 - Configure important file permissions#
To ensure that the file permissions are set properly on important files and directories, run:
sudo chown root:root /etc/passwd
sudo chmod u-x,go-wx /etc/passwd
sudo chown root:root /etc/passwd~
sudo chmod u-x,go-wx /etc/passwd~
sudo chown root:root /etc/group
sudo chmod u-x,go-wx /etc/group
sudo chown root:root /etc/group~
sudo chmod u-x,go-wx /etc/group~
sudo chown root:root /etc/shadow
sudo chmod u-x,go-wx /etc/shadow
sudo chown root:root /etc/shadow~
sudo chmod u-x,go-wx /etc/shadow~
sudo chown root:root /etc/gshadow
sudo chmod u-x,go-wx /etc/gshadow
sudo chown root:root /etc/gshadow~
sudo chmod u-x,go-wx /etc/gshadow~
Note
To run all of these commands at once, paste them into a .sh file and run it with bash.
Ex: sudo bash script.sh
6.1.10 - Ensure no world writable files exist#
To scan for world-writable files in local directories, run:
df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -type f -perm -0002
To search on individual partitions, run:
find PARTITION_NAME -xdev -type f -perm -0002
If a world-writable file is found, remove miscellaneous write access on it by running chmod o-w FILENAME
.
6.1.11 - 6.1.12 - Check for unowned/ungrouped files#
To scan for unowned files in local directories, run:
df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -nouser
To scan for ungrouped files in local directories, run:
df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev -nogroup
To search for unowned files in individual partitions, run:
find PARTITION_NAME -xdev -nouser
To search for ungrouped files in individual partitions, run:
find PARTITION_NAME -xdev -nogroup
If any files are found, assign them an owner or group by using chown
.
See man chown
for more information.
6.1.13 - 6.1.14 - Audit SUID and SGID executables#
To scan for SUID files locally, run:
df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev
-type f -perm -4000
To scan for SGID files locally, run:
df --local -P | awk '{if (NR!=1) print $6}' | xargs -I '{}' find '{}' -xdev
-type f -perm -2000
To scan on individual partitions, run:
# SUID:
find PARTITION_NAME -xdev -type f -perm 4000
# SGID:
find PARTITION_NAME -xdev -type f -perm 2000
For files that are found, review them, and either revoke the permissions of or delete rogue files.
6.2 - User and Group Settings#
6.2.1 - 6.2.2 - Ensure password integrity#
Find accounts without shadowed passwords by running:
awk -F: '($2 != "x" ) { print $1 " is not set to shadowed passwords "}'
/etc/passwd
Set all accounts to use shadowed passwords by running:
sed -e 's/^\([a-zA-Z0-9_]*\):[^:]*:/\1:x:/' -i /etc/passwd
Search for accounts with empty passwords by running:
awk -F: '($2 == "" ) { print $1 " does not have a password "}' /etc/shadow
If an account has an empty password, change it or lock the account using the passwd
command or the user settings GUI.
6.2.3 - Ensure all groups in /etc/passwd exist in /etc/group#
Make sure that all groups in /etc/passwd
are in /etc/group
by running the following script:
#!/bin/bash
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 /etc/group"
fi
done
source <(curl -s https://raw.githubusercontent.com/CAMSCSC/CIS-Breakdown/main/scripts/6.2.3.sh)
6.2.4 - 6.2.6 - Configure home directories#
Create a home directory for users with an interactive shell without a home directory and ensure that users own their home directory by running the following script
#!/bin/bash
awk -F: '($1!~/(halt|sync|shutdown)/ && $7!~/^(\/usr)?\/sbin\/nologin(\/)?$/
&& $7!~/(\/usr)?\/bin\/false(\/)?$/) { print $1 " " $6 }' | while
read -r
user dir
do
if [ ! -d "$dir" ]; then
echo "User: \"$user\" home directory: \"$dir\" does not exist, creating
home directory"
mkdir "$dir"
chmod g-w,o-rwx "$dir"
chown "$user" "$dir"
else
owner=$(stat -L -c "%U" "$dir")
if [ "$owner" != "$user" ]; then
chmod g-w,o-rwx "$dir"
chown "$user" "$dir"
fi
fi
done
source <(curl -s https://raw.githubusercontent.com/CAMSCSC/CIS-Breakdown/main/scripts/6.2.4.sh)
Then ensure that the home directories have permissions of 750 by running the following script:
#!/bin/bash
awk -F: '($1!~/(halt|sync|shutdown)/ && $7!~/^(\/usr)?\/sbin\/nologin(\/)?$/
&& $7!~/(\/usr)?\/bin\/false(\/)?$/) {print $6}' /etc/passwd | while
read -r
dir
do
if [ -d "$dir" ]; then
dirperm=$(stat -L -c "%A" "$dir")
if [ "$(echo "$dirperm" | cut -c6)" != "-" ] || [ "$(echo "$dirperm" |
cut -c8)" != "-" ] || [ "$(echo "$dirperm" | cut -c9)" != "-" ] || [ "$(
echo
"$dirperm" | cut -c10
)" != "-" ]; then
chmod g-w,o-rwx "$dir"
fi
fi
done
source <(curl -s https://raw.githubusercontent.com/CAMSCSC/CIS-Breakdown/main/scripts/6.2.6.sh)
6.2.7 - 6.2.10 - Configure dot files#
Configure the dot files in every home directory by running the following script:
#!/bin/bash
awk -F: '($1!~/(halt|sync|shutdown)/ && $7!~/^(\/usr)?\/sbin\/nologin(\/)?$/ && $7!~/(\/usr)?\/bin\/false(\/)?$/) { print $1 " " $6 }' /etc/passwd | while read -r user dir
do
if [ -d "$dir" ]; then
for file in "$dir"/.*; do
if [ ! -h "$file" ] && [ -f "$file" ]; then
fileperm=$(stat -L -c "%A" "$file")
if [ "$(echo "$fileperm" | cut -c6)" != "-" ] || [ "$(echo "$fileperm" | cut -c9)" != "-" ]; then
echo "User: \"$user\" file: \"$file\" has permissions:\"$fileperm\""
chmod go-w "$file"
fi
fi
done
file="$dir/.netrc"
if [ ! -h "$file" ] && [ -f "$file" ]; then
rm -f "$file"
echo ".netrc file found and removed in $user\'s home directory."
fi
file="$dir/.forward"
if [ ! -h "$file" ] && [ -f "$file" ]; then
rm -r "$file"
echo ".forward file found and removed in $user\'s home directory."
fi
file="$dir/.rhosts"
if [ ! -h "$file" ] && [ -f "$file" ]; then
rm -r "$file"
echo ".rhosts file found and removed in $user\'s home directory."
fi
fi
done
source <(curl -s https://raw.githubusercontent.com/CAMSCSC/CIS-Breakdown/main/scripts/6.2.7.sh)
6.2.11 - 6.2.12 - Validate root account integrity#
Ensure that root
is the only account with UID 0 by running:
awk -F: '($3 == 0) { print $1 }' /etc/passwd
If anything other than root is returned, assign those accounts a new UID or remove them.
Check for the integrity of the root PATH by running the following script:
#!/bin/bash
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"}'
else
echo "$x is not a directory"
fi
done
source <(curl -s https://raw.githubusercontent.com/CAMSCSC/CIS-Breakdown/main/scripts/6.2.7.sh)
6.2.13 - 6.2.16 - Remove duplicate groups and users#
Check for duplicates by scanning /etc/passwd
and /etc/group
with the following script:
#!/bin/bash
cut -f3 -d":" /etc/passwd | sort -n | uniq -c | while read x; do
[ -z "$x" ] && break
set - $x
if [ $1 -gt 1 ]; then
users=$(awk -F: '($3 == n) { print $1 }' n=$2 /etc/passwd | xargs)
echo "Duplicate UID ($2): $users"
fi
done
cut -d: -f1 /etc/passwd | sort | uniq -d | while read -r x; do
echo "Duplicate login name $x in /etc/passwd"
done
cut -d: -f3 /etc/group | sort | uniq -d | while read x; do
echo "Duplicate GID ($x) in /etc/group"
done
cut -d: -f1 /etc/group | sort | uniq -d | while read -r x; do
echo "Duplicate group name $x in /etc/group"
done
source <(curl -s https://raw.githubusercontent.com/CAMSCSC/CIS-Breakdown/main/scripts/6.2.13.sh)
If any results are returned, edit /etc/passwd
or /etc/group
to fix the discrepancy.
The grpck
command can also be used to scan for other discrepancies in /etc/group
.
6.2.17 - Ensure shadow group is empty#
Ensure that no users are in the shadow group by running:
grep ^shadow:[^:]*:[^:]*:[^:]+ /etc/group
awk -F: -v GID="$(awk -F: '($1=="shadow") {print $3}' /etc/group)" '($4==GID) {print}' /etc/passwd
If any groups are returned, remove them from the shadow group.