From 2fcbbbb9e6d6d1e6a8fe341cbd0e054b4271c548 Mon Sep 17 00:00:00 2001 From: girlier Date: Sat, 28 Mar 2026 14:43:30 +0000 Subject: [PATCH 01/21] Add cron-based privilege escalation modules and CTF scenario Two new vulnerability modules under access_control_misconfigurations: - cron_tar_wildcard: tar wildcard injection via root cron job - cron_writable_script: world-writable cron script executed as root Both adapted from benchmark-privesc-linux scenarios #11 and #12. Includes CTF scenario (cron_privesc.xml) chaining RCE with cron priv-esc on Debian 12, with 1 shared flag in /root/. --- .../cron_tar_wildcard/cron_tar_wildcard.pp | 1 + .../cron_tar_wildcard/manifests/config.pp | 43 ++++++ .../cron_tar_wildcard/secgen_metadata.xml | 44 ++++++ .../secgen_test/cron_tar_wildcard.rb | 18 +++ .../cron_writable_script.pp | 1 + .../cron_writable_script/manifests/config.pp | 29 ++++ .../cron_writable_script/secgen_metadata.xml | 44 ++++++ .../secgen_test/cron_writable_script.rb | 17 +++ scenarios/ctf/cron_privesc.xml | 130 ++++++++++++++++++ 9 files changed, 327 insertions(+) create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/cron_tar_wildcard.pp create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_test/cron_tar_wildcard.rb create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/cron_writable_script.pp create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml create mode 100644 modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_test/cron_writable_script.rb create mode 100644 scenarios/ctf/cron_privesc.xml diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/cron_tar_wildcard.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/cron_tar_wildcard.pp new file mode 100644 index 000000000..ae0b03023 --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/cron_tar_wildcard.pp @@ -0,0 +1 @@ +include cron_tar_wildcard::config diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp new file mode 100644 index 000000000..4214e7b82 --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -0,0 +1,43 @@ +class cron_tar_wildcard::config { + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) + $leaked_filenames = $secgen_parameters['leaked_filenames'] + $strings_to_leak = $secgen_parameters['strings_to_leak'] + + file { '/var/spool/backups': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + + file { '/opt/backup': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0777', + } + + file { '/opt/backup.txt': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => "# cron backup hint\n(cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + } + + cron { 'backup_wildcard': + command => 'cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *', + user => 'root', + hour => '*', + minute => '*', + } + + ::secgen_functions::leak_files { 'cron_tar_wildcard-file-leak': + storage_directory => '/root', + leaked_filenames => $leaked_filenames, + strings_to_leak => $strings_to_leak, + owner => 'root', + mode => '0600', + leaked_from => 'cron_tar_wildcard', + } +} diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml new file mode 100644 index 000000000..e10b3e03a --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml @@ -0,0 +1,44 @@ + + + Cron Tar Wildcard Privilege Escalation + SecGen + MIT + A root cron job runs tar with a wildcard (*) inside a user-writable directory. This can be + exploited using tar checkpoint flag injection by creating specially-named files (--checkpoint=1 and + --checkpoint-action=exec=sh exploit.sh) to execute arbitrary commands as root. + + + access_control_misconfiguration + cron_privilege_escalation + root_rwx + local + linux + medium + + strings_to_leak + leaked_filenames + + + + + + + + + + utilities/unix/puppet_module/cron_new + + + + access control + Elevated privileges + Vulnerabilities and attacks on access control misconfigurations + + + Access controls and operating systems + Linux security model + cron + + diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_test/cron_tar_wildcard.rb b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_test/cron_tar_wildcard.rb new file mode 100644 index 000000000..5413df512 --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_test/cron_tar_wildcard.rb @@ -0,0 +1,18 @@ +require_relative '../../../../../lib/post_provision_test' + +class CronTarWildcardTest < PostProvisionTest + def initialize + self.module_name = 'cron_tar_wildcard' + self.module_path = get_module_path(__FILE__) + super + end + + def test_module + super + test_local_command('backup directory exists and is world-writable?', 'sudo ls -la /opt/backup', 'backup') + test_local_command('hint file is readable?', 'sudo cat /opt/backup.txt', 'tar') + test_local_command('cron job exists?', 'sudo crontab -l', 'backup_wildcard') + end +end + +CronTarWildcardTest.new.run diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/cron_writable_script.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/cron_writable_script.pp new file mode 100644 index 000000000..6584bdd24 --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/cron_writable_script.pp @@ -0,0 +1 @@ +include cron_writable_script::config diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp new file mode 100644 index 000000000..c307cf50d --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp @@ -0,0 +1,29 @@ +class cron_writable_script::config { + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) + $leaked_filenames = $secgen_parameters['leaked_filenames'] + $strings_to_leak = $secgen_parameters['strings_to_leak'] + + file { '/opt/cron.sh': + ensure => file, + owner => 'root', + group => 'root', + mode => '0777', + content => "#!/bin/bash -p\necho 'hello from cron' >> /tmp/cron.log\n", + } + + cron { 'writable_cron_script': + command => '/opt/cron.sh', + user => 'root', + hour => '*', + minute => '*', + } + + ::secgen_functions::leak_files { 'cron_writable_script-file-leak': + storage_directory => '/root', + leaked_filenames => $leaked_filenames, + strings_to_leak => $strings_to_leak, + owner => 'root', + mode => '0600', + leaked_from => 'cron_writable_script', + } +} diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml new file mode 100644 index 000000000..6ca5702f0 --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml @@ -0,0 +1,44 @@ + + + Cron Writable Script Privilege Escalation + SecGen + MIT + A root cron job executes a world-writable script at /opt/cron.sh. Any + user can overwrite this script with arbitrary commands that will be executed as root by cron, + enabling trivial local privilege escalation. + + + access_control_misconfiguration + cron_privilege_escalation + root_rwx + local + linux + easy + + strings_to_leak + leaked_filenames + + + + + + + + + + utilities/unix/puppet_module/cron_new + + + + access control + Elevated privileges + Vulnerabilities and attacks on access control misconfigurations + + + Access controls and operating systems + Linux security model + cron + + diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_test/cron_writable_script.rb b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_test/cron_writable_script.rb new file mode 100644 index 000000000..d2b8dda58 --- /dev/null +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_test/cron_writable_script.rb @@ -0,0 +1,17 @@ +require_relative '../../../../../lib/post_provision_test' + +class CronWritableScriptTest < PostProvisionTest + def initialize + self.module_name = 'cron_writable_script' + self.module_path = get_module_path(__FILE__) + super + end + + def test_module + super + test_local_command('cron.sh is world-writable?', 'sudo ls -la /opt/cron.sh', 'rwxrwxrwx') + test_local_command('cron job exists?', 'sudo crontab -l', 'writable_cron_script') + end +end + +CronWritableScriptTest.new.run diff --git a/scenarios/ctf/cron_privesc.xml b/scenarios/ctf/cron_privesc.xml new file mode 100644 index 000000000..a23962985 --- /dev/null +++ b/scenarios/ctf/cron_privesc.xml @@ -0,0 +1,130 @@ + + + + Cron Privilege Escalation + SecGen + SSH into the target server as a standard user and escalate to root via cron + misconfigurations. Find the flag in /root/. + + + ctf + attack-ctf + pwn-ctf + easy + + Elevated privileges + Vulnerabilities and attacks on access control misconfigurations + + + Access controls and operating systems + Linux security model + cron + + + kill chains + + + cyber kill chain + + + + attack_vm + + + + 172.16.0.2 + 172.16.0.3 + + + + + {"username":"kali","password":"kali","super_user":"true","strings_to_leak":[],"leaked_filenames":[]} + + + + + + {"username":"kali","password":"kali","super_user":"true","strings_to_leak":[],"leaked_filenames":[]} + + + false + + + + + + + + + IP_addresses + + + + + + + + spoiler_admin_pass + + + + + + cron_privesc_server + + + + + + + + + + tiaspbiqe2r + + + false + + + + + + + + + + + + spoiler_admin_pass + + + + + + root_flag + + + + + + root_flag + + + + + + + + IP_addresses + + + + + spoiler_admin_pass + + + + + From fb1c9c3c78458e6f4ffa0b6b0d64e5e07abc35e0 Mon Sep 17 00:00:00 2001 From: girlier Date: Mon, 30 Mar 2026 15:43:51 +0100 Subject: [PATCH 02/21] Fix invalid difficulty value in cron_writable_script metadata Changed easy to low to conform with vulnerability_metadata_schema.xsd which only allows low, medium, or high as valid enumeration values. --- .../cron_writable_script/secgen_metadata.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml index 6ca5702f0..23279b318 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml @@ -15,7 +15,7 @@ root_rwx local linux - easy + low strings_to_leak leaked_filenames From 2594cf9abb7b151fd0cd8cf125d58d353d8036a0 Mon Sep 17 00:00:00 2001 From: girlier Date: Mon, 30 Mar 2026 16:01:25 +0100 Subject: [PATCH 03/21] Fix cron_privesc scenario: change server base type from server to desktop No Debian 12 server base module exists. Changed to type desktop with KDE to match the available debian_bookworm_desktop_kde base module. --- scenarios/ctf/cron_privesc.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenarios/ctf/cron_privesc.xml b/scenarios/ctf/cron_privesc.xml index a23962985..d7e3b5921 100644 --- a/scenarios/ctf/cron_privesc.xml +++ b/scenarios/ctf/cron_privesc.xml @@ -73,7 +73,7 @@ cron_privesc_server - + From bb7b33d0b46254d110ed26054a6282106f6acca9 Mon Sep 17 00:00:00 2001 From: girlier Date: Fri, 10 Apr 2026 13:56:36 +0100 Subject: [PATCH 04/21] Change Hint to involve sudo -l --- .../cron_tar_wildcard/manifests/config.pp | 49 ++++++++++++++++--- .../cron_tar_wildcard/secgen_metadata.xml | 4 ++ scenarios/ctf/cron_privesc.xml | 2 - 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp index 4214e7b82..3ebbf5493 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -2,6 +2,17 @@ $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] + $show_crontab_hint = $secgen_parameters['show_crontab_hint'] + + package { 'cron': + ensure => installed, + } + + service { 'cron': + ensure => running, + enable => true, + require => Package['cron'], + } file { '/var/spool/backups': ensure => directory, @@ -17,12 +28,37 @@ mode => '0777', } - file { '/opt/backup.txt': - ensure => file, - owner => 'root', - group => 'root', - mode => '0644', - content => "# cron backup hint\n(cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + if $show_crontab_hint =~ /^(true|1|yes)$/ { + # Enable sudo access to crontab -l so players can discover the cron job + class { 'sudo': + config_file_replace => false, + } + + sudo::conf { 'users_sudo_list': + ensure => present, + content => 'ALL ALL=(root) NOPASSWD: /usr/bin/sudo -l', + } + + sudo::conf { 'users_crontab_list': + ensure => present, + content => 'ALL ALL=(root) NOPASSWD: /usr/bin/crontab -l', + } + + file { '/opt/backup.txt': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => "# cron backup hint\n# Try: sudo -l to see what you can run\n# Then: sudo crontab -l to view root's cron jobs\n(cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + } + } else { + file { '/opt/backup.txt': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => "# cron backup hint\n(cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + } } cron { 'backup_wildcard': @@ -30,6 +66,7 @@ user => 'root', hour => '*', minute => '*', + require => [Service['cron'], File['/opt/backup']], } ::secgen_functions::leak_files { 'cron_tar_wildcard-file-leak': diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml index e10b3e03a..ad8405ab9 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml @@ -19,6 +19,7 @@ strings_to_leak leaked_filenames + show_crontab_hint @@ -26,6 +27,9 @@ + + false + utilities/unix/puppet_module/cron_new diff --git a/scenarios/ctf/cron_privesc.xml b/scenarios/ctf/cron_privesc.xml index d7e3b5921..a0977ada9 100644 --- a/scenarios/ctf/cron_privesc.xml +++ b/scenarios/ctf/cron_privesc.xml @@ -113,8 +113,6 @@ - - IP_addresses From 945a814a0215fc2ab19956ca5b5449ecf4f15f34 Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 21:29:20 +0100 Subject: [PATCH 05/21] Add random_file_path generator for configurable cron locations - New generator selects from 15 system paths, optionally includes user-specific paths when username provided - Both cron escalation modules now use random_file_path for configurable deployment locations - cron_writable_script uses random_evil_plans for dynamic script content - Path validation, permission checks, and detailed logging for debugging/auditing --- .../random_file_path/manifests/.no_puppet | 0 .../random_file_path/random_file_path.pp | 0 .../random_file_path/secgen_local/local.rb | 181 ++++++++++++++++++ .../random_file_path/secgen_metadata.xml | 19 ++ .../cron_tar_wildcard/manifests/config.pp | 20 +- .../cron_tar_wildcard/secgen_metadata.xml | 9 +- .../cron_writable_script/manifests/config.pp | 17 +- .../cron_writable_script/secgen_metadata.xml | 11 +- 8 files changed, 242 insertions(+), 15 deletions(-) create mode 100644 modules/generators/random/random_file_path/manifests/.no_puppet create mode 100644 modules/generators/random/random_file_path/random_file_path.pp create mode 100644 modules/generators/random/random_file_path/secgen_local/local.rb create mode 100644 modules/generators/random/random_file_path/secgen_metadata.xml diff --git a/modules/generators/random/random_file_path/manifests/.no_puppet b/modules/generators/random/random_file_path/manifests/.no_puppet new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/random/random_file_path/random_file_path.pp b/modules/generators/random/random_file_path/random_file_path.pp new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/random/random_file_path/secgen_local/local.rb b/modules/generators/random/random_file_path/secgen_local/local.rb new file mode 100644 index 000000000..a5813c495 --- /dev/null +++ b/modules/generators/random/random_file_path/secgen_local/local.rb @@ -0,0 +1,181 @@ +#!/usr/bin/ruby +require_relative '../../../../../lib/objects/local_string_generator.rb' +require 'fileutils' +require 'logger' + +class FilePathGenerator < StringGenerator + attr_accessor :selected_location + attr_accessor :username + + BASE_SYSTEM_LOCATIONS = [ + '/usr/bin', + '/etc/cron.d', + '/opt', + '/usr/local/bin', + '/usr/sbin', + '/var/tmp', + '/usr/share', + '/var/opt', + '/usr/lib', + '/srv', + '/var/spool', + '/usr/src', + '/var/cache' + ].freeze + + def initialize + super + self.module_name = 'Random File Path Generator' + @logger = Logger.new($stdout) + @logger.level = Logger::INFO + @logger.formatter = proc do |severity, datetime, _progname, msg| + "[#{datetime.strftime('%Y-%m-%d %H:%M:%S')}] #{severity}: #{msg}\n" + end + @username = nil + end + + def get_options_array + super + [ + ['--validate-writable', GetoptLong::OPTIONAL_ARGUMENT], + ['--username', GetoptLong::REQUIRED_ARGUMENT] + ] + end + + def process_options(opt, arg) + super + case opt + when '--validate-writable' + @validate_writable = true + when '--username' + @username = arg + end + end + + def predefined_locations + locations = BASE_SYSTEM_LOCATIONS.dup + if @username && !@username.empty? + locations << "/home/#{@username}/.config" + locations << "/home/#{@username}/.config/local" + locations << "/home/#{@username}/.local/share" + @logger.info("Including user-specific paths for username: #{@username}") + else + @logger.info("No username provided, using only system locations") + end + locations << "/root/.config" + locations << "/root/.local/share" + locations + end + + def validate_path(path) + unless path.is_a?(String) && !path.empty? + @logger.error("Invalid path: path must be a non-empty string") + return false + end + + normalized_path = File.expand_path(path) + + unless normalized_path == path + @logger.warn("Path '#{path}' normalized to '#{normalized_path}'") + end + + unless predefined_locations.include?(normalized_path) + @logger.error("Path '#{normalized_path}' is not in the predefined list of allowed locations") + return false + end + + @logger.info("Path validation successful for: #{normalized_path}") + true + end + + def check_write_permissions(path) + return false unless validate_path(path) + + begin + if File.directory?(path) + if File.writable?(path) + @logger.info("Write permission confirmed for: #{path}") + return true + else + @logger.warn("No write permission for existing directory: #{path}") + end + else + parent_dir = File.dirname(path) + if File.directory?(parent_dir) && File.writable?(parent_dir) + @logger.info("Parent directory writable, can create: #{path}") + return true + else + @logger.warn("Cannot create path, parent not writable: #{parent_dir}") + end + end + rescue Errno::EACCES => e + @logger.error("Permission denied accessing: #{path} - #{e.message}") + rescue Errno::ENOENT => e + @logger.error("Path does not exist: #{path} - #{e.message}") + rescue StandardError => e + @logger.error("Unexpected error checking permissions for #{path}: #{e.message}") + end + + false + end + + def filter_available_locations + locations = predefined_locations + available = locations.select do |location| + begin + if File.directory?(location) + @logger.info("Location available: #{location}") + true + else + @logger.warn("Location not found (will be created): #{location}") + true + end + rescue StandardError => e + @logger.error("Error checking location #{location}: #{e.message}") + false + end + end + + if available.empty? + @logger.warn("No locations available, using fallback: /tmp") + available = ['/tmp'] + end + + available + end + + def select_random_location + available_locations = filter_available_locations + + if @validate_writable + writable_locations = available_locations.select { |loc| check_write_permissions(loc) } + if writable_locations.empty? + @logger.warn("No writable locations found, selecting from all available") + writable_locations = available_locations + end + available_locations = writable_locations + end + + selected = available_locations.sample + @logger.info("=" * 60) + @logger.info("SELECTED PATH: #{selected}") + @logger.info("Username context: #{@username}") + @logger.info("Selection made from #{available_locations.length} available path(s)") + @logger.info("Available paths were: #{available_locations.join(', ')}") + @logger.info("=" * 60) + @logger.info("AUDIT: Random path selected at #{Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')}") + @logger.info("AUDIT: Path: #{selected}") + @logger.info("AUDIT: Username: #{@username}") + @logger.info("AUDIT: Module: #{module_name}") + @logger.info("=" * 60) + + selected + end + + def generate + location = select_random_location + self.outputs << location + self.selected_location = location + end +end + +FilePathGenerator.new.run \ No newline at end of file diff --git a/modules/generators/random/random_file_path/secgen_metadata.xml b/modules/generators/random/random_file_path/secgen_metadata.xml new file mode 100644 index 000000000..db67a3c0d --- /dev/null +++ b/modules/generators/random/random_file_path/secgen_metadata.xml @@ -0,0 +1,19 @@ + + + + Random File Path Generator + Rosie Fletcher + MIT + Randomly selects a file path from a predefined list of system locations designed for misconfiguration privilege escalation vulnerabilities, specifically cron. If a username is provided, user-specific paths are also included. + + location_generator + path_generator + local_calculation + linux + + username + + location + \ No newline at end of file diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp index 3ebbf5493..d9b7c303b 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -3,6 +3,12 @@ $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] $show_crontab_hint = $secgen_parameters['show_crontab_hint'] + $cron_location = $secgen_parameters['cron_location'] ? { + undef => '/opt', + default => $secgen_parameters['cron_location'], + } + + $backup_dir = "${cron_location}/backup" package { 'cron': ensure => installed, @@ -21,7 +27,7 @@ mode => '0755', } - file { '/opt/backup': + file { $backup_dir: ensure => directory, owner => 'root', group => 'root', @@ -44,29 +50,29 @@ content => 'ALL ALL=(root) NOPASSWD: /usr/bin/crontab -l', } - file { '/opt/backup.txt': + file { "${cron_location}/backup.txt": ensure => file, owner => 'root', group => 'root', mode => '0644', - content => "# cron backup hint\n# Try: sudo -l to see what you can run\n# Then: sudo crontab -l to view root's cron jobs\n(cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + content => "# cron backup hint\n# Try: sudo -l to see what you can run\n# Then: sudo crontab -l to view root's cron jobs\n(cd ${backup_dir} && tar -zcf /var/spool/backups/backup.tar.gz *)\n", } } else { - file { '/opt/backup.txt': + file { "${cron_location}/backup.txt": ensure => file, owner => 'root', group => 'root', mode => '0644', - content => "# cron backup hint\n(cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + content => "# cron backup hint\n(cd ${backup_dir} && tar -zcf /var/spool/backups/backup.tar.gz *)\n", } } cron { 'backup_wildcard': - command => 'cd /opt/backup && tar -zcf /var/spool/backups/backup.tar.gz *', + command => "cd ${backup_dir} && tar -zcf /var/spool/backups/backup.tar.gz *", user => 'root', hour => '*', minute => '*', - require => [Service['cron'], File['/opt/backup']], + require => [Service['cron'], File[$backup_dir]], } ::secgen_functions::leak_files { 'cron_tar_wildcard-file-leak': diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml index ad8405ab9..6c23e482e 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.github/cliffe/SecGen/vulnerability"> Cron Tar Wildcard Privilege Escalation - SecGen + Rosie Fletcher MIT A root cron job runs tar with a wildcard (*) inside a user-writable directory. This can be exploited using tar checkpoint flag injection by creating specially-named files (--checkpoint=1 and @@ -20,6 +20,7 @@ strings_to_leak leaked_filenames show_crontab_hint + cron_location @@ -28,7 +29,10 @@ - false + true + + + @@ -43,6 +47,5 @@ Access controls and operating systems Linux security model - cron diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp index c307cf50d..899150280 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp @@ -2,20 +2,31 @@ $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] + $cron_location = $secgen_parameters['cron_location'] ? { + undef => '/opt', + default => $secgen_parameters['cron_location'], + } + $cron_message = $secgen_parameters['cron_message'] ? { + undef => 'hello from cron', + default => $secgen_parameters['cron_message'], + } + + $cron_script_path = "${cron_location}/cron.sh" - file { '/opt/cron.sh': + file { $cron_script_path: ensure => file, owner => 'root', group => 'root', mode => '0777', - content => "#!/bin/bash -p\necho 'hello from cron' >> /tmp/cron.log\n", + content => "#!/bin/bash -p\necho '${cron_message}' >> /tmp/cron.log\n", } cron { 'writable_cron_script': - command => '/opt/cron.sh', + command => $cron_script_path, user => 'root', hour => '*', minute => '*', + require => File[$cron_script_path], } ::secgen_functions::leak_files { 'cron_writable_script-file-leak': diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml index 23279b318..d038865c2 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.github/cliffe/SecGen/vulnerability"> Cron Writable Script Privilege Escalation - SecGen + Rosie Fletcher MIT A root cron job executes a world-writable script at /opt/cron.sh. Any user can overwrite this script with arbitrary commands that will be executed as root by cron, @@ -19,6 +19,8 @@ strings_to_leak leaked_filenames + cron_location + cron_message @@ -26,6 +28,12 @@ + + + + + + utilities/unix/puppet_module/cron_new @@ -39,6 +47,5 @@ Access controls and operating systems Linux security model - cron From 3c03dc8e0fe1833466e172dd1a9e29ad0de3a48d Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 21:33:48 +0100 Subject: [PATCH 06/21] Add optional cron_user parameter for horizontal privilege escalation - New cron_user parameter defaults to root but can be set to any user - Enables horizontal privilege escalation scenarios (user-to-user escalation) - Leak storage directory dynamically adjusts based on cron_user - Updated description to reflect configurable escalation type --- .../cron_writable_script/manifests/config.pp | 14 +++++++++++--- .../cron_writable_script/secgen_metadata.xml | 13 ++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp index 899150280..ca7613416 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp @@ -10,8 +10,16 @@ undef => 'hello from cron', default => $secgen_parameters['cron_message'], } + $cron_user = $secgen_parameters['cron_user'] ? { + undef => 'root', + default => $secgen_parameters['cron_user'], + } $cron_script_path = "${cron_location}/cron.sh" + $leak_storage_dir = $cron_user ? { + 'root' => '/root', + default => "/home/${cron_user}", + } file { $cron_script_path: ensure => file, @@ -23,17 +31,17 @@ cron { 'writable_cron_script': command => $cron_script_path, - user => 'root', + user => $cron_user, hour => '*', minute => '*', require => File[$cron_script_path], } ::secgen_functions::leak_files { 'cron_writable_script-file-leak': - storage_directory => '/root', + storage_directory => $leak_storage_dir, leaked_filenames => $leaked_filenames, strings_to_leak => $strings_to_leak, - owner => 'root', + owner => $cron_user, mode => '0600', leaked_from => 'cron_writable_script', } diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml index d038865c2..027d0006b 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/secgen_metadata.xml @@ -5,10 +5,9 @@ Cron Writable Script Privilege Escalation Rosie Fletcher MIT - A root cron job executes a world-writable script at /opt/cron.sh. Any - user can overwrite this script with arbitrary commands that will be executed as root by cron, - enabling trivial local privilege escalation. - + A cron job executes a world-writable script. By default runs as root for vertical privilege escalation. + Optionally configurable to run as a non-privileged user, enabling horizontal privilege escalation scenarios + where a lower-privileged user can escalate to another user account. access_control_misconfiguration cron_privilege_escalation @@ -21,6 +20,7 @@ leaked_filenames cron_location cron_message + cron_user @@ -34,6 +34,9 @@ + + root + utilities/unix/puppet_module/cron_new @@ -48,4 +51,4 @@ Access controls and operating systems Linux security model - + \ No newline at end of file From f1ea5fa70b652757340cdee0209eed5ca51583b4 Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 21:54:25 +0100 Subject: [PATCH 07/21] Add permission control to cron_tar_wildcard module - Default: world-writable (0777) for backup/archive directories - Optional restrict_write_user parameter limits write access to specific user - User validation via exec ensures user exists before applying restrictions - cron_user parameter allows non-root cron execution - Clear permission hierarchy logging via notice statements - Leak storage directory adjusts based on cron_user --- .../cron_tar_wildcard/manifests/config.pp | 97 +++++++++++++++---- .../cron_tar_wildcard/secgen_metadata.xml | 19 +++- 2 files changed, 92 insertions(+), 24 deletions(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp index d9b7c303b..0aa73f70c 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -7,8 +7,19 @@ undef => '/opt', default => $secgen_parameters['cron_location'], } + $cron_user = $secgen_parameters['cron_user'] ? { + undef => 'root', + default => $secgen_parameters['cron_user'], + } + $restrict_write_user_input = $secgen_parameters['restrict_write_user'] $backup_dir = "${cron_location}/backup" + $archive_dest = '/var/spool/backups' + + $leak_storage_dir = $cron_user ? { + 'root' => '/root', + default => "/home/${cron_user}", + } package { 'cron': ensure => installed, @@ -20,22 +31,68 @@ require => Package['cron'], } - file { '/var/spool/backups': - ensure => directory, - owner => 'root', - group => 'root', - mode => '0755', - } + if $restrict_write_user_input and $restrict_write_user_input != '' { + $restrict_write_user = $restrict_write_user_input + $backup_dir_owner = $restrict_write_user + $backup_dir_group = $restrict_write_user + $backup_dir_mode = '0755' + $archive_owner = $restrict_write_user + $archive_group = $restrict_write_user + $archive_mode = '0755' + + exec { "validate_restricted_user": + command => "/usr/bin/id ${restrict_write_user}", + unless => "/usr/bin/id ${restrict_write_user}", + path => ['/usr/bin'], + before => File[$backup_dir], + } + + notice("Permission hierarchy: Write access restricted to user '${restrict_write_user}'") + notice("Backup directory mode: 0755 (user-writable only)") + notice("Archive directory mode: 0755 (user-writable only)") + + file { $archive_dest: + ensure => directory, + owner => $archive_owner, + group => $archive_group, + mode => $archive_mode, + } + + file { $backup_dir: + ensure => directory, + owner => $backup_dir_owner, + group => $backup_dir_group, + mode => $backup_dir_mode, + require => Exec['validate_restricted_user'], + } + } else { + $backup_dir_owner = 'root' + $backup_dir_group = 'root' + $backup_dir_mode = '0777' + $archive_owner = 'root' + $archive_group = 'root' + $archive_mode = '0777' - file { $backup_dir: - ensure => directory, - owner => 'root', - group => 'root', - mode => '0777', + notice("Permission hierarchy: Write access global (mode 0777)") + notice("Backup directory mode: 0777 (world-writable)") + notice("Archive directory mode: 0777 (world-writable)") + + file { $archive_dest: + ensure => directory, + owner => $archive_owner, + group => $archive_group, + mode => $archive_mode, + } + + file { $backup_dir: + ensure => directory, + owner => $backup_dir_owner, + group => $backup_dir_group, + mode => $backup_dir_mode, + } } if $show_crontab_hint =~ /^(true|1|yes)$/ { - # Enable sudo access to crontab -l so players can discover the cron job class { 'sudo': config_file_replace => false, } @@ -55,7 +112,7 @@ owner => 'root', group => 'root', mode => '0644', - content => "# cron backup hint\n# Try: sudo -l to see what you can run\n# Then: sudo crontab -l to view root's cron jobs\n(cd ${backup_dir} && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + content => "# cron backup hint\n# Try: sudo -l to see what you can run\n# Then: sudo crontab -l to view root's cron jobs\n(cd ${backup_dir} && tar -zcf ${archive_dest}/backup.tar.gz *)\n", } } else { file { "${cron_location}/backup.txt": @@ -63,24 +120,24 @@ owner => 'root', group => 'root', mode => '0644', - content => "# cron backup hint\n(cd ${backup_dir} && tar -zcf /var/spool/backups/backup.tar.gz *)\n", + content => "# cron backup hint\n(cd ${backup_dir} && tar -zcf ${archive_dest}/backup.tar.gz *)\n", } } cron { 'backup_wildcard': - command => "cd ${backup_dir} && tar -zcf /var/spool/backups/backup.tar.gz *", - user => 'root', + command => "cd ${backup_dir} && tar -zcf ${archive_dest}/backup.tar.gz *", + user => $cron_user, hour => '*', minute => '*', - require => [Service['cron'], File[$backup_dir]], + require => [Service['cron'], File[$backup_dir], File[$archive_dest]], } ::secgen_functions::leak_files { 'cron_tar_wildcard-file-leak': - storage_directory => '/root', + storage_directory => $leak_storage_dir, leaked_filenames => $leaked_filenames, strings_to_leak => $strings_to_leak, - owner => 'root', + owner => $cron_user, mode => '0600', leaked_from => 'cron_tar_wildcard', } -} +} \ No newline at end of file diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml index 6c23e482e..fafd54059 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml @@ -5,10 +5,13 @@ Cron Tar Wildcard Privilege Escalation Rosie Fletcher MIT - A root cron job runs tar with a wildcard (*) inside a user-writable directory. This can be + A cron job runs tar with a wildcard (*) inside a user-writable directory. This can be exploited using tar checkpoint flag injection by creating specially-named files (--checkpoint=1 and - --checkpoint-action=exec=sh exploit.sh) to execute arbitrary commands as root. - + --checkpoint-action=exec=sh exploit.sh) to execute arbitrary commands as the cron user. + + By default, the backup directory is world-writable (mode 0777) allowing any user to exploit. + Optionally, write access can be restricted to a specific user via the restrict_write_user parameter, + enabling targeted privilege escalation scenarios where only that user can exploit the vulnerability. access_control_misconfiguration cron_privilege_escalation @@ -21,6 +24,8 @@ leaked_filenames show_crontab_hint cron_location + cron_user + restrict_write_user @@ -34,6 +39,12 @@ + + root + + + + utilities/unix/puppet_module/cron_new @@ -48,4 +59,4 @@ Access controls and operating systems Linux security model - + \ No newline at end of file From fa02321f2f99f45d5b12c71c277f9e0f4e59d3e4 Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 22:06:15 +0100 Subject: [PATCH 08/21] Restrict crontab viewing when restrict_write_user is set - When restrict_write_user is specified, only that user can sudo crontab -l - Default behavior (no restriction): all users can view crontab via sudo - Added notice statements for permission hierarchy clarity - Updated description to document crontab restriction behavior --- .../cron_tar_wildcard/manifests/config.pp | 17 ++++++++++++++--- .../cron_tar_wildcard/secgen_metadata.xml | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp index 0aa73f70c..fa3626ab5 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -102,9 +102,20 @@ content => 'ALL ALL=(root) NOPASSWD: /usr/bin/sudo -l', } - sudo::conf { 'users_crontab_list': - ensure => present, - content => 'ALL ALL=(root) NOPASSWD: /usr/bin/crontab -l', + if $restrict_write_user_input and $restrict_write_user_input != '' { + sudo::conf { 'restricted_crontab_list': + ensure => present, + content => "${restrict_write_user} ALL=(root) NOPASSWD: /usr/bin/crontab -l", + } + + notice("Crontab hint restricted: Only user '${restrict_write_user}' can view crontab") + } else { + sudo::conf { 'users_crontab_list': + ensure => present, + content => 'ALL ALL=(root) NOPASSWD: /usr/bin/crontab -l', + } + + notice("Crontab hint global: All users can view crontab") } file { "${cron_location}/backup.txt": diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml index fafd54059..07965bb2e 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml @@ -11,7 +11,8 @@ By default, the backup directory is world-writable (mode 0777) allowing any user to exploit. Optionally, write access can be restricted to a specific user via the restrict_write_user parameter, - enabling targeted privilege escalation scenarios where only that user can exploit the vulnerability. + enabling targeted privilege escalation scenarios where only that user can exploit the vulnerability. + When restrict_write_user is set, crontab viewing via sudo is also restricted to that user only. access_control_misconfiguration cron_privilege_escalation From fda84500197d6f35ca3d4e3a0b76742d5170a87c Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 22:17:22 +0100 Subject: [PATCH 09/21] Implement two-stage privilege escalation scenario: Root Cron-trol - Stage 1: SSH access as lowpriv user, horizontal escalation via writable cron script (lowpriv -> backup user) - Stage 2: Vertical escalation to root via tar wildcard injection in root cron job - Uses random_file_path generator for randomized file locations - cron_writable_script configured with cron_user=backup for horizontal escalation - cron_tar_wildcard configured with restrict_write_user=backup for targeted exploitation - Two distinct flags: horizontal_flag (user escalation), root_flag (root escalation) - Renamed from cron_privesc.xml to root_cron-trol.xml --- .../{cron_privesc.xml => root_cron-trol.xml} | 79 ++++++++++++++++--- 1 file changed, 66 insertions(+), 13 deletions(-) rename scenarios/ctf/{cron_privesc.xml => root_cron-trol.xml} (59%) diff --git a/scenarios/ctf/cron_privesc.xml b/scenarios/ctf/root_cron-trol.xml similarity index 59% rename from scenarios/ctf/cron_privesc.xml rename to scenarios/ctf/root_cron-trol.xml index a0977ada9..8f06a9942 100644 --- a/scenarios/ctf/cron_privesc.xml +++ b/scenarios/ctf/root_cron-trol.xml @@ -3,19 +3,22 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.github/cliffe/SecGen/scenario"> - Cron Privilege Escalation - SecGen - SSH into the target server as a standard user and escalate to root via cron - misconfigurations. Find the flag in /root/. - + Root Cron-trol + Rosie Fletcher + A two-stage privilege escalation challenge. Gain initial SSH access as a low-privileged user, + then perform horizontal privilege escalation by exploiting a writable cron script owned by another user. + Finally, achieve vertical privilege escalation to root through a tar wildcard injection vulnerability in a + root-owned cron job. Master the art of cron-based privilege escalation! ctf attack-ctf pwn-ctf - easy + intermediate Elevated privileges Vulnerabilities and attacks on access control misconfigurations + Horizontal privilege escalation + Vertical privilege escalation Access controls and operating systems @@ -72,17 +75,41 @@ - cron_privesc_server + server + + + + + tiaspbiqe2r + + + backup + + + + + - + lowpriv_user + + + lowpriv_pass + + + false + + + + + target_user - tiaspbiqe2r + target_pass false @@ -91,6 +118,9 @@ + + + @@ -101,16 +131,39 @@ - + - root_flag + horizontal_flag + + + target_user + + + + + target_user + + - + root_flag + + root + + + target_user + + + + + target_user + + + @@ -125,4 +178,4 @@ - + \ No newline at end of file From a70879ebefdfd7771974d0e6d1f4d48283c900ca Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 22:20:28 +0100 Subject: [PATCH 10/21] Make target_user random in Root Cron-trol scenario - Changed target_user from hardcoded 'backup' to username_generator - Both lowpriv_user and target_user are now randomly generated - Increases realism and prevents predictable username exploitation --- scenarios/ctf/root_cron-trol.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenarios/ctf/root_cron-trol.xml b/scenarios/ctf/root_cron-trol.xml index 8f06a9942..875798be7 100644 --- a/scenarios/ctf/root_cron-trol.xml +++ b/scenarios/ctf/root_cron-trol.xml @@ -85,7 +85,7 @@ tiaspbiqe2r - backup + From 135d92617d49c0f886a6ee610f9cbb49fff75fc3 Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 22:23:41 +0100 Subject: [PATCH 11/21] Format root_cron-trol scenario to match project standards - Added empty line after XML declaration (standard format) - Added comments for IP addresses indicating which system they belong to - Split CyBOK entries into logical sections with comments - Added comments for vulnerability sections (SSH, horizontal, vertical) - Removed redundant 'cron' keyword from CyBOK --- scenarios/ctf/root_cron-trol.xml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scenarios/ctf/root_cron-trol.xml b/scenarios/ctf/root_cron-trol.xml index 875798be7..5b842329e 100644 --- a/scenarios/ctf/root_cron-trol.xml +++ b/scenarios/ctf/root_cron-trol.xml @@ -1,4 +1,5 @@ + @@ -14,17 +15,26 @@ attack-ctf pwn-ctf intermediate + + Elevated privileges Vulnerabilities and attacks on access control misconfigurations Horizontal privilege escalation + + + + Vertical privilege escalation + + Access controls and operating systems Linux security model - cron + + kill chains @@ -37,7 +47,9 @@ + 172.16.0.2 + 172.16.0.3 @@ -125,12 +137,14 @@ + spoiler_admin_pass + horizontal_flag @@ -147,6 +161,7 @@ + root_flag From 410d259c1520dc7016434abc19535db8c097a19d Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 22:44:40 +0100 Subject: [PATCH 12/21] Fix base64 decode crash: Logger outputs to stderr not stdout - Changed Logger.new() to Logger.new() - SecGen captures stdout expecting only base64-encoded output - Logger messages interleaved with output caused strict_decode64 failures - stderr now receives logging/debug info, stdout only has base64 output --- .../generators/random/random_file_path/secgen_local/local.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/generators/random/random_file_path/secgen_local/local.rb b/modules/generators/random/random_file_path/secgen_local/local.rb index a5813c495..930d30db0 100644 --- a/modules/generators/random/random_file_path/secgen_local/local.rb +++ b/modules/generators/random/random_file_path/secgen_local/local.rb @@ -26,7 +26,7 @@ class FilePathGenerator < StringGenerator def initialize super self.module_name = 'Random File Path Generator' - @logger = Logger.new($stdout) + @logger = Logger.new($stderr) @logger.level = Logger::INFO @logger.formatter = proc do |severity, datetime, _progname, msg| "[#{datetime.strftime('%Y-%m-%d %H:%M:%S')}] #{severity}: #{msg}\n" From 08375a3288e1585aaf80e9efb9282e114beb7e5b Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 23:22:52 +0100 Subject: [PATCH 13/21] Fix Puppet array interpolation: extract [0] from secgen_parameters - SecGen generators output arrays, not single values - Without [0], Puppet interpolates array as '[value]' string - Added [0] extraction for cron_location, cron_user, cron_message, restrict_write_user - Matches pattern used in all other SecGen modules - Fixes 'File paths must be fully qualified' error with malformed paths like '[/home/user/.config]/cron.sh' --- .../cron_tar_wildcard/manifests/config.pp | 27 ++++++++++++++----- .../cron_writable_script/manifests/config.pp | 21 ++++++++++----- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp index fa3626ab5..1c9777df7 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -2,16 +2,31 @@ $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] - $show_crontab_hint = $secgen_parameters['show_crontab_hint'] - $cron_location = $secgen_parameters['cron_location'] ? { + + # Extract first element from arrays (SecGen generators output arrays) + $show_crontab_hint_raw = $secgen_parameters['show_crontab_hint'] + $show_crontab_hint = $show_crontab_hint_raw ? { + undef => 'false', + default => $show_crontab_hint_raw[0], + } + + $cron_location_raw = $secgen_parameters['cron_location'] + $cron_location = $cron_location_raw ? { undef => '/opt', - default => $secgen_parameters['cron_location'], + default => $cron_location_raw[0], } - $cron_user = $secgen_parameters['cron_user'] ? { + + $cron_user_raw = $secgen_parameters['cron_user'] + $cron_user = $cron_user_raw ? { undef => 'root', - default => $secgen_parameters['cron_user'], + default => $cron_user_raw[0], + } + + $restrict_write_user_raw = $secgen_parameters['restrict_write_user'] + $restrict_write_user_input = $restrict_write_user_raw ? { + undef => '', + default => $restrict_write_user_raw[0], } - $restrict_write_user_input = $secgen_parameters['restrict_write_user'] $backup_dir = "${cron_location}/backup" $archive_dest = '/var/spool/backups' diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp index ca7613416..ee0070dce 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp @@ -2,17 +2,24 @@ $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] - $cron_location = $secgen_parameters['cron_location'] ? { + + # Extract first element from arrays (SecGen generators output arrays) + $cron_location_raw = $secgen_parameters['cron_location'] + $cron_location = $cron_location_raw ? { undef => '/opt', - default => $secgen_parameters['cron_location'], + default => $cron_location_raw[0], } - $cron_message = $secgen_parameters['cron_message'] ? { + + $cron_message_raw = $secgen_parameters['cron_message'] + $cron_message = $cron_message_raw ? { undef => 'hello from cron', - default => $secgen_parameters['cron_message'], + default => $cron_message_raw[0], } - $cron_user = $secgen_parameters['cron_user'] ? { + + $cron_user_raw = $secgen_parameters['cron_user'] + $cron_user = $cron_user_raw ? { undef => 'root', - default => $secgen_parameters['cron_user'], + default => $cron_user_raw[0], } $cron_script_path = "${cron_location}/cron.sh" @@ -45,4 +52,4 @@ mode => '0600', leaked_from => 'cron_writable_script', } -} +} \ No newline at end of file From 2202f447f40d6f288b5d525335980403e87a0293 Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 23:39:13 +0100 Subject: [PATCH 14/21] Fix sudo class declaration: move outside conditional block - sudo::conf define requires ::config_dir from sudo class - Declaring sudo class inside conditional caused dependency resolution failure - Moved 'class { sudo: ... }' to top level, matching sudo_root_less pattern - sudo::conf resources remain conditional (only created when show_crontab_hint is true) --- .../cron_tar_wildcard/manifests/config.pp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp index 1c9777df7..e2af8e779 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -36,6 +36,11 @@ default => "/home/${cron_user}", } + # Declare sudo class at top level (sudo::conf requires $sudo::config_dir) + class { 'sudo': + config_file_replace => false, + } + package { 'cron': ensure => installed, } @@ -108,10 +113,6 @@ } if $show_crontab_hint =~ /^(true|1|yes)$/ { - class { 'sudo': - config_file_replace => false, - } - sudo::conf { 'users_sudo_list': ensure => present, content => 'ALL ALL=(root) NOPASSWD: /usr/bin/sudo -l', From d0d681dc23e2c9bb4cc36ed41575cebefa4fc49f Mon Sep 17 00:00:00 2001 From: girlier Date: Wed, 29 Apr 2026 23:47:14 +0100 Subject: [PATCH 15/21] Comprehensive audit fixes: critical and high severity issues CRITICAL FIXES: - Added cron_user validation in cron_writable_script (exec check before file creation) - Shared cron_location datastore prevents inconsistent random selections between modules HIGH FIXES: - Single generator for cron_location used by both vulnerabilities in scenario - Added require dependency for user validation exec LOW FIXES: - Removed unused 'fileutils' require in random_file_path generator AUDIT FINDINGS DOCUMENTED: - Race condition with cron * minute (accept as design for rapid testing) - sudo always declared (acceptable as sudo typically needed) - Logger INFO level (acceptable for debugging) --- .../random_file_path/secgen_local/local.rb | 1 - .../cron_writable_script/manifests/config.pp | 13 +++++++++++++ scenarios/ctf/root_cron-trol.xml | 19 +++++++++---------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/modules/generators/random/random_file_path/secgen_local/local.rb b/modules/generators/random/random_file_path/secgen_local/local.rb index 930d30db0..4f9c36657 100644 --- a/modules/generators/random/random_file_path/secgen_local/local.rb +++ b/modules/generators/random/random_file_path/secgen_local/local.rb @@ -1,6 +1,5 @@ #!/usr/bin/ruby require_relative '../../../../../lib/objects/local_string_generator.rb' -require 'fileutils' require 'logger' class FilePathGenerator < StringGenerator diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp index ee0070dce..102205a42 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp @@ -22,6 +22,15 @@ default => $cron_user_raw[0], } + # Validate cron_user exists (if not root) + if $cron_user != 'root' { + exec { "validate_cron_user_${cron_user}": + command => "/usr/bin/id ${cron_user}", + unless => "/usr/bin/id ${cron_user}", + path => ['/usr/bin'], + } + } + $cron_script_path = "${cron_location}/cron.sh" $leak_storage_dir = $cron_user ? { 'root' => '/root', @@ -34,6 +43,10 @@ group => 'root', mode => '0777', content => "#!/bin/bash -p\necho '${cron_message}' >> /tmp/cron.log\n", + require => $cron_user ? { + 'root' => undef, + default => Exec["validate_cron_user_${cron_user}"], + }, } cron { 'writable_cron_script': diff --git a/scenarios/ctf/root_cron-trol.xml b/scenarios/ctf/root_cron-trol.xml index 5b842329e..887238910 100644 --- a/scenarios/ctf/root_cron-trol.xml +++ b/scenarios/ctf/root_cron-trol.xml @@ -136,6 +136,13 @@ + + + + target_user + + + @@ -153,11 +160,7 @@ target_user - - - target_user - - + cron_location @@ -173,11 +176,7 @@ target_user - - - target_user - - + cron_location From 2fcfc38db637fcc69bd29186d3eaac655506d445 Mon Sep 17 00:00:00 2001 From: girlier Date: Thu, 30 Apr 2026 00:12:48 +0100 Subject: [PATCH 16/21] Fix sudo puppet module dependency in cron_tar_wildcard - Added utilities/unix/puppet_module/sudo to - sudo::conf requires sudo class which needs sudo puppet module loaded - Matches pattern used in all other sudo-using vulnerability modules - This was the root cause of the Vagrant provisioning error --- .../cron_tar_wildcard/secgen_metadata.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml index 07965bb2e..f510cdf88 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml @@ -49,6 +49,7 @@ utilities/unix/puppet_module/cron_new + utilities/unix/puppet_module/sudo From 5db6a09a87a9a7474d2ca75f1c67575bd9c02cc2 Mon Sep 17 00:00:00 2001 From: girlier Date: Thu, 30 Apr 2026 00:43:44 +0100 Subject: [PATCH 17/21] CRITICAL FIX: Separate requires blocks for each puppet module dependency - Multiple in ONE block only selects ONE module - Each dependency must have its OWN block - SecGen's select_modules() selects first matching module from search_list - This was why sudo puppet module wasn't being loaded despite being listed Root cause: module_reader.rb parses all module_paths in one requires block into a single hash, and select_modules only returns ONE module match --- .../cron_tar_wildcard/secgen_metadata.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml index f510cdf88..6120ef8ff 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/secgen_metadata.xml @@ -49,6 +49,8 @@ utilities/unix/puppet_module/cron_new + + utilities/unix/puppet_module/sudo From 9eff587bc8f5413e0c007fb348a3da654cf3cb58 Mon Sep 17 00:00:00 2001 From: girlier Date: Thu, 30 Apr 2026 00:59:06 +0100 Subject: [PATCH 18/21] Fix: Create cron_location directory before placing files - random_file_path can select nested paths like /home/user/.config/local - These directories don't exist by default, causing Puppet file creation to fail - Added file resource to ensure cron_location directory exists first - Added require dependencies to cascade: cron_location -> backup_dir -> cron job Error was: 'No such file or directory - A directory component in /home/user/.config/local/cron.sh.lock does not exist' --- .../cron_tar_wildcard/manifests/config.pp | 11 +++++++++- .../cron_writable_script/manifests/config.pp | 20 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp index e2af8e779..5e75cc797 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_tar_wildcard/manifests/config.pp @@ -36,6 +36,14 @@ default => "/home/${cron_user}", } + # Ensure cron_location directory exists (may be nested like /home/user/.config/local) + file { $cron_location: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + # Declare sudo class at top level (sudo::conf requires $sudo::config_dir) class { 'sudo': config_file_replace => false, @@ -83,7 +91,7 @@ owner => $backup_dir_owner, group => $backup_dir_group, mode => $backup_dir_mode, - require => Exec['validate_restricted_user'], + require => [Exec['validate_restricted_user'], File[$cron_location]], } } else { $backup_dir_owner = 'root' @@ -109,6 +117,7 @@ owner => $backup_dir_owner, group => $backup_dir_group, mode => $backup_dir_mode, + require => File[$cron_location], } } diff --git a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp index 102205a42..716e4abab 100644 --- a/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp +++ b/modules/vulnerabilities/unix/access_control_misconfigurations/cron_writable_script/manifests/config.pp @@ -37,16 +37,28 @@ default => "/home/${cron_user}", } + # Ensure cron_location directory exists (may be nested like /home/user/.config/local) + file { $cron_location: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + + # Define requirements for the script file + if $cron_user == 'root' { + $cron_script_requires = [File[$cron_location]] + } else { + $cron_script_requires = [Exec["validate_cron_user_${cron_user}"], File[$cron_location]] + } + file { $cron_script_path: ensure => file, owner => 'root', group => 'root', mode => '0777', content => "#!/bin/bash -p\necho '${cron_message}' >> /tmp/cron.log\n", - require => $cron_user ? { - 'root' => undef, - default => Exec["validate_cron_user_${cron_user}"], - }, + require => $cron_script_requires, } cron { 'writable_cron_script': From 8c07f84aee9bc9b8e0238cd16ba011bf5516370a Mon Sep 17 00:00:00 2001 From: girlier Date: Thu, 30 Apr 2026 03:08:20 +0100 Subject: [PATCH 19/21] Simplify scenario: single machine, no SSH, no Kali MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed attack_vm (Kali) system for faster build - Removed SSH vulnerability requirement - Single Debian server with local access - Fixed lowpriv credentials: lowpriv/password (discoverable) - Random target_user for horizontal escalation - Players log in directly to Debian desktop as lowpriv - Two-stage escalation remains: lowpriv → target_user → root - Fixed IP: 192.168.56.10 for easier testing --- scenarios/ctf/root_cron-trol.xml | 77 ++++++++------------------------ 1 file changed, 19 insertions(+), 58 deletions(-) diff --git a/scenarios/ctf/root_cron-trol.xml b/scenarios/ctf/root_cron-trol.xml index 887238910..c551f547f 100644 --- a/scenarios/ctf/root_cron-trol.xml +++ b/scenarios/ctf/root_cron-trol.xml @@ -6,7 +6,7 @@ Root Cron-trol Rosie Fletcher - A two-stage privilege escalation challenge. Gain initial SSH access as a low-privileged user, + A two-stage privilege escalation challenge. Start as a low-privileged user on a local system, then perform horizontal privilege escalation by exploiting a writable cron script owned by another user. Finally, achieve vertical privilege escalation to root through a tar wildcard injection vulnerability in a root-owned cron job. Master the art of cron-based privilege escalation! @@ -42,60 +42,20 @@ cyber kill chain - - attack_vm - - - - - 172.16.0.2 - - 172.16.0.3 - - - - - {"username":"kali","password":"kali","super_user":"true","strings_to_leak":[],"leaked_filenames":[]} - - - - - - {"username":"kali","password":"kali","super_user":"true","strings_to_leak":[],"leaked_filenames":[]} - - - false - - - - - - - - - IP_addresses - - - - - - - - spoiler_admin_pass - - - - + server + - + lowpriv - tiaspbiqe2r + password + + @@ -103,6 +63,7 @@ + @@ -130,12 +91,15 @@ + + + @@ -144,14 +108,7 @@ - - - - spoiler_admin_pass - - - - + horizontal_flag @@ -164,7 +121,7 @@ - + root_flag @@ -178,16 +135,20 @@ cron_location + + true + - IP_addresses + 192.168.56.10 + - spoiler_admin_pass + root From aa4d635706f446ca79bdee3aab650aff1b238f85 Mon Sep 17 00:00:00 2001 From: girlier Date: Thu, 30 Apr 2026 03:11:20 +0100 Subject: [PATCH 20/21] Change lowpriv to random username with fixed password - lowpriv_user: now uses username_generator (random) - lowpriv_pass: fixed as tiaspbiqe2r (shown in hints) - Players see available usernames on KDE login screen - Added hints for password and exploitation techniques --- scenarios/ctf/root_cron-trol.xml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scenarios/ctf/root_cron-trol.xml b/scenarios/ctf/root_cron-trol.xml index c551f547f..e64985b0d 100644 --- a/scenarios/ctf/root_cron-trol.xml +++ b/scenarios/ctf/root_cron-trol.xml @@ -6,7 +6,7 @@ Root Cron-trol Rosie Fletcher - A two-stage privilege escalation challenge. Start as a low-privileged user on a local system, + A two-stage privilege escalation challenge. Login to the desktop as a low-privileged user (password: tiaspbiqe2r), then perform horizontal privilege escalation by exploiting a writable cron script owned by another user. Finally, achieve vertical privilege escalation to root through a tar wildcard injection vulnerability in a root-owned cron job. Master the art of cron-based privilege escalation! @@ -15,6 +15,11 @@ attack-ctf pwn-ctf intermediate + + Login password: tiaspbiqe2r + Check sudo -l and crontab -l for cron job hints + Look for world-writable scripts executed by cron + tar wildcard injection: --checkpoint=1 --checkpoint-action=exec=sh shell.sh @@ -47,12 +52,12 @@ server - + - lowpriv + - password + tiaspbiqe2r From 19d020c19b9c1c23d21aacfa7ed0df02f1b6ea5b Mon Sep 17 00:00:00 2001 From: girlier Date: Thu, 30 Apr 2026 08:14:27 +0100 Subject: [PATCH 21/21] Update scenario: separate cron locations, KDE autologin, DHCP network - Split cron_location into horizontal_cron_location and vertical_cron_location - Add kde_minimal utility with autologin for lowpriv_user - Change network to DHCP (no fixed IP) - Use strong_password for target_pass (harder to crack) - Remove explicit hints (password in description only) - Add securerandom require to generator - Use Random.new for explicit randomness control --- .../random_file_path/secgen_local/local.rb | 3 +- scenarios/ctf/root_cron-trol.xml | 45 ++++++++++++------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/modules/generators/random/random_file_path/secgen_local/local.rb b/modules/generators/random/random_file_path/secgen_local/local.rb index 4f9c36657..d8989abe0 100644 --- a/modules/generators/random/random_file_path/secgen_local/local.rb +++ b/modules/generators/random/random_file_path/secgen_local/local.rb @@ -1,6 +1,7 @@ #!/usr/bin/ruby require_relative '../../../../../lib/objects/local_string_generator.rb' require 'logger' +require 'securerandom' class FilePathGenerator < StringGenerator attr_accessor :selected_location @@ -154,7 +155,7 @@ def select_random_location available_locations = writable_locations end - selected = available_locations.sample + selected = available_locations.sample(random: Random.new) @logger.info("=" * 60) @logger.info("SELECTED PATH: #{selected}") @logger.info("Username context: #{@username}") diff --git a/scenarios/ctf/root_cron-trol.xml b/scenarios/ctf/root_cron-trol.xml index e64985b0d..3007bdac0 100644 --- a/scenarios/ctf/root_cron-trol.xml +++ b/scenarios/ctf/root_cron-trol.xml @@ -9,17 +9,12 @@ A two-stage privilege escalation challenge. Login to the desktop as a low-privileged user (password: tiaspbiqe2r), then perform horizontal privilege escalation by exploiting a writable cron script owned by another user. Finally, achieve vertical privilege escalation to root through a tar wildcard injection vulnerability in a - root-owned cron job. Master the art of cron-based privilege escalation! + root-owned cron job. Master the art of cron-based privilege escalation! Login password: tiaspbiqe2r ctf attack-ctf pwn-ctf intermediate - - Login password: tiaspbiqe2r - Check sudo -l and crontab -l for cron job hints - Look for world-writable scripts executed by cron - tar wildcard injection: --checkpoint=1 --checkpoint-action=exec=sh shell.sh @@ -65,7 +60,7 @@ - + @@ -96,6 +91,15 @@ + + + lowpriv_user + + + true + + + @@ -104,8 +108,15 @@ - - + + + + + target_user + + + + target_user @@ -122,7 +133,7 @@ target_user - cron_location + horizontal_cron_location @@ -138,22 +149,22 @@ target_user - cron_location + vertical_cron_location true - - - 192.168.56.10 - - + + + + + - root + spoiler_admin_pass