The nosuid mount option can be used to prevent
execution of setuid programs in /home. The SUID and SGID permissions
should not be required in these user data directories.
Add the nosuid option to the fourth column of
/etc/fstab for the line which controls mounting of
/home.
warning alert:
Functionality Warning
OVAL looks for partitions whose mount point is a substring of any interactive user's home
directory and validates that noexec option is there. Because of this, there could be false
negatives when several partitions share a base substring. For example, if there is a home
directory in /var/tmp/user1 and there are partitions mounted in /var and
/var/tmp. The noexec option is only expected in /var/tmp, but OVAL will
check both.
Bash remediation uses the df command to find out the partition where the home
directory is mounted. However, if the directory doesn't exist the remediation won't be
applied.
Rationale
The presence of SUID and SGID executables should be tightly controlled. Users
should not be able to execute SUID or SGID binaries from user home directory partitions.
ISA-62443-2-1-2009, Security for Industrial Automation and Control Systems Part 2-1: Establishing an Industrial Automation and Control Systems Security Program
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-AC-6
- NIST-800-53-AC-6(1)
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-MP-7
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_nosuid
- no_reboot_needed
- name: Add nosuid Option to /home - Initialize variables
ansible.builtin.set_fact:
non_allowed_partitions:
- /
- /lib
- /opt
- /usr
- /bin
- /sbin
- /boot
- /dev
- /proc
home_directories: []
allowed_mount_point: []
fstab_mount_point_info: []
when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
and "bootc" in ansible_facts.packages ) and not ( ansible_virtualization_type
in ["docker", "lxc", "openvz", "podman", "container"] ) )
tags:
- NIST-800-53-AC-6
- NIST-800-53-AC-6(1)
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-MP-7
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_nosuid
- no_reboot_needed
- name: Add nosuid Option to /home - Get home directories from passwd
ansible.builtin.getent:
database: passwd
when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
and "bootc" in ansible_facts.packages ) and not ( ansible_virtualization_type
in ["docker", "lxc", "openvz", "podman", "container"] ) )
tags:
- NIST-800-53-AC-6
- NIST-800-53-AC-6(1)
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-MP-7
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_nosuid
- no_reboot_needed
- name: Add nosuid Option to /home - Filter home directories based on UID range
ansible.builtin.set_fact:
home_directories: '{{ home_directories + [item.data[4]] }}'
when:
- ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
and "bootc" in ansible_facts.packages ) and not ( ansible_virtualization_type
in ["docker", "lxc", "openvz", "podman", "container"] ) )
- item.data[4] is defined
- item.data[2]|int >= 1000
- item.data[2]|int != 65534
- item.data[4] not in non_allowed_partitions
with_items: '{{ ansible_facts.getent_passwd | dict2items(key_name=''user'', value_name=''data'')}}'
tags:
- NIST-800-53-AC-6
- NIST-800-53-AC-6(1)
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-MP-7
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_nosuid
- no_reboot_needed
- name: Add nosuid Option to /home - Gather mount points
ansible.builtin.setup:
filter: ansible_mounts
when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
and "bootc" in ansible_facts.packages ) and not ( ansible_virtualization_type
in ["docker", "lxc", "openvz", "podman", "container"] ) )
tags:
- NIST-800-53-AC-6
- NIST-800-53-AC-6(1)
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-MP-7
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_nosuid
- no_reboot_needed
- name: Add nosuid Option to /home - Ensure mount options for home directories
block:
- name: ' Add nosuid Option to /home - Obtain mount point using df and shell'
ansible.builtin.shell: |
df {{ item }} | awk '/^\/dev/ {print $6}'
register: df_output
with_items: '{{ home_directories }}'
- name: Add nosuid Option to /home - Set mount point for each home directory
ansible.builtin.set_fact:
allowed_mount_point: '{{ allowed_mount_point + [item.stdout_lines[0]] }}'
with_items: '{{ df_output.results }}'
when:
- item.stdout_lines is defined
- item.stdout_lines | length > 0
- item.stdout_lines[0] != ""
- name: Add nosuid Option to /home - Obtain full mount information for allowed mount
point
ansible.builtin.set_fact:
fstab_mount_point_info: '{{ fstab_mount_point_info + [ ansible_mounts | selectattr(''mount'',
''equalto'', item) | first ]}}'
with_items: '{{ allowed_mount_point }}'
when: allowed_mount_point is defined
- name: Add nosuid Option to /home - Ensure mount option nosuid is in fstab for
allowed mount point
ansible.builtin.mount:
path: '{{ item.mount }}'
src: '{{ item.device }}'
opts: '{{ item.options }},nosuid'
state: mounted
fstype: '{{ item.fstype }}'
with_items: '{{ fstab_mount_point_info }}'
when:
- allowed_mount_point is defined
- item.mount not in non_allowed_partitions
- '''nosuid'' not in item.options'
when: ( not ( "kernel" in ansible_facts.packages and "rpm-ostree" in ansible_facts.packages
and "bootc" in ansible_facts.packages ) and not ( ansible_virtualization_type
in ["docker", "lxc", "openvz", "podman", "container"] ) )
tags:
- NIST-800-53-AC-6
- NIST-800-53-AC-6(1)
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-MP-7
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_nosuid
- no_reboot_needed
Remediation - Shell Script
# Remediation is applicable only in certain platforms
if ( ! ( { rpm --quiet -q kernel ;} && { rpm --quiet -q rpm-ostree ;} && { rpm --quiet -q bootc ;} ) && ! ( [ -f /.dockerenv ] || [ -f /run/.containerenv ] ) ); then
function perform_remediation (){
mount_point_match_regexp="$(printf "^[[:space:]]*[^#].*[[:space:]]%s[[:space:]]" $1)"
# If the mount point is not in /etc/fstab, get previous mount options from /etc/mtab
if ! grep -q "$mount_point_match_regexp" /etc/fstab; then
# runtime opts without some automatic kernel/userspace-added defaults
previous_mount_opts=$(grep "$mount_point_match_regexp" /etc/mtab | head -1 | awk '{print $4}' \
| sed -E "s/(rw|defaults|seclabel|nosuid)(,|$)//g;s/,$//")
[ "$previous_mount_opts" ] && previous_mount_opts+=","
# In iso9660 filesystems mtab could describe a "blocksize" value, this should be reflected in
# fstab as "block". The next variable is to satisfy shellcheck SC2050.
fs_type=""
if [ "$fs_type" == "iso9660" ] ; then
previous_mount_opts=$(sed 's/blocksize=/block=/' <<< "$previous_mount_opts")
fi
echo " $1 defaults,${previous_mount_opts}nosuid 0 0" >> /etc/fstab
# If the mount_opt option is not already in the mount point's /etc/fstab entry, add it
elif ! grep "$mount_point_match_regexp" /etc/fstab | grep -q "nosuid"; then
previous_mount_opts=$(grep "$mount_point_match_regexp" /etc/fstab | awk '{print $4}')
sed -i "s|\(${mount_point_match_regexp}.*${previous_mount_opts}\)|\1,nosuid|" /etc/fstab
fi
if mkdir -p "$1"; then
if mountpoint -q "$1"; then
mount -o remount --target "$1"
fi
fi
}
readarray -t home_directories < \
<(awk -F':' '{if ($3>=1000 && $3!= 65534) print $6}' /etc/passwd )
for home_directory in "${home_directories[@]}"
do
if [ -d $home_directory ]; then
fstab_mount_point=$(df $home_directory | awk '/^\/dev/ {print $6}')
if ! grep -qP "^/$|^/lib$|^/opt$|^/usr$|^/bin$|^/sbin$|^/boot$|^/dev$|^/proc$" <<< $fstab_mount_point
then
perform_remediation "$fstab_mount_point"
fi
fi
done
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi