Skip to content

Cron priv esc#367

Open
girlier wants to merge 22 commits into
cliffe:masterfrom
girlier:cron_priv_esc
Open

Cron priv esc#367
girlier wants to merge 22 commits into
cliffe:masterfrom
girlier:cron_priv_esc

Conversation

@girlier
Copy link
Copy Markdown

@girlier girlier commented May 27, 2026

2 Cron based access control misconfiguration

1. Cron Writeable

Creates a globally writeable script that runs as a specified user (default: root) that can be used to escalate privilege

2. Cron Tar Wildcard

Creates a writeable folder and a cron job to run a tar compression with wildcard. A user can create fake checkpoints to run commands on the specified user (default: root)

Scenario

These modules contain a example ctf called root cron-trol that involves horizontal and vertical escalations to gain root through both exploits.

Both modules can be configured to specify file location and user that can be accessed from the exploit.

There is also a random_file_path module which selects a random path (common config file locations) (!For highest reliability specify a path)

girlier and others added 22 commits March 30, 2026 15:10
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 cliffe#11 and cliffe#12.
Includes CTF scenario (cron_privesc.xml) chaining RCE with cron priv-esc
on Debian 12, with 1 shared flag in /root/.
Changed <difficulty>easy</difficulty> to <difficulty>low</difficulty> to
conform with vulnerability_metadata_schema.xsd which only allows
low, medium, or high as valid enumeration values.
…ktop

No Debian 12 server base module exists. Changed to type desktop with
KDE to match the available debian_bookworm_desktop_kde base module.
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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'
- 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)
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)
- Added utilities/unix/puppet_module/sudo to <requires>
- 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
- Multiple <module_path> in ONE <requires> block only selects ONE module
- Each dependency must have its OWN <requires> 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
- 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'
- 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
- 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
- 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant