2021-01-29 10:27:31 +00:00
# frozen_string_literal: true
2015-11-26 09:57:53 +00:00
#
2022-03-18 19:41:09 +00:00
# Copyright:: 2015, Patrick Muench
2015-11-26 09:57:53 +00:00
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# author: Christoph Hartmann
# author: Dominik Richter
2015-11-26 19:26:38 +00:00
# author: Patrick Muench
2015-11-26 09:57:53 +00:00
2023-11-19 00:07:22 +00:00
login_defs_umask = input ( 'login_defs_umask' , value : os . redhat? ? '077' : '027' )
2017-11-19 10:48:07 +00:00
2023-11-19 00:07:22 +00:00
login_defs_passmaxdays = input ( 'login_defs_passmaxdays' , value : '60' )
login_defs_passmindays = input ( 'login_defs_passmindays' , value : '7' )
login_defs_passwarnage = input ( 'login_defs_passwarnage' , value : '7' )
2017-11-19 10:48:07 +00:00
2017-06-26 10:17:12 +00:00
shadow_group = 'root'
2019-03-07 20:14:24 +00:00
shadow_group = 'shadow' if os . debian? || os . suse? || os . name == 'alpine'
2018-06-05 12:23:42 +00:00
container_execution = begin
2021-01-29 10:27:31 +00:00
virtualization . role == 'guest' && virtualization . system =~ / ^(lxc|docker)$ /
2022-03-18 19:41:09 +00:00
rescue NoMethodError
false
2021-01-29 10:27:31 +00:00
end
2017-11-19 10:48:07 +00:00
2022-01-12 17:12:38 +00:00
blacklist = input (
2016-12-22 09:55:31 +00:00
'blacklist' ,
2023-11-19 00:07:22 +00:00
value : suid_blacklist . default
2016-12-22 09:58:26 +00:00
)
2016-09-18 20:38:55 +00:00
2020-11-04 22:22:14 +00:00
cpuvulndir = '/sys/devices/system/cpu/vulnerabilities/'
2021-11-23 11:04:53 +00:00
# Overview of necessary mount options to be checked:
#
#---------------------------------------------------------
# Mount point nodev noexec nosuid
# /boot v v v
# /dev v v
# /dev/shm v v v
# /home v v
# /run v v
# /tmp v v v
# /var v v
# /var/log v v v
# /var/log/audit v v v
# /var/tmp v v v
#---------------------------------------------------------
2022-01-12 17:12:38 +00:00
mount_exec_blocklist = input (
2021-11-23 11:04:53 +00:00
'mount_exec_blocklist' ,
2023-11-19 00:07:22 +00:00
value : [ '/boot' , '/dev' , '/dev/shm' , '/tmp' , '/var/log' , '/var/log/audit' , '/var/tmp' ]
2021-11-23 11:04:53 +00:00
)
2022-01-12 17:12:38 +00:00
mount_suid_blocklist = input (
2021-11-23 11:04:53 +00:00
'mount_suid_blocklist' ,
2023-11-19 00:07:22 +00:00
value : [ '/boot' , '/dev' , '/dev/shm' , '/home' , '/run' , '/tmp' , '/var' , '/var/log' , '/var/log/audit' , '/var/tmp' ]
2021-11-23 11:04:53 +00:00
)
2022-01-12 17:12:38 +00:00
mount_dev_blocklist = input (
2021-11-23 11:04:53 +00:00
'mount_dev_blocklist' ,
2023-11-19 00:07:22 +00:00
value : [ '/boot' , '/dev/shm' , '/home' , '/run' , '/tmp' , '/var' , '/var/log' , '/var/log/audit' , '/var/tmp' ]
2021-11-23 11:04:53 +00:00
)
2016-02-28 15:14:23 +00:00
control 'os-01' do
2015-11-26 09:57:53 +00:00
impact 1 . 0
2015-11-26 19:26:38 +00:00
title 'Trusted hosts login'
2023-04-30 17:11:41 +00:00
desc " hosts.equiv file is a weak implementation of authentication. Disabling the hosts.equiv support helps to prevent users from subverting the system's normal access control mechanisms of the system. "
2017-07-13 18:16:28 +00:00
describe file ( '/etc/hosts.equiv' ) do
it { should_not exist }
2015-11-26 09:57:53 +00:00
end
end
2016-02-28 15:14:23 +00:00
control 'os-02' do
2015-11-26 09:57:53 +00:00
impact 1 . 0
2015-11-26 19:26:38 +00:00
title 'Check owner and permissions for /etc/shadow'
desc 'Check periodically the owner and permissions for /etc/shadow'
2015-11-26 09:57:53 +00:00
describe file ( '/etc/shadow' ) do
it { should exist }
it { should be_file }
it { should be_owned_by 'root' }
2016-12-21 18:53:32 +00:00
its ( 'group' ) { should eq shadow_group }
2015-11-26 09:57:53 +00:00
it { should_not be_executable }
it { should_not be_readable . by ( 'other' ) }
end
2017-12-27 20:05:44 +00:00
if os . redhat? || os . name == 'fedora'
2017-10-19 06:34:12 +00:00
describe file ( '/etc/shadow' ) do
it { should_not be_writable . by ( 'owner' ) }
it { should_not be_readable . by ( 'owner' ) }
end
else
describe file ( '/etc/shadow' ) do
it { should be_writable . by ( 'owner' ) }
it { should be_readable . by ( 'owner' ) }
end
end
2017-06-26 10:17:12 +00:00
if os . debian? || os . suse?
2016-12-21 18:53:32 +00:00
describe file ( '/etc/shadow' ) do
2017-06-26 10:17:12 +00:00
it { should be_readable . by ( 'group' ) }
2016-12-21 18:53:32 +00:00
end
2017-06-26 10:17:12 +00:00
else
2016-12-21 18:53:32 +00:00
describe file ( '/etc/shadow' ) do
2017-06-26 10:17:12 +00:00
it { should_not be_readable . by ( 'group' ) }
2016-12-21 18:53:32 +00:00
end
2016-09-18 20:38:55 +00:00
end
2015-11-26 09:57:53 +00:00
end
2016-02-28 15:14:23 +00:00
control 'os-03' do
2015-11-26 09:57:53 +00:00
impact 1 . 0
2015-11-26 19:26:38 +00:00
title 'Check owner and permissions for /etc/passwd'
desc 'Check periodically the owner and permissions for /etc/passwd'
2015-11-26 09:57:53 +00:00
describe file ( '/etc/passwd' ) do
it { should exist }
it { should be_file }
it { should be_owned_by 'root' }
its ( 'group' ) { should eq 'root' }
it { should_not be_executable }
it { should be_writable . by ( 'owner' ) }
it { should_not be_writable . by ( 'group' ) }
it { should_not be_writable . by ( 'other' ) }
it { should be_readable . by ( 'owner' ) }
it { should be_readable . by ( 'group' ) }
it { should be_readable . by ( 'other' ) }
end
end
2020-06-28 18:49:19 +00:00
control 'os-03b' do
impact 1 . 0
title 'Check passwords hashes in /etc/passwd'
desc 'Check periodically that /etc/passwd does not contain passwords'
describe passwd do
2020-06-30 12:14:55 +00:00
its ( 'passwords' ) { should be_in [ 'x' , '*' ] }
2020-06-28 18:49:19 +00:00
end
end
2016-02-28 15:14:23 +00:00
control 'os-04' do
2015-11-26 09:57:53 +00:00
impact 1 . 0
2015-11-26 19:26:38 +00:00
title 'Dot in PATH variable'
2021-01-25 09:06:25 +00:00
desc 'Do not include the current working directory in PATH variable. This makes it easier for an attacker to gain extensive rights by executing a Trojan program'
2015-11-26 09:57:53 +00:00
describe os_env ( 'PATH' ) do
its ( 'split' ) { should_not include ( '' ) }
its ( 'split' ) { should_not include ( '.' ) }
end
end
2016-02-28 15:14:23 +00:00
control 'os-05' do
2015-11-26 09:57:53 +00:00
impact 1 . 0
2015-11-26 19:26:38 +00:00
title 'Check login.defs'
desc 'Check owner and permissions for login.defs. Also check the configured PATH variable and umask in login.defs'
2015-11-26 09:57:53 +00:00
describe file ( '/etc/login.defs' ) do
it { should exist }
it { should be_file }
it { should be_owned_by 'root' }
its ( 'group' ) { should eq 'root' }
it { should_not be_executable }
it { should be_readable . by ( 'owner' ) }
it { should be_readable . by ( 'group' ) }
it { should be_readable . by ( 'other' ) }
end
describe login_defs do
its ( 'ENV_SUPATH' ) { should include ( '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' ) }
its ( 'ENV_PATH' ) { should include ( '/usr/local/bin:/usr/bin:/bin' ) }
2016-09-18 20:38:55 +00:00
its ( 'UMASK' ) { should include ( login_defs_umask ) }
its ( 'PASS_MAX_DAYS' ) { should eq login_defs_passmaxdays }
its ( 'PASS_MIN_DAYS' ) { should eq login_defs_passmindays }
its ( 'PASS_WARN_AGE' ) { should eq login_defs_passwarnage }
2015-11-26 09:57:53 +00:00
its ( 'LOGIN_RETRIES' ) { should eq '5' }
its ( 'LOGIN_TIMEOUT' ) { should eq '60' }
its ( 'UID_MIN' ) { should eq '1000' }
its ( 'GID_MIN' ) { should eq '1000' }
2016-09-18 20:38:55 +00:00
end
2016-12-22 09:17:32 +00:00
end
control 'os-05b' do
impact 1 . 0
title 'Check login.defs - RedHat specific'
desc 'Check owner and permissions for login.defs. Also check the configured PATH variable and umask in login.defs'
2017-05-30 10:37:27 +00:00
describe file ( '/etc/login.defs' ) do
it { should_not be_writable }
end
describe login_defs do
2017-10-19 06:34:12 +00:00
its ( 'SYS_UID_MIN' ) { should eq '201' }
2017-05-30 10:37:27 +00:00
its ( 'SYS_UID_MAX' ) { should eq '999' }
2017-10-19 06:34:12 +00:00
its ( 'SYS_GID_MIN' ) { should eq '201' }
2017-05-30 10:37:27 +00:00
its ( 'SYS_GID_MAX' ) { should eq '999' }
2015-11-26 09:57:53 +00:00
end
2017-05-30 10:37:27 +00:00
only_if { os . redhat? }
2015-11-26 09:57:53 +00:00
end
2016-02-28 15:14:23 +00:00
control 'os-06' do
2015-11-26 09:57:53 +00:00
impact 1 . 0
2015-11-26 19:26:38 +00:00
title 'Check for SUID/ SGID blacklist'
desc 'Find blacklisted SUID and SGID files to ensure that no rogue SUID and SGID files have been introduced into the system'
2015-11-26 09:57:53 +00:00
2017-11-19 10:48:07 +00:00
describe suid_check ( blacklist ) do
its ( 'diff' ) { should be_empty }
2015-11-26 09:57:53 +00:00
end
end
2016-02-28 15:14:23 +00:00
control 'os-07' do
2015-11-26 09:57:53 +00:00
impact 1 . 0
2015-11-26 19:26:38 +00:00
title 'Unique uid and gid'
desc 'Check for unique uids gids'
2015-11-26 09:57:53 +00:00
describe passwd do
its ( 'uids' ) { should_not contain_duplicates }
end
describe etc_group do
its ( 'gids' ) { should_not contain_duplicates }
end
end
2016-09-18 20:38:55 +00:00
control 'os-09' do
impact 1 . 0
title 'Check for .rhosts and .netrc file'
desc 'Find .rhosts and .netrc files - CIS Benchmark 9.2.9-10'
2017-07-13 18:16:28 +00:00
output = command ( 'find / -maxdepth 3 \( -iname .rhosts -o -iname .netrc \) -print 2>/dev/null | grep -v \'^find:\'' )
2016-09-18 20:38:55 +00:00
out = output . stdout . split ( / \ r? \ n / )
describe out do
it { should be_empty }
end
end
2017-07-01 22:58:01 +00:00
control 'os-10' do
impact 1 . 0
title 'CIS: Disable unused filesystems'
desc '1.1.1 Ensure mounting of cramfs, freevxfs, jffs2, hfs, hfsplus, squashfs, udf, FAT'
2018-02-27 15:59:07 +00:00
only_if { ! container_execution }
2018-09-04 16:13:10 +00:00
efi_dir = inspec . file ( '/sys/firmware/efi' )
2017-07-01 22:58:01 +00:00
describe file ( '/etc/modprobe.d/dev-sec.conf' ) do
its ( :content ) { should match 'install cramfs /bin/true' }
its ( :content ) { should match 'install freevxfs /bin/true' }
its ( :content ) { should match 'install jffs2 /bin/true' }
its ( :content ) { should match 'install hfs /bin/true' }
its ( :content ) { should match 'install hfsplus /bin/true' }
2022-08-06 13:08:28 +00:00
# Ubuntu Snaps need SquashFS to function
unless service ( 'snapd' ) . running?
its ( :content ) { should match 'install squashfs /bin/true' }
end
2017-07-01 22:58:01 +00:00
its ( :content ) { should match 'install udf /bin/true' }
2018-07-01 10:15:07 +00:00
# if efi is active, do not disable vfat. otherwise the system
# won't boot anymore
2018-09-04 16:13:10 +00:00
unless efi_dir . exist?
2018-07-01 10:15:07 +00:00
its ( :content ) { should match 'install vfat /bin/true' }
end
2017-07-01 22:58:01 +00:00
end
end
2017-08-22 16:23:24 +00:00
control 'os-11' do
impact 1 . 0
title 'Protect log-directory'
desc 'The log-directory /var/log should belong to root'
describe file ( '/var/log' ) do
it { should be_directory }
it { should be_owned_by 'root' }
2018-10-12 20:12:29 +00:00
its ( :group ) { should match ( / ^root|syslog$ / ) }
2017-08-22 16:23:24 +00:00
end
end
2020-11-04 22:22:14 +00:00
control 'os-12' do
impact 1 . 0
title 'Detect vulnerabilities in the cpu-vulnerability-directory'
desc 'Check for known cpu vulnerabilities described here: https://www.kernel.org/doc/html/v5.6/admin-guide/hw-vuln/index.html'
2020-12-16 20:22:48 +00:00
only_if { ! container_execution }
2020-11-04 22:22:14 +00:00
if file ( cpuvulndir ) . exist?
describe file ( cpuvulndir ) do
it { should be_directory }
end
2021-01-29 10:27:31 +00:00
loaded_files = command ( " find #{ cpuvulndir } -type f -maxdepth 1 " ) . stdout . split ( / \ n / ) . map ( & :strip ) . find_all { | vulnfiles | ! vulnfiles . empty? }
2020-11-04 22:22:14 +00:00
loaded_files . each do | vulnfile |
describe file ( vulnfile ) do
2020-11-05 08:33:37 +00:00
its ( :content ) { should_not match 'vulnerable' }
its ( :content ) { should_not match 'Vulnerable' }
2020-11-04 22:22:14 +00:00
end
end
end
end
2021-02-22 08:47:05 +00:00
control 'os-13' do
impact 1 . 0
title 'Protect cron directories and files'
desc 'The cron directories and files should belong to root.'
cron_files = [ '/etc/crontab' , '/etc/cron.hourly' , '/etc/cron.daily' , '/etc/cron.weekly' , '/etc/cron.monthly' , '/etc/cron.d' ]
cron_files . each do | cron_file |
next unless file ( cron_file ) . exist?
2021-02-22 08:52:12 +00:00
2021-02-22 08:47:05 +00:00
describe file ( cron_file ) do
it { should be_owned_by 'root' }
it { should_not be_writable . by ( 'group' ) }
it { should_not be_writable . by ( 'other' ) }
it { should_not be_readable . by ( 'group' ) }
it { should_not be_readable . by ( 'other' ) }
end
end
end
2021-11-23 11:04:53 +00:00
control 'os-14' do
impact 1 . 0
title 'Check mountpoints for noexec mount options'
desc 'Use the noexec mount options to limit attack vectors via mount points'
mount_exec_blocklist . each do | mnt_point |
next unless mount ( mnt_point ) . mounted?
describe mount ( mnt_point ) do
its ( 'options' ) { should include ( 'noexec' ) }
end
end
end
control 'os-15' do
impact 1 . 0
title 'Check mountpoints for nosuid mount options'
desc 'Use the nosuid mount options to limit attack vectors via mount points'
mount_suid_blocklist . each do | mnt_point |
next unless mount ( mnt_point ) . mounted?
describe mount ( mnt_point ) do
its ( 'options' ) { should include ( 'nosuid' ) }
end
end
end
control 'os-16' do
impact 1 . 0
title 'Check mountpoints for nodev mount options'
desc 'Use the nodev mount options to limit attack vectors via mount points'
mount_dev_blocklist . each do | mnt_point |
next unless mount ( mnt_point ) . mounted?
describe mount ( mnt_point ) do
its ( 'options' ) { should include ( 'nodev' ) }
end
end
end