ardecy 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'display'
4
+ require 'nito'
5
+
6
+ module Ardecy
7
+ module Harden
8
+ module Mountpoint
9
+ def self.exec(args)
10
+ ProcHidepid.new(args).x
11
+ puts " ===> Mountpoint Corrected." if args[:fix]
12
+ end
13
+
14
+ class MountInc
15
+ include Display
16
+ include NiTo
17
+
18
+ def initialize(args)
19
+ @res = 'FAIL'
20
+ @args = args
21
+ @tab = 2
22
+ end
23
+
24
+ def x
25
+ scan
26
+ add_group
27
+ build_args
28
+ fix
29
+ systemd_case
30
+ end
31
+
32
+ def add_group
33
+ return unless @args[:fix] && @group
34
+
35
+ has_group = group_search
36
+ unless has_group
37
+ if File.exists? '/usr/sbin/groupadd'
38
+ puts " => Group #{@group} added." if system("/usr/sbin/groupadd #{@group}")
39
+ elsif File.exists? '/usr/bin/groupadd'
40
+ puts " => Group #{@group} added." if system("/usr/bin/groupadd #{@group}")
41
+ else
42
+ puts '[-] Can\'t find command groupadd'
43
+ end
44
+ end
45
+ end
46
+
47
+ def group_search
48
+ if File.readable? '/etc/group'
49
+ etc_group = File.readlines('/etc/group')
50
+ etc_group.each { |l| return true if l =~ /#{@group}/ }
51
+ else
52
+ puts " [-] /etc/group is not readable"
53
+ end
54
+ false
55
+ end
56
+
57
+ def scan
58
+ return unless mount_match('/proc/mounts')
59
+
60
+ print " - Checking #{@name} contain " + @ensure.join(',') if @args[:audit]
61
+ res_a = []
62
+ @ensure.each do |v|
63
+ o = v.split('=')
64
+ res_a << true if @val =~ /#{o[0]}=[a-z0-9]+/
65
+ end
66
+ @res = 'OK' if res_a.length == @ensure.length
67
+
68
+ @tab ? result(@res, @tab) : result(@res) if @args[:audit]
69
+ end
70
+
71
+ def build_args
72
+ return unless @args[:fix]
73
+ return if @res =~ /OK/
74
+
75
+ v = @val.split ' '
76
+ @ensure.each do |e|
77
+ o = e.split('=')
78
+ v[3] += ",#{e}" unless v[3] =~ /#{o[0]}=[a-z0-9]+/
79
+ end
80
+ @new = v.join(' ')
81
+ end
82
+
83
+ def fix
84
+ return unless @args[:fix]
85
+ return if @res =~ /OK/
86
+
87
+ if mount_match('/etc/fstab')
88
+ edit_fstab
89
+ else
90
+ File.write('/etc/fstab', "\n#{@new}\n", mode: 'a')
91
+ end
92
+
93
+ puts "old -> " + @val
94
+ puts "new -> " + @new
95
+ puts
96
+ end
97
+
98
+ def mount_match(file)
99
+ File.readlines(file).each do |l|
100
+ if l =~ /^#{@name}/
101
+ @val = l
102
+ return true
103
+ end
104
+ end
105
+ false
106
+ end
107
+
108
+ def edit_fstab
109
+ sed(/^#{@name}/, @new, '/etc/fstab')
110
+ end
111
+
112
+ def systemd_case
113
+ end
114
+ end
115
+
116
+ class ProcHidepid < Mountpoint::MountInc
117
+ def initialize(args)
118
+ super
119
+ @name = 'proc'
120
+ @ensure = [ 'hidepid=2', 'gid=proc' ]
121
+ @group = 'proc'
122
+ end
123
+
124
+ # man logind.conf check under:
125
+ # > /etc/systemd/logind.conf.d/*.conf
126
+ # > /run/systemd/logind.conf.d/*.conf
127
+ # > /usr/lib/systemd/logind.conf.d/*.conf
128
+ def systemd_case
129
+ return unless @args[:fix]
130
+
131
+ if File.exist? '/etc/systemd/logind.conf'
132
+ create_content '/etc/systemd/logind.conf.d'
133
+ end
134
+ end
135
+
136
+ def create_content(in_dir)
137
+ content = [
138
+ '[Service]',
139
+ 'SupplementaryGroups=proc',
140
+ ''
141
+ ]
142
+ Dir.mkdir in_dir, 0700 unless Dir.exists? in_dir
143
+ File.write("#{in_dir}/hidepid.conf", content.join("\n"), mode: 'w')
144
+ puts " > Creating file #{in_dir}/hidepid.conf"
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'display'
4
+
5
+ module Ardecy
6
+ module Harden
7
+ module Perms
8
+ class DirCheck
9
+ include Display
10
+
11
+ def initialize(args)
12
+ @args = args
13
+ @res = 'OK'
14
+ @exp = 0755
15
+ @tab = 2
16
+ end
17
+
18
+ def x
19
+ scan
20
+ fix
21
+ end
22
+
23
+ def scan
24
+ return unless Dir.exist? @name
25
+
26
+ perm = File.stat(@name).mode & 07777
27
+ @line = "Permission on #{@name}"
28
+
29
+ perm_show(@line, @exp) if @args[:audit]
30
+ @res = 'FAIL' if perm > @exp
31
+ @tab ? result(@res, @tab) : result(@res) if @args[:audit]
32
+ end
33
+
34
+ def fix
35
+ return unless @args[:fix]
36
+
37
+ File.chmod @exp, @name unless @res =~ /OK/
38
+ end
39
+ end
40
+
41
+ module Directory
42
+ def self.exec(args)
43
+ Directory::Home.new(args).x
44
+ Directory::CronDaily.new(args).x
45
+ Directory::Boot.new(args).x
46
+ Directory::UsrSrc.new(args).x
47
+ Directory::LibMod.new(args).x
48
+ Directory::UsrLibMod.new(args).x
49
+ puts " ===> Permission Corrected." if args[:fix]
50
+ end
51
+
52
+ class Home < Perms::DirCheck
53
+ def initialize(args)
54
+ super
55
+ @exp = 0700
56
+ end
57
+
58
+ def x
59
+ Dir.glob('/home/*').each { |d|
60
+ @name = d
61
+ scan
62
+ fix
63
+ }
64
+ end
65
+ end
66
+
67
+ class CronDaily < Perms::DirCheck
68
+ def initialize(args)
69
+ super
70
+ @name = '/etc/cron.daily'
71
+ @exp = 0700
72
+ end
73
+ end
74
+
75
+ class Boot < Perms::DirCheck
76
+ def initialize(args)
77
+ super
78
+ @name = '/boot'
79
+ @exp = 0700
80
+ @tab = 3
81
+ end
82
+ end
83
+
84
+ class UsrSrc < Perms::DirCheck
85
+ def initialize(args)
86
+ super
87
+ @name = '/usr/src'
88
+ @exp = 0700
89
+ end
90
+ end
91
+
92
+ class LibMod < Perms::DirCheck
93
+ def initialize(args)
94
+ super
95
+ @name = '/lib/modules'
96
+ @exp = 0700
97
+ end
98
+ end
99
+
100
+ class UsrLibMod < Perms::DirCheck
101
+ def initialize(args)
102
+ super
103
+ @name = '/usr/lib/modules'
104
+ @exp = 0700
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -11,6 +11,12 @@ module Ardecy
11
11
  class SysKern
12
12
  include Display
13
13
 
14
+ def initialize(args)
15
+ @res = 'FALSE'
16
+ @args = args
17
+ @exp = '0'
18
+ end
19
+
14
20
  def scan
15
21
  kernel_show(@line, @exp) if @args[:audit]
16
22
  if File.exist? @file
@@ -23,11 +29,7 @@ module Ardecy
23
29
  else
24
30
  @res = 'NO FOUND'
25
31
  end
26
- if @tab
27
- kernel_res(@res, @tab) if @args[:audit]
28
- elsif @args[:audit]
29
- kernel_res(@res)
30
- end
32
+ @tab ? result(@res, @tab) : result(@res) if @args[:audit]
31
33
  end
32
34
 
33
35
  def fix
@@ -4,205 +4,214 @@ module Ardecy
4
4
  module Harden
5
5
  module Sysctl
6
6
  module Kernel
7
+ def self.exec(args)
8
+ Kernel::KPointer.new(args).x
9
+ Kernel::Dmesg.new(args).x
10
+ Kernel::Printk.new(args).x
11
+ Kernel::BpfDisabled.new(args).x
12
+ Kernel::BpfJitHarden.new(args).x
13
+ Kernel::LdiskAutoload.new(args).x
14
+ Kernel::UserFaultFd.new(args).x
15
+ Kernel::KExecLoadDisabled.new(args).x
16
+ Kernel::SysRQ.new(args).x
17
+ Kernel::UsernsClone.new(args).x
18
+ Kernel::MaxUserNameSpace.new(args).x
19
+ Kernel::PerfEventParanoid.new(args).x
20
+ Kernel::YamaPtrace.new(args).x
21
+ Kernel::VmMmapRndBits.new(args).x
22
+ Kernel::VmMmapRndCompatBits.new(args).x
23
+ Kernel::FsProtectedSymlinks.new(args).x
24
+ Kernel::FsProtectedHardlinks.new(args).x
25
+ Kernel::FsProtectedFifos.new(args).x
26
+ Kernel::FsProtectedRegular.new(args).x
27
+ Kernel::FsSuidDumpable.new(args).x
28
+ end
29
+
7
30
  class KPointer < Sysctl::SysKern
8
31
  def initialize(args)
9
32
  @file = '/proc/sys/kernel/kptr_restrict'
10
- @exp = '2'
11
- @res = 'FALSE'
12
33
  @line = 'kernel.kptr_restrict'
13
- @args = args
34
+ super
35
+ @exp = '2'
14
36
  end
15
37
  end
16
38
 
17
39
  class Dmesg < Sysctl::SysKern
18
40
  def initialize(args)
19
41
  @file = '/proc/sys/kernel/dmesg_restrict'
20
- @exp = '1'
21
- @res = 'FALSE'
22
42
  @line = 'kernel.dmesg_restrict'
23
- @args = args
43
+ super
44
+ @exp = '1'
24
45
  end
25
46
  end
26
47
 
27
48
  class Printk < Sysctl::SysKern
28
49
  def initialize(args)
29
50
  @file = '/proc/sys/kernel/printk'
30
- @exp = '3 3 3 3'
31
- @res = 'FALSE'
32
51
  @line = 'kernel.printk'
33
- @args = args
52
+ @tab = 6
53
+ super
54
+ @exp = '3 3 3 3'
34
55
  end
35
56
 
36
57
  def scan
37
58
  kernel_show(@line, @exp) if @args[:audit]
38
59
  value = File.read(@file).chomp
39
60
  @res = 'OK' if value =~ /3\s+3\s+3\s+3/
40
- kernel_res(@res) if @args[:audit]
61
+ result(@res) if @args[:audit]
41
62
  end
42
63
  end
43
64
 
44
65
  class BpfDisabled < Sysctl::SysKern
45
66
  def initialize(args)
46
67
  @file = '/proc/sys/kernel/unprivileged_bpf_disabled'
47
- @exp = '1'
48
- @res = 'FALSE'
49
68
  @line = 'kernel.unprivileged_bpf_disabled'
50
69
  @tab = 2
51
- @args = args
70
+ super
71
+ @exp = '1'
52
72
  end
53
73
  end
54
74
 
55
75
  class BpfJitHarden < Sysctl::SysKern
56
76
  def initialize(args)
57
77
  @file = '/proc/sys/net/core/bpf_jit_harden'
58
- @exp = '2'
59
- @res = 'FALSE'
60
78
  @line = 'net.core.bpf_jit_harden'
61
- @args = args
79
+ super
80
+ @exp = '2'
62
81
  end
63
82
  end
64
83
 
65
84
  class LdiskAutoload < Sysctl::SysKern
66
85
  def initialize(args)
67
86
  @file = '/proc/sys/dev/tty/ldisc_autoload'
68
- @exp = '0'
69
- @res = 'FALSE'
70
87
  @line = 'dev.tty.ldisc_autoload'
71
- @args = args
88
+ super
72
89
  end
73
90
  end
74
91
 
75
92
  class UserFaultFd < Sysctl::SysKern
76
93
  def initialize(args)
77
94
  @file = '/proc/sys/vm/unprivileged_userfaultfd'
78
- @exp = '0'
79
- @res = 'FALSE'
80
95
  @line = 'vm.unprivileged_userfaultfd'
81
- @args = args
82
96
  @tab = 2
97
+ super
83
98
  end
84
99
  end
85
100
 
86
101
  class KExecLoadDisabled < Sysctl::SysKern
87
102
  def initialize(args)
88
103
  @file = '/proc/sys/kernel/kexec_load_disabled'
89
- @exp = '1'
90
- @res = 'FALSE'
91
104
  @line = 'kernel.kexec_load_disabled'
92
- @args = args
105
+ super
106
+ @exp = '1'
93
107
  end
94
108
  end
95
109
 
96
110
  class SysRQ < Sysctl::SysKern
97
111
  def initialize(args)
98
112
  @file = '/proc/sys/kernel/sysrq'
99
- @exp = '0'
100
- @res = 'FALSE'
101
113
  @line = 'kernel.sysrq'
102
- @args = args
103
114
  @tab = 4
115
+ super
104
116
  end
105
117
  end
106
118
 
107
119
  class UsernsClone < Sysctl::SysKern
108
120
  def initialize(args)
109
121
  @file = '/proc/sys/kernel/unprivileged_userns_clone'
110
- @exp = '0'
111
- @res = 'FALSE'
112
122
  @line = 'unprivileged_userns_clone'
113
- @args = args
123
+ super
114
124
  end
115
125
  end
116
126
 
117
127
  class MaxUserNameSpace < Sysctl::SysKern
118
128
  def initialize(args)
119
129
  @file = '/proc/sys/user/max_user_namespaces'
120
- @exp = '0'
121
- @res = 'FALSE'
122
130
  @line = 'user.max_user_namespaces'
123
- @args = args
131
+ super
124
132
  end
125
133
  end
126
134
 
127
135
  class PerfEventParanoid < Sysctl::SysKern
128
136
  def initialize(args)
129
137
  @file = '/proc/sys/kernel/perf_event_paranoid'
130
- @exp = '3'
131
- @res = 'FALSE'
132
138
  @line = 'kernel.perf_event_paranoid'
133
- @args = args
139
+ super
140
+ @exp = '3'
134
141
  end
135
142
  end
136
143
 
137
144
  class YamaPtrace < Sysctl::SysKern
138
145
  def initialize(args)
139
146
  @file = '/proc/sys/kernel/yama/ptrace_scope'
140
- @exp = '2'
141
- @res = 'FALSE'
142
147
  @line = 'kernel.yama.ptrace_scope'
143
- @args = args
148
+ super
149
+ @exp = '2'
144
150
  end
145
151
  end
146
152
 
147
153
  class VmMmapRndBits < Sysctl::SysKern
148
154
  def initialize(args)
149
155
  @file = '/proc/sys/vm/mmap_rnd_bits'
150
- @exp = '32'
151
- @res = 'FALSE'
152
156
  @line = 'vm.mmap_rnd_bits'
153
- @args = args
154
157
  @tab = 4
158
+ super
159
+ @exp = '32'
155
160
  end
156
161
  end
157
162
 
158
163
  class VmMmapRndCompatBits < Sysctl::SysKern
159
164
  def initialize(args)
160
165
  @file = '/proc/sys/vm/mmap_rnd_compat_bits'
161
- @exp = '16'
162
- @res = 'FALSE'
163
166
  @line = 'vm.mmap_rnd_compat_bits'
164
- @args = args
167
+ super
168
+ @exp = '16'
165
169
  end
166
170
  end
167
171
 
168
172
  class FsProtectedSymlinks < Sysctl::SysKern
169
173
  def initialize(args)
170
174
  @file = '/proc/sys/fs/protected_symlinks'
171
- @exp = '1'
172
- @res = 'FALSE'
173
175
  @line = 'fs.protected_symlinks'
174
- @args = args
176
+ super
177
+ @exp = '1'
175
178
  end
176
179
  end
177
180
 
178
181
  class FsProtectedHardlinks < Sysctl::SysKern
179
182
  def initialize(args)
180
183
  @file = '/proc/sys/fs/protected_hardlinks'
181
- @exp = '1'
182
- @res = 'FALSE'
183
184
  @line = 'fs.protected_hardlinks'
184
- @args = args
185
+ super
186
+ @exp = '1'
185
187
  end
186
188
  end
187
189
 
188
190
  class FsProtectedFifos < Sysctl::SysKern
189
191
  def initialize(args)
190
192
  @file = '/proc/sys/fs/protected_fifos'
191
- @exp = '2'
192
- @res = 'FALSE'
193
193
  @line = 'fs.protected_fifos'
194
- @args = args
195
194
  @tab = 4
195
+ super
196
+ @exp = '2'
196
197
  end
197
198
  end
198
199
 
199
200
  class FsProtectedRegular < Sysctl::SysKern
200
201
  def initialize(args)
201
202
  @file = '/proc/sys/fs/protected_regular'
202
- @exp = '2'
203
- @res = 'FALSE'
204
203
  @line = 'fs.protected_regular'
205
- @args = args
204
+ super
205
+ @exp = '2'
206
+ end
207
+ end
208
+
209
+ class FsSuidDumpable < Sysctl::SysKern
210
+ def initialize(args)
211
+ @file = '/proc/sys/fs/suid_dumpable'
212
+ @line = 'fs.suid_dumpable'
213
+ super
214
+ @tab = 4
206
215
  end
207
216
  end
208
217
  end