ardecy 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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