diff --git a/Rakefile b/Rakefile index 3b2f68c..6196cd9 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,4 @@ #!/usr/bin/env rake -# encoding: utf-8 require 'rake/testtask' require 'rubocop/rake_task' diff --git a/controls/os_spec.rb b/controls/os_spec.rb index 2540724..1197d34 100644 --- a/controls/os_spec.rb +++ b/controls/os_spec.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 # # Copyright 2015, Patrick Muench # @@ -18,6 +17,62 @@ # author: Dominik Richter # author: Patrick Muench +login_defs_umask = attribute('login_defs_umask', default: '027', description: 'Default umask to set in login.defs') +login_defs_passmaxdays = attribute('login_defs_passmaxdays', default: '60', description: 'Default password maxdays to set in login.defs') +login_defs_passmindays = attribute('login_defs_passmindays', default: '7', description: 'Default password mindays to set in login.defs') +login_defs_passwarnage = attribute('login_defs_passwarnage', default: '7', description: 'Default password warnage (days) to set in login.defs') +if os.redhat? + shadow_group = 'root' +elsif os.debian? + shadow_group = 'shadow' +end +blacklist = attribute( + 'blacklist', + default: [ + # blacklist as provided by NSA + '/usr/bin/rcp', '/usr/bin/rlogin', '/usr/bin/rsh', + # sshd must not use host-based authentication (see ssh cookbook) + '/usr/libexec/openssh/ssh-keysign', + '/usr/lib/openssh/ssh-keysign', + # misc others + '/sbin/netreport', # not normally required for user + '/usr/sbin/usernetctl', # modify interfaces via functional accounts + # connecting to ... + '/usr/sbin/userisdnctl', # no isdn... + '/usr/sbin/pppd', # no ppp / dsl ... + # lockfile + '/usr/bin/lockfile', + '/usr/bin/mail-lock', + '/usr/bin/mail-unlock', + '/usr/bin/mail-touchlock', + '/usr/bin/dotlockfile', + # need more investigation, blacklist for now + '/usr/bin/arping', + '/usr/sbin/arping', + '/usr/sbin/uuidd', + '/usr/bin/mtr', # investigate current state... + '/usr/lib/evolution/camel-lock-helper-1.2', # investigate current state... + '/usr/lib/pt_chown', # pseudo-tty, needed? + '/usr/lib/eject/dmcrypt-get-device', + '/usr/lib/mc/cons.saver' # midnight commander screensaver + # from Ubuntu xenial, need to investigate + # '/sbin/unix_chkpwd', + # '/sbin/pam_extrausers_chkpwd', + # '/usr/lib/x86_64-linux-gnu/utempter/utempter', + # '/usr/sbin/postdrop', + # '/usr/sbin/postqueue', + # '/usr/bin/ssh-agent', + # '/usr/bin/mlocate', + # '/usr/bin/crontab', + # '/usr/bin/screen', + # '/usr/bin/expiry', + # '/usr/bin/wall', + # '/usr/bin/chage', + # '/usr/bin/bsd-write' + ], + description: 'blacklist of suid/sgid program on system' +) + control 'os-01' do impact 1.0 title 'Trusted hosts login' @@ -38,13 +93,21 @@ control 'os-02' do it { should exist } it { should be_file } it { should be_owned_by 'root' } - its('group') { should eq 'root' } + its('group') { should eq shadow_group } it { should_not be_executable } it { should be_writable.by('owner') } it { should be_readable.by('owner') } - it { should_not be_readable.by('group') } it { should_not be_readable.by('other') } end + if os.redhat? + describe file('/etc/shadow') do + it { should_not be_readable.by('group') } + end + elsif os.debian? + describe file('/etc/shadow') do + it { should be_readable.by('group') } + end + end end control 'os-03' do @@ -86,7 +149,6 @@ control 'os-05' do it { should be_owned_by 'root' } its('group') { should eq 'root' } it { should_not be_executable } - it { should_not be_writable } it { should be_readable.by('owner') } it { should be_readable.by('group') } it { should be_readable.by('other') } @@ -94,19 +156,31 @@ control 'os-05' do 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') } - its('UMASK') { should include('027') } - its('PASS_MAX_DAYS') { should eq '60' } - its('PASS_MIN_DAYS') { should eq '7' } - its('PASS_WARN_AGE') { should eq '7' } + 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 } its('LOGIN_RETRIES') { should eq '5' } its('LOGIN_TIMEOUT') { should eq '60' } its('UID_MIN') { should eq '1000' } its('GID_MIN') { should eq '1000' } - its('SYS_UID_MIN') { should eq '100' } - its('SYS_UID_MAX') { should eq '999' } - its('SYS_GID_MIN') { should eq '100' } - its('SYS_GID_MAX') { should eq '999' } - its('ENCRYPT_METHOD') { should eq 'SHA512' } + end +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' + if os.redhat? + describe file('/etc/login.defs') do + it { should_not be_writable } + end + describe login_defs do + its('SYS_UID_MIN') { should eq '100' } + its('SYS_UID_MAX') { should eq '999' } + its('SYS_GID_MIN') { should eq '100' } + its('SYS_GID_MAX') { should eq '999' } + end end end @@ -115,36 +189,7 @@ control 'os-06' do 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' - blacklist = [ - # blacklist as provided by NSA - '/usr/bin/rcp', '/usr/bin/rlogin', '/usr/bin/rsh', - # sshd must not use host-based authentication (see ssh cookbook) - '/usr/libexec/openssh/ssh-keysign', - '/usr/lib/openssh/ssh-keysign', - # misc others - '/sbin/netreport', # not normally required for user - '/usr/sbin/usernetctl', # modify interfaces via functional accounts - # connecting to ... - '/usr/sbin/userisdnctl', # no isdn... - '/usr/sbin/pppd', # no ppp / dsl ... - # lockfile - '/usr/bin/lockfile', - '/usr/bin/mail-lock', - '/usr/bin/mail-unlock', - '/usr/bin/mail-touchlock', - '/usr/bin/dotlockfile', - # need more investigation, blacklist for now - '/usr/bin/arping', - '/usr/sbin/arping', - '/usr/sbin/uuidd', - '/usr/bin/mtr', # investigate current state... - '/usr/lib/evolution/camel-lock-helper-1.2', # investigate current state... - '/usr/lib/pt_chown', # pseudo-tty, needed? - '/usr/lib/eject/dmcrypt-get-device', - '/usr/lib/mc/cons.saver' # midnight commander screensaver - ] - - output = command('find / -perm -4000 -o -perm -2000 -type f ! -path \'/proc/*\' -print 2>/dev/null | grep -v \'^find:\'') + output = command('find / -perm -4000 -o -perm -2000 -type f ! -path \'/proc/*\' ! -path \'/var/lib/lxd/containers/*\' -print 2>/dev/null | grep -v \'^find:\'') diff = output.stdout.split(/\r?\n/) & blacklist describe diff do it { should be_empty } @@ -162,3 +207,24 @@ control 'os-07' do its('gids') { should_not contain_duplicates } end end + +control 'os-08' do + impact 1.0 + title 'Entropy' + desc 'Check system has enough entropy - greater than 1000' + describe file('/proc/sys/kernel/random/entropy_avail').content.to_i do + it { should >= 1000 } + end +end + +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' + + output = command('find / \( -iname .rhosts -o -iname .netrc \) -print 2>/dev/null | grep -v \'^find:\'') + out = output.stdout.split(/\r?\n/) + describe out do + it { should be_empty } + end +end diff --git a/controls/package_spec.rb b/controls/package_spec.rb index 70c4e8b..e3544ac 100644 --- a/controls/package_spec.rb +++ b/controls/package_spec.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 # # Copyright 2015, Patrick Muench # @@ -18,6 +17,8 @@ # author: Dominik Richter # author: Patrick Muench +val_syslog_pkg = attribute('syslog_pkg', default: 'rsyslog', description: 'syslog package to ensure present (default: rsyslog, alternative: syslog-ng...') + control 'package-01' do impact 1.0 title 'Do not run deprecated inetd or xinetd' @@ -65,3 +66,37 @@ control 'package-06' do it { should_not be_installed } end end + +control 'package-07' do + impact 1.0 + title 'Install syslog server package' + desc 'Syslog server is required to receive system and applications logs' + describe package(val_syslog_pkg) do + it { should be_installed } + end +end + +control 'package-08' do + impact 1.0 + title 'Install auditd' + desc 'auditd provides extended logging capacities on recent distribution' + describe package('auditd') do + it { should be_installed } + end + describe auditd_conf do + its('log_file') { should cmp '/var/log/audit/audit.log' } + its('log_format') { should cmp 'raw' } + its('flush') { should cmp 'INCREMENTAL' } + its('freq') { should cmp 20 } + its('num_logs') { should cmp 5 } + its('max_log_file') { should cmp 6 } + its('max_log_file_action') { should cmp 'ROTATE' } + its('space_left') { should cmp 75 } + its('action_mail_acct') { should cmp 'root' } + its('space_left_action') { should cmp 'SYSLOG' } + its('admin_space_left') { should cmp 50 } + its('admin_space_left_action') { should cmp 'SUSPEND' } + its('disk_full_action') { should cmp 'SUSPEND' } + its('disk_error_action') { should cmp 'SUSPEND' } + end +end diff --git a/controls/sysctl_spec.rb b/controls/sysctl_spec.rb index e9c2668..bd2ecaa 100644 --- a/controls/sysctl_spec.rb +++ b/controls/sysctl_spec.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 # # Copyright 2015, Patrick Muench # @@ -18,6 +17,8 @@ # author: Dominik Richter # author: Patrick Muench +sysctl_forwarding = attribute('sysctl_forwarding', default: false, description: 'Is network forwarding needed?') + control 'sysctl-01' do impact 1.0 title 'IPv4 Forwarding' @@ -28,6 +29,7 @@ control 'sysctl-01' do describe kernel_parameter('net.ipv4.conf.all.forwarding') do its(:value) { should eq 0 } end + only_if { sysctl_forwarding == false } end control 'sysctl-02' do @@ -317,11 +319,24 @@ end control 'sysctl-31' do impact 1.0 - title 'Disable Core Dumps' - desc 'Ensure that core dumps can never be made by setuid programs' + title 'Secure Core Dumps' + desc 'Ensure that core dumps can never be made by setuid programs or with fully qualified path' + describe kernel_parameter('fs.suid_dumpable') do - its(:value) { should eq 0 } + ## those are not valid. how to? + # its(:value) { should eq 0 or should eq 2 } + # its(:value) { should match /[02]/ } + # its(:value) { should match /0|2/ } + its(:value) { should eq 2 } end + # unless kernel_parameter('fs.suid_dumpable') == 2 + # describe kernel_parameter('fs.suid_dumpable') do + # its(:value) { should eq 2 } + # end + describe kernel_parameter('kernel.core_pattern') do + its(:value) { should match %r{^/.*} } + end + # end end control 'sysctl-32' do