|
| 1 | +# encoding: utf-8 |
| 2 | +# |
| 3 | +# Copyright 2015, Patrick Muench |
| 4 | +# |
| 5 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | +# you may not use this file except in compliance with the License. |
| 7 | +# You may obtain a copy of the License at |
| 8 | +# |
| 9 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +# |
| 11 | +# Unless required by applicable law or agreed to in writing, software |
| 12 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | +# See the License for the specific language governing permissions and |
| 15 | +# limitations under the License. |
| 16 | +# |
| 17 | +# author: Christoph Hartmann |
| 18 | +# author: Dominik Richter |
| 19 | +# author: Patrick Muench |
| 20 | + |
| 21 | +control '01' do |
| 22 | + impact 1.0 |
| 23 | + title 'Trusted hosts login' |
| 24 | + desc "Rhosts/hosts.equiv files are a weak implemenation of authentication. Disabling the .rhosts and hosts.equiv support helps to prevent users from subverting the system's normal access control mechanisms of the system." |
| 25 | + describe command('find / -name \'.rhosts\'') do |
| 26 | + its('stdout') { should be_empty } |
| 27 | + end |
| 28 | + describe command('find / -name \'hosts.equiv\' ') do |
| 29 | + its('stdout') { should be_empty } |
| 30 | + end |
| 31 | +end |
| 32 | + |
| 33 | +control '02' do |
| 34 | + impact 1.0 |
| 35 | + title 'Check owner and permissions for /etc/shadow' |
| 36 | + desc 'Check periodically the owner and permissions for /etc/shadow' |
| 37 | + describe file('/etc/shadow') do |
| 38 | + it { should exist } |
| 39 | + it { should be_file } |
| 40 | + it { should be_owned_by 'root' } |
| 41 | + its('group') { should eq 'root' } |
| 42 | + it { should_not be_executable } |
| 43 | + it { should be_writable.by('owner') } |
| 44 | + it { should be_readable.by('owner') } |
| 45 | + it { should_not be_readable.by('group') } |
| 46 | + it { should_not be_readable.by('other') } |
| 47 | + end |
| 48 | +end |
| 49 | + |
| 50 | +control '03' do |
| 51 | + impact 1.0 |
| 52 | + title 'Check owner and permissions for /etc/passwd' |
| 53 | + desc 'Check periodically the owner and permissions for /etc/passwd' |
| 54 | + describe file('/etc/passwd') do |
| 55 | + it { should exist } |
| 56 | + it { should be_file } |
| 57 | + it { should be_owned_by 'root' } |
| 58 | + its('group') { should eq 'root' } |
| 59 | + it { should_not be_executable } |
| 60 | + it { should be_writable.by('owner') } |
| 61 | + it { should_not be_writable.by('group') } |
| 62 | + it { should_not be_writable.by('other') } |
| 63 | + it { should be_readable.by('owner') } |
| 64 | + it { should be_readable.by('group') } |
| 65 | + it { should be_readable.by('other') } |
| 66 | + end |
| 67 | +end |
| 68 | + |
| 69 | +control '04' do |
| 70 | + impact 1.0 |
| 71 | + title 'Dot in PATH variable' |
| 72 | + desc 'Do not include the current working directory in PATH variable. This makes it easier for an attacker to gain extensive rigths by executing a Trojan program' |
| 73 | + describe os_env('PATH') do |
| 74 | + its('split') { should_not include('') } |
| 75 | + its('split') { should_not include('.') } |
| 76 | + end |
| 77 | +end |
| 78 | + |
| 79 | +control '05' do |
| 80 | + impact 1.0 |
| 81 | + title 'Check login.defs' |
| 82 | + desc 'Check owner and permissions for login.defs. Also check the configured PATH variable and umask in login.defs' |
| 83 | + describe file('/etc/login.defs') do |
| 84 | + it { should exist } |
| 85 | + it { should be_file } |
| 86 | + it { should be_owned_by 'root' } |
| 87 | + its('group') { should eq 'root' } |
| 88 | + it { should_not be_executable } |
| 89 | + it { should_not be_writable } |
| 90 | + it { should be_readable.by('owner') } |
| 91 | + it { should be_readable.by('group') } |
| 92 | + it { should be_readable.by('other') } |
| 93 | + end |
| 94 | + describe login_defs do |
| 95 | + its('ENV_SUPATH') { should include('/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin') } |
| 96 | + its('ENV_PATH') { should include('/usr/local/bin:/usr/bin:/bin') } |
| 97 | + its('UMASK') { should include('027') } |
| 98 | + its('PASS_MAX_DAYS') { should eq '60' } |
| 99 | + its('PASS_MIN_DAYS') { should eq '7' } |
| 100 | + its('PASS_WARN_AGE') { should eq '7' } |
| 101 | + its('LOGIN_RETRIES') { should eq '5' } |
| 102 | + its('LOGIN_TIMEOUT') { should eq '60' } |
| 103 | + its('UID_MIN') { should eq '1000' } |
| 104 | + its('GID_MIN') { should eq '1000' } |
| 105 | + its('SYS_UID_MIN') { should eq '100' } |
| 106 | + its('SYS_UID_MAX') { should eq '999' } |
| 107 | + its('SYS_GID_MIN') { should eq '100' } |
| 108 | + its('SYS_GID_MAX') { should eq '999' } |
| 109 | + its('ENCRYPT_METHOD') { should eq 'SHA512' } |
| 110 | + end |
| 111 | +end |
| 112 | + |
| 113 | +control '06' do |
| 114 | + impact 1.0 |
| 115 | + title 'Check for SUID/ SGID blacklist' |
| 116 | + desc 'Find blacklisted SUID and SGID files to ensure that no rogue SUID and SGID files have been introduced into the system' |
| 117 | + |
| 118 | + blacklist = [ |
| 119 | + # blacklist as provided by NSA |
| 120 | + '/usr/bin/rcp', '/usr/bin/rlogin', '/usr/bin/rsh', |
| 121 | + # sshd must not use host-based authentication (see ssh cookbook) |
| 122 | + '/usr/libexec/openssh/ssh-keysign', |
| 123 | + '/usr/lib/openssh/ssh-keysign', |
| 124 | + # misc others |
| 125 | + '/sbin/netreport', # not normally required for user |
| 126 | + '/usr/sbin/usernetctl', # modify interfaces via functional accounts |
| 127 | + # connecting to ... |
| 128 | + '/usr/sbin/userisdnctl', # no isdn... |
| 129 | + '/usr/sbin/pppd', # no ppp / dsl ... |
| 130 | + # lockfile |
| 131 | + '/usr/bin/lockfile', |
| 132 | + '/usr/bin/mail-lock', |
| 133 | + '/usr/bin/mail-unlock', |
| 134 | + '/usr/bin/mail-touchlock', |
| 135 | + '/usr/bin/dotlockfile', |
| 136 | + # need more investigation, blacklist for now |
| 137 | + '/usr/bin/arping', |
| 138 | + '/usr/sbin/arping', |
| 139 | + '/usr/sbin/uuidd', |
| 140 | + '/usr/bin/mtr', # investigate current state... |
| 141 | + '/usr/lib/evolution/camel-lock-helper-1.2', # investigate current state... |
| 142 | + '/usr/lib/pt_chown', # pseudo-tty, needed? |
| 143 | + '/usr/lib/eject/dmcrypt-get-device', |
| 144 | + '/usr/lib/mc/cons.saver' # midnight commander screensaver |
| 145 | + ] |
| 146 | + |
| 147 | + output = command('find / -perm -4000 -o -perm -2000 -type f ! -path \'/proc/*\' -print 2>/dev/null | grep -v \'^find:\'') |
| 148 | + diff = output.stdout.split(/\r?\n/) & blacklist |
| 149 | + describe diff do |
| 150 | + it { should be_empty } |
| 151 | + end |
| 152 | +end |
| 153 | + |
| 154 | +control '07' do |
| 155 | + impact 1.0 |
| 156 | + title 'Unique uid and gid' |
| 157 | + desc 'Check for unique uids gids' |
| 158 | + describe passwd do |
| 159 | + its('uids') { should_not contain_duplicates } |
| 160 | + end |
| 161 | + describe etc_group do |
| 162 | + its('gids') { should_not contain_duplicates } |
| 163 | + end |
| 164 | +end |
0 commit comments