Module: Msf::Post::Linux::Kernel

Includes:
Architecture, Common, File
Included in:
Wsl
Defined in:
lib/msf/core/post/linux/kernel.rb

Instance Method Summary collapse

Methods included from Architecture

#get_os_architecture

Methods included from File

#_append_file_powershell, #_append_file_unix_shell, #_can_echo?, #_read_file_meterpreter, #_read_file_powershell, #_read_file_powershell_fragment, #_shell_command_with_success_code, #_shell_process_with_success_code, #_unix_max_line_length, #_win_ansi_append_file, #_win_ansi_write_file, #_win_bin_append_file, #_win_bin_write_file, #_write_file_meterpreter, #_write_file_powershell, #_write_file_powershell_fragment, #_write_file_unix_shell, #append_file, #attributes, #cd, #chmod, #copy_file, #dir, #directory?, #executable?, #exist?, #expand_path, #exploit_data, #exploit_source, #file?, #file_local_write, #file_remote_digestmd5, #file_remote_digestsha1, #file_remote_digestsha2, #find_writable_directories, #immutable?, #initialize, #mkdir, #pwd, #read_file, #readable?, #rename_file, #rm_f, #rm_rf, #setuid?, #stat, #upload_and_chmodx, #upload_file, #writable?, #write_file

Methods included from Common

#clear_screen, #cmd_exec, #cmd_exec_get_pid, #cmd_exec_with_result, #command_exists?, #create_process, #get_env, #get_envs, #initialize, #peer, #report_virtualization, #rhost, #rport

Instance Method Details

#aslr_enabled?Boolean

Returns true if Address Space Layout Randomization (ASLR) is enabled

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



196
197
198
199
200
201
# File 'lib/msf/core/post/linux/kernel.rb', line 196

def aslr_enabled?
  aslr = read_file('/proc/sys/kernel/randomize_va_space').to_s.strip
  aslr.eql?('1') || aslr.eql?('2')
rescue StandardError
  raise 'Could not determine ASLR status'
end

#cpu_flagsArray

Returns a list of CPU flags

Returns:

  • (Array)

Raises:

  • (RuntimeError)

    If execution fails.



117
118
119
120
121
122
123
124
125
# File 'lib/msf/core/post/linux/kernel.rb', line 117

def cpu_flags
  cpuinfo = read_file('/proc/cpuinfo').to_s

  return unless cpuinfo.include? 'flags'

  cpuinfo.scan(/^flags\s*:(.*)$/).flatten.join(' ').split(/\s/).map(&:strip).reject(&:empty?).uniq
rescue StandardError
  raise 'Could not retrieve CPU flags'
end

#dmesg_restrict?Boolean

Returns true if dmesg restriction is enabled

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



247
248
249
250
251
# File 'lib/msf/core/post/linux/kernel.rb', line 247

def dmesg_restrict?
  read_file('/proc/sys/kernel/dmesg_restrict').to_s.strip.eql? '1'
rescue StandardError
  raise 'Could not determine kernel.dmesg_restrict status'
end

#exec_shield_enabled?Boolean

Returns true if Exec-Shield is enabled

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



209
210
211
212
213
214
# File 'lib/msf/core/post/linux/kernel.rb', line 209

def exec_shield_enabled?
  exec_shield = read_file('/proc/sys/kernel/exec-shield').to_s.strip
  exec_shield.eql?('1') || exec_shield.eql?('2')
rescue StandardError
  raise 'Could not determine exec-shield status'
end

#grsec_installed?Boolean

Returns true if grsecurity is installed

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



286
287
288
289
290
# File 'lib/msf/core/post/linux/kernel.rb', line 286

def grsec_installed?
  cmd_exec('test -c /dev/grsec && echo true').to_s.strip.include? 'true'
rescue StandardError
  raise 'Could not determine grsecurity status'
end

#kaiser_enabled?Boolean

Returns true if Kernel Address Isolation (KAISER) is enabled

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



157
158
159
160
161
# File 'lib/msf/core/post/linux/kernel.rb', line 157

def kaiser_enabled?
  cpu_flags.include? 'kaiser'
rescue StandardError
  raise 'Could not determine KAISER status'
end

#kernel_configArray

Returns the kernel boot config with comments removed

Returns:

  • (Array)

Raises:

  • (RuntimeError)

    If execution fails.



88
89
90
91
92
93
94
95
96
97
# File 'lib/msf/core/post/linux/kernel.rb', line 88

def kernel_config
  release = kernel_release
  output = read_file("/boot/config-#{release}").to_s.strip
  return if output.empty?

  config = output.split("\n").map(&:strip).reject(&:empty?).reject { |i| i.start_with? '#' }
  config
rescue StandardError
  raise 'Could not retrieve kernel config'
end

#kernel_hardwareString

Returns the kernel hardware

Returns:

  • (String)


76
77
78
# File 'lib/msf/core/post/linux/kernel.rb', line 76

def kernel_hardware
  uname('-m')
end

#kernel_modulesArray

Returns the kernel modules

Returns:

  • (Array)

Raises:

  • (RuntimeError)

    If execution fails.



105
106
107
108
109
# File 'lib/msf/core/post/linux/kernel.rb', line 105

def kernel_modules
  read_file('/proc/modules').to_s.scan(/^[^ ]+/)
rescue StandardError
  raise 'Could not determine kernel modules'
end

#kernel_nameString

Returns the kernel name

Returns:

  • (String)


67
68
69
# File 'lib/msf/core/post/linux/kernel.rb', line 67

def kernel_name
  uname('-s')
end

#kernel_releaseString

Returns the kernel release

Returns:

  • (String)


29
30
31
# File 'lib/msf/core/post/linux/kernel.rb', line 29

def kernel_release
  uname('-r')
end

#kernel_rex_releaseObject

Returns the kernel release information as a hashable object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/msf/core/post/linux/kernel.rb', line 36

def kernel_rex_release
  release = kernel_release

  # regex for parsing kernel release
  # (5.15.0)-(25-generic) 
  # consists of two groups - the kernel upstream version (xx.zz.yy) and distro-specific information
  # this regex should make it easier to parse it
  
  return nil unless release =~ /(\d+\.\d+\.?\d*\.?\d*)[-.]?(.+)/
  
  { 
    :upstream => Rex::Version.new(Regexp.last_match(1)),
    :distro_suffix => Regexp.last_match(2)
  }

end

#kernel_versionString

Returns the kernel version

Returns:

  • (String)


58
59
60
# File 'lib/msf/core/post/linux/kernel.rb', line 58

def kernel_version
  uname('-v')
end

#kpti_enabled?Boolean

Returns true if Kernel Page-Table Isolation (KPTI) is enabled, false if not.

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



169
170
171
172
173
# File 'lib/msf/core/post/linux/kernel.rb', line 169

def kpti_enabled?
  cpu_flags.include? 'pti'
rescue StandardError
  raise 'Could not determine KPTI status'
end

#kptr_restrict?Boolean

Returns true if kernel pointer restriction is enabled

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



235
236
237
238
239
# File 'lib/msf/core/post/linux/kernel.rb', line 235

def kptr_restrict?
  read_file('/proc/sys/kernel/kptr_restrict').to_s.strip.eql? '1'
rescue StandardError
  raise 'Could not determine kernel.kptr_restrict status'
end

#lkrg_installed?Boolean

Returns true if Linux Kernel Runtime Guard (LKRG) kernel module is installed

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



274
275
276
277
278
# File 'lib/msf/core/post/linux/kernel.rb', line 274

def lkrg_installed?
  directory?('/proc/sys/lkrg')
rescue StandardError
  raise 'Could not determine LKRG status'
end

#mmap_min_addrInteger

Returns mmap minimum address

Returns:

  • (Integer)

Raises:

  • (RuntimeError)

    If execution fails.



259
260
261
262
263
264
265
266
# File 'lib/msf/core/post/linux/kernel.rb', line 259

def mmap_min_addr
  mmap_min_addr = read_file('/proc/sys/vm/mmap_min_addr').to_s.strip
  return 0 unless mmap_min_addr =~ /\A\d+\z/

  mmap_min_addr
rescue StandardError
  raise 'Could not determine system mmap_min_addr'
end

#pax_installed?Boolean

Returns true if PaX is installed

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



298
299
300
301
302
# File 'lib/msf/core/post/linux/kernel.rb', line 298

def pax_installed?
  read_file('/proc/self/status').to_s.include? 'PaX:'
rescue StandardError
  raise 'Could not determine PaX status'
end

#selinux_enforcing?Boolean

Returns true if SELinux is in enforcing mode

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/msf/core/post/linux/kernel.rb', line 322

def selinux_enforcing?
  return false unless selinux_installed?

  sestatus = cmd_exec('/usr/sbin/sestatus').to_s.strip
  raise unless sestatus.include?('SELinux')

  return true if sestatus =~ /Current mode:\s*enforcing/

  false
rescue StandardError
  raise 'Could not determine SELinux status'
end

#selinux_installed?Boolean

Returns true if SELinux is installed

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



310
311
312
313
314
# File 'lib/msf/core/post/linux/kernel.rb', line 310

def selinux_installed?
  cmd_exec('id').to_s.include? 'context='
rescue StandardError
  raise 'Could not determine SELinux status'
end

#smap_enabled?Boolean

Returns true if kernel and hardware supports Supervisor Mode Access Prevention (SMAP), false if not.

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



133
134
135
136
137
# File 'lib/msf/core/post/linux/kernel.rb', line 133

def smap_enabled?
  cpu_flags.include? 'smap'
rescue StandardError
  raise 'Could not determine SMAP status'
end

#smep_enabled?Boolean

Returns true if kernel and hardware supports Supervisor Mode Execution Protection (SMEP), false if not.

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



145
146
147
148
149
# File 'lib/msf/core/post/linux/kernel.rb', line 145

def smep_enabled?
  cpu_flags.include? 'smep'
rescue StandardError
  raise 'Could not determine SMEP status'
end

#uname(opts = '-a') ⇒ String

Returns uname output

Parameters:

  • opt (String)

    uname options, defaults to -a

Returns:

  • (String)

Raises:

  • (RuntimeError)

    If execution fails.



18
19
20
21
22
# File 'lib/msf/core/post/linux/kernel.rb', line 18

def uname(opts = '-a')
  cmd_exec("uname #{opts}").to_s.strip
rescue StandardError
  raise "Failed to run uname #{opts}"
end

#unprivileged_bpf_disabled?Boolean

Returns true if unprivileged bpf is disabled

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



222
223
224
225
226
227
# File 'lib/msf/core/post/linux/kernel.rb', line 222

def unprivileged_bpf_disabled?
  unprivileged_bpf_disabled = read_file('/proc/sys/kernel/unprivileged_bpf_disabled').to_s.strip
  return unprivileged_bpf_disabled == '1' || unprivileged_bpf_disabled == '2'
rescue StandardError
  raise 'Could not determine kernel.unprivileged_bpf_disabled status'
end

#userns_enabled?Boolean

Returns true if user namespaces are enabled, false if not.

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



181
182
183
184
185
186
187
188
# File 'lib/msf/core/post/linux/kernel.rb', line 181

def userns_enabled?
  return false if read_file('/proc/sys/user/max_user_namespaces').to_s.strip.eql? '0'
  return false if read_file('/proc/sys/kernel/unprivileged_userns_clone').to_s.strip.eql? '0'

  true
rescue StandardError
  raise 'Could not determine userns status'
end

#yama_enabled?Boolean

Returns true if Yama is enabled

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



376
377
378
379
380
# File 'lib/msf/core/post/linux/kernel.rb', line 376

def yama_enabled?
  yama_ptrace_scope > 0
rescue StandardError
  raise 'Could not determine Yama status'
end

#yama_installed?Boolean

Returns true if Yama is installed

Returns:

  • (Boolean)

Raises:

  • (RuntimeError)

    If execution fails.



361
362
363
364
365
366
367
368
# File 'lib/msf/core/post/linux/kernel.rb', line 361

def yama_installed?
  ptrace_scope = read_file('/proc/sys/kernel/yama/ptrace_scope').to_s.strip
  return true if ptrace_scope =~ /\A\d\z/

  false
rescue StandardError
  raise 'Could not determine Yama status'
end

#yama_ptrace_scopeInteger

Returns Yama LSM ptrace scope level

Returns:

  • (Integer)

    Yama ptrace scope level (0 if disabled or not installed)

Raises:

  • (RuntimeError)

    If execution fails.



341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/msf/core/post/linux/kernel.rb', line 341

def yama_ptrace_scope
  ptrace_scope = read_file('/proc/sys/kernel/yama/ptrace_scope').to_s.strip

  return 0 unless ptrace_scope

  level = ptrace_scope.scan(/\A(\d+)\z/).flatten.first.to_i

  return 0 unless level

  level
rescue StandardError
  raise 'Could not determine Yama scope'
end