Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding multiple passwd/group/shadow controls #165

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
104 changes: 104 additions & 0 deletions controls/os_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
login_defs_passmindays = attribute('login_defs_passmindays', value: '7', description: 'Default password mindays to set in login.defs')
login_defs_passwarnage = attribute('login_defs_passwarnage', value: '7', description: 'Default password warnage (days) to set in login.defs')

system_users = passwd.params ? passwd.params.select { |x| x['uid'].to_i < login_defs.UID_MIN.to_i && x['uid'].to_i.positive? } : []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic should be part of the control


system_users_non_login_permitlist = attribute(
'system_users_non_login_permitlist',
value: %w[sync halt shutdown],
description: 'List of system users which are allowed to log in'
)

shadow_group = 'root'
shadow_group = 'shadow' if os.debian? || os.suse? || os.name == 'alpine'
container_execution = begin
Expand Down Expand Up @@ -282,3 +290,99 @@
end
end
end

control 'os-14' do
impact 1.0
title 'All password change dates are in the past'
desc 'The password change date is used to detect expired passwords. Entering future dates might circumvent that.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to add a reference to read more about the reasoning

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The internal document I have doesn't state much more information about this rule, that I wrote here. It is based on CIS, linking to it is sadly to so easy. I could drop this rule if the other rules are ok for you?

describe shadow.where { last_change.to_i > (Date.today - Date.new(1970, 1, 1)).to_i } do
its('users') { should be_empty }
end
end

control 'os-15' do
impact 1.0
title 'All system users are non-login'
desc 'The login of system users should be disabled'
system_users.each do |user|
next if system_users_non_login_permitlist.include? user['user']

describe OpenStruct.new(user) do
its('shell') { should be_in ['/bin/false', '/sbin/nologin', '/usr/bin/false', '/usr/sbin/nologin'] }
end
end
end

control 'os-16' do
impact 1.0
title 'User \'root\' should be member of group \'root\' with gid \'0\''
desc 'This prevents root-owned files and directories to be accessible to non-privileged users'
describe passwd.uids(0) do
its('users') { should cmp 'root' }
its('gids') { should cmp 0 }
end
describe etc_group.where(gid: 0) do
its('groups') { should cmp 'root' }
its('users') { should be_empty }
end
end

control 'os-17' do
impact 1.0
title 'Prevent + or - fields in passwd an related files used by NIS'
desc 'NIS is insecure and should not be used'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A reference to the rule and reasoning for be beneficial

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule is also based on CIS, but expanded upon. Cis only mentions that passwd entries should not include +, but NIS allow allows - entries. This rule tests for both. So I don't have any reference to the exact rule. I could drop this rule as well if required.

describe file('/etc/passwd') do
its('content') { should_not match(/^[+-]/) }
end
describe file('/etc/shadow') do
its('content') { should_not match(/^[+-]/) }
end
describe file('/etc/group') do
its('content') { should_not match(/^[+-]/) }
end
end

control 'os-18' do
impact 1.0
title 'Users and groups should be unique'
desc 'In order to avoid confusion or identity theft, every group and user should be unique'
describe passwd do
its('users') { should_not contain_duplicates }
its('uids') { should_not contain_duplicates }
end
describe etc_group do
its('groups') { should_not contain_duplicates }
its('gids') { should_not contain_duplicates }
end
end

control 'os-19' do
impact 1.0
title 'Shadow group should not have any users'
desc 'Members of the shadow group could have access to password hashes, so no user should be a member of that group'
shadow_group_entry = etc_group.where(name: shadow_group)

describe passwd.gids(shadow_group_entry.gids) do
its('count') { should eq 0 }
end

describe shadow_group_entry do
its('users') { should be_empty }
end
end

control 'os-20' do
impact 1.0
title 'All users and gids referred in /etc/group and /etc/passwd should exist'
desc 'Errors in system administration can lead to a case where gids or uids referred to do not exist'

gids = etc_group.gids.map(&:to_s)
describe passwd do
its('gids') { should be_in gids }
end

users = passwd.users
describe etc_group do
its('users') { should be_in users }
end
end