π§ OverTheWire Bandit Level 23: Exploiting Cron Jobs with Variable Substitution
Level 23 builds on what you learned in Level 22 about cron jobs, but adds a twist: the script uses variable substitution and MD5 hashing to create dynamic file paths. This level teaches you how to analyze shell scripts, understand variable substitution, and exploit the difference between who runs a script versus who executes it.
Level 23 teaches you:
- Analyzing shell scripts written by others
- Understanding variable substitution (
whoami,$myname) - MD5 hashing and how it's used
- The difference between script execution context and cron execution context
- How to manipulate script logic to your advantage
If you've made it this far, you understand cron jobs. Now you're learning how to analyze and exploit scripts that use dynamic valuesβa common pattern in privilege escalation.
π― The Objective
After logging into bandit22, your goal is to find the password for Level 23. A program is running automatically from cron, similar to Level 22, but this time the script uses variable substitution to create dynamic file paths based on the user running it.
What Level 23 teaches:
- Reading and understanding shell scripts
- Variable substitution in bash
- MD5 hashing
- Understanding execution context
- Exploiting dynamic file paths
The challenge: The cron job runs a script that uses whoami to determine the user, creates an MD5 hash, and writes the password to a file with that hash as the name. You need to figure out what hash the cron job creates (when it runs as bandit23) and read that file.
π Understanding the Problem
Let's start by connecting to Level 22 and exploring:
sshpass -p `cat bandit22` ssh bandit22@bandit.labs.overthewire.org -p 2220
Once connected, let's check the cron configuration:
cd /etc/cron.d/
ls -la
The problem: The cron job runs a script that uses whoami to get the current user, creates an MD5 hash of "I am user $username", and writes the password to /tmp/<hash>. When the cron runs as bandit23, it creates one hash. When you run it as bandit22, it creates a different hash. You need to figure out what hash the cron job creates.
π§ Understanding Variable Substitution and MD5 Hashing
Here's what's happening: The script uses whoami to get the current user, then creates an MD5 hash based on that user's name.
What Is Variable Substitution?
Variable substitution is when a shell replaces a variable with its value. In bash:
myname=$(whoami) # Command substitution - runs whoami and stores result
echo $myname # Variable expansion - prints the value
Common substitution types:
$(command)β Command substitution (runs command, returns output)${variable}β Variable expansion$variableβ Simple variable expansion
Understanding MD5 Hashing
MD5 (Message Digest 5) is a cryptographic hash function that takes input and produces a fixed-size hash value (32 hexadecimal characters).
Properties of MD5:
- Deterministic β Same input always produces same output
- One-way β Can't reverse the hash to get original input
- Fixed size β Always produces 32-character hex string
- Fast β Designed for speed
In Level 23: The script creates an MD5 hash of "I am user bandit23" (when run by cron) or "I am user bandit22" (when you run it).
The Execution Context Problem
The key insight: When you run a script, whoami returns YOUR username. When cron runs a script, whoami returns the username specified in the cron job.
Example:
- You run script β
whoami=bandit22β Hash of "I am user bandit22" - Cron runs script as
bandit23βwhoami=bandit23β Hash of "I am user bandit23"
The challenge: You need the hash that cron creates (with bandit23), not the hash you create (with bandit22).
π Step-by-Step Walkthrough
Step 1: Connect to Level 22
sshpass -p `cat bandit22` ssh bandit22@bandit.labs.overthewire.org -p 2220
Step 2: Navigate to the Cron Directory
cd /etc/cron.d/
ls -la
Look for cronjob_bandit23.
Step 3: Read the Cron Configuration
cat cronjob_bandit23
What you'll see:
@reboot bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
Breaking this down:
@rebootβ Runs once at system boot* * * * *β Runs every minutebandit23β Runs as userbandit23/usr/bin/cronjob_bandit23.shβ The script being executed
Step 4: Read the Script
Now let's read the actual script:
cat /usr/bin/cronjob_bandit23.sh
What you'll see:
#!/bin/bash
myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)
echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"
cat /etc/bandit_pass/$myname > /tmp/$mytarget
Breaking this down:
myname=$(whoami)β Gets current username (will bebandit23when run by cron)echo I am user $mynameβ Creates string "I am user bandit23"md5sumβ Creates MD5 hash of that stringcut -d ' ' -f 1β Extracts just the hash (removes filename if present)mytargetβ Stores the hash valuecat /etc/bandit_pass/$myname > /tmp/$mytargetβ Writes password to/tmp/<hash>
The key: When cron runs this as bandit23, whoami returns bandit23, so it creates a hash of "I am user bandit23" and writes to /tmp/<that_hash>.
Step 5: Test the Script Yourself
Let's run the script to see what it does:
bash /usr/bin/cronjob_bandit23.sh
What happens:
- Script runs as
bandit22(you) whoamireturnsbandit22- Creates hash of "I am user bandit22"
- Writes
bandit22password to/tmp/<hash_of_bandit22>
What you'll see:
Copying passwordfile /etc/bandit_pass/bandit22 to /tmp/8169b67bd894ddbb4412f91573b38b49
This shows you the script works, but it's creating a file for bandit22, not bandit23.
Step 6: Calculate the Correct Hash
The cron job runs as bandit23, so we need to calculate what hash it creates. Let's recreate the logic:
echo "I am user bandit23" | md5sum | cut -d ' ' -f 1
What you'll see: A 32-character hexadecimal stringβthis is the hash that the cron job creates!
Example output:
8ca319486bfbbc3663ea0fbe81326349
(Your hash will be differentβMD5 is deterministic, so "I am user bandit23" always produces the same hash.)
Step 7: Read the Password File
Now that you know the hash, read the file:
cat /tmp/8ca319486bfbbc3663ea0fbe81326349
Important: Replace the hash with the actual hash you calculated.
What you'll see: The password for Level 23!
Why this works: The cron job has already run (it runs every minute), so it has already created the file /tmp/<hash> with the bandit23 password. You just need to calculate what that hash is.
Step 8: Save the Password
Copy the password and save it:
On Linux/macOS:
echo "PASSWORD_HERE" > bandit23
On Windows (PowerShell):
"PASSWORD_HERE" | Out-File -FilePath bandit23 -NoNewline
Step 9: Connect to Level 23
sshpass -p `cat bandit23` ssh bandit23@bandit.labs.overthewire.org -p 2220
π‘ Understanding Shell Scripting in Depth
Let's dive deeper into the script components:
Command Substitution
Command substitution ($(command)) runs a command and replaces it with the output:
myname=$(whoami)
# Equivalent to:
# whoami > temp_file
# myname=$(cat temp_file)
# rm temp_file
Common uses:
$(date)β Get current date/time$(pwd)β Get current directory$(ls)β Get file listing$(whoami)β Get current username
Variable Expansion
Variable expansion replaces $variable with its value:
myname="bandit23"
echo $myname # Prints: bandit23
echo "I am $myname" # Prints: I am bandit23
In the script:
echo I am user $myname
# When myname="bandit23", this becomes:
# echo I am user bandit23
MD5 Hashing
MD5 creates a hash of input:
echo "test" | md5sum
# Output: 098f6bcd4621d373cade4e832627b4f6 -
The cut command:
cut -d ' ' -f 1β Splits by space, takes first field- Removes the
-thatmd5sumadds when reading from stdin
Complete pipeline:
echo "I am user bandit23" | md5sum | cut -d ' ' -f 1
# 1. echo creates: "I am user bandit23"
# 2. md5sum hashes it: "8ca319486bfbbc3663ea0fbe81326349 -"
# 3. cut extracts: "8ca319486bfbbc3663ea0fbe81326349"
Understanding Execution Context
Execution context matters for whoami:
- When you run:
whoamiβbandit22(your username) - When cron runs:
whoamiβbandit23(user specified in cron)
Why this matters: The script's behavior changes based on who executes it. This is a common source of privilege escalation vulnerabilities.
π Real-World Context
Why does this matter in penetration testing?
Understanding script execution context and variable substitution is essential for:
1. Analyzing Scripts
When you find scripts during a penetration test:
# Read the script
cat /path/to/script.sh
# Understand what it does
# - What variables does it use?
# - What commands does it execute?
# - What files does it create?
# - Who runs it?
2. Exploiting Variable Substitution
If a script uses whoami or other user-dependent variables:
# Understand what it does for different users
# Can you make it run as a different user?
# Can you manipulate the variables?
3. MD5 and Hashing
MD5 is commonly used for:
- File integrity checks
- Password hashing (deprecated, but still seen)
- Creating unique identifiers
- Generating file names
Security note: MD5 is cryptographically broken and shouldn't be used for security purposes, but it's still commonly found in scripts.
4. Real-World Examples
Common vulnerabilities:
- Scripts using
whoamithat can be exploited - Predictable file names based on hashes
- Scripts that write to world-readable locations
- Variable substitution vulnerabilities
The skill you're learning: How to analyze scripts and understand execution context. This is essential for:
- Privilege escalation
- Script analysis
- Finding misconfigurations
- Exploiting automation
π οΈ Alternative Methods
Here are different ways to approach Level 23:
Method 1: Calculate Hash Directly (Recommended)
echo "I am user bandit23" | md5sum | cut -d ' ' -f 1
cat /tmp/<hash>
Pros: Simple, direct, works immediately Cons: None really
Method 2: Run Script and Analyze
bash /usr/bin/cronjob_bandit23.sh
# See what hash it creates for bandit22
# Then calculate what it would create for bandit23
echo "I am user bandit23" | md5sum | cut -d ' ' -f 1
cat /tmp/<hash>
Pros: Helps understand the script Cons: Extra step
Method 3: Recreate Script Logic
myname="bandit23"
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)
echo $mytarget
cat /tmp/$mytarget
Pros: Shows the exact logic Cons: More verbose
For Level 23, use Method 1 β it's the most straightforward.
π¨ Common Mistakes
Mistake 1: Using the Wrong Hash
Wrong: Calculating hash with bandit22 instead of bandit23.
Right: Use bandit23 since that's who the cron job runs as.
Why: The cron job runs as bandit23, so whoami returns bandit23, creating a hash of "I am user bandit23".
Mistake 2: Not Understanding Execution Context
Wrong thinking: "I'll run the script and it will create the file I need."
Reality: When you run the script, it creates a file for bandit22. When cron runs it, it creates a file for bandit23.
Solution: Understand that whoami returns different values depending on who executes the script.
Mistake 3: Forgetting to Extract Just the Hash
Wrong:
echo "I am user bandit23" | md5sum
# Output: 8ca319486bfbbc3663ea0fbe81326349 -
# Includes the dash!
Right:
echo "I am user bandit23" | md5sum | cut -d ' ' -f 1
# Output: 8ca319486bfbbc3663ea0fbe81326349
# Clean hash only
Why: md5sum adds a - when reading from stdin. You need cut to remove it.
Mistake 4: Not Reading the Script First
Wrong: Trying to guess what the script does.
Right: Read the script to understand its logic.
Why: The script shows you exactly how it creates the hash. Reading it makes the solution clear.
Mistake 5: Overcomplicating It
Wrong thinking: "I need to modify the script or wait for it to run."
Reality: The cron job has already run and created the file. You just need to calculate what hash it used and read that file.
Solution: Calculate the hash that cron creates, then read the file with that name.
π» Practice Exercise
Try these to reinforce what you learned:
-
Understand command substitution:
myname=$(whoami) echo $myname -
Practice MD5 hashing:
echo "test" | md5sum echo "test" | md5sum | cut -d ' ' -f 1 -
Test variable expansion:
name="bandit23" echo "I am user $name" | md5sum | cut -d ' ' -f 1 -
Analyze the script step by step:
myname=$(whoami) echo $myname mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1) echo $mytarget
π Understanding Script Analysis
This level introduces script analysis concepts:
What Is Script Analysis?
Script analysis is the process of reading and understanding what a script does:
- Read the script β Understand the code
- Identify variables β What values are used?
- Trace execution β What happens step by step?
- Understand context β Who runs it? When?
- Find vulnerabilities β Can it be exploited?
Why Script Analysis Matters
Understanding scripts is essential for:
- Privilege escalation
- Finding misconfigurations
- Exploiting automation
- Security auditing
- Understanding system behavior
The skill you're learning: How to read and analyze shell scripts. This is fundamental for:
- Penetration testing
- System security
- Privilege escalation
- Security auditing
π What's Next?
Level 24 will likely introduce another system concept or build on script analysis. You'll continue building on the concepts you've learned about cron jobs, shell scripting, and privilege escalation.
Before moving on, make sure you:
- β
Understand command substitution (
$(command)) - β
Know how variable expansion works (
$variable) - β Can calculate MD5 hashes
- β
Understand execution context (
whoamibehavior) - β Can analyze shell scripts
π Key Takeaways
After completing Level 23, you should understand:
- Command substitution β Using
$(command)to capture output - Variable expansion β How
$variableworks - MD5 hashing β Creating hashes with
md5sum - Execution context β How
whoamichanges based on who runs the script - Script analysis β Reading and understanding shell scripts
π― Quick Reference
| Concept | Explanation | Example |
|---|---|---|
| Command substitution | Run command, capture output | myname=$(whoami) |
| Variable expansion | Replace variable with value | echo $myname |
| MD5 hash | Create hash of input | echo "text" | md5sum |
cut | Extract fields | cut -d ' ' -f 1 |
whoami | Get current username | whoami |
π Advanced: Understanding MD5 and Hashing
If you want to go deeper, here's how MD5 works:
MD5 Properties
MD5 characteristics:
- Deterministic β Same input always produces same output
- Fixed size β Always 32 hexadecimal characters (128 bits)
- One-way β Can't reverse to get original input
- Fast β Designed for speed, not security
MD5 Security Issues
Why MD5 is broken:
- Vulnerable to collision attacks
- Can create two different inputs with same hash
- Not suitable for password hashing
- Not suitable for digital signatures
Still used for:
- File integrity checks (non-security)
- Creating unique identifiers
- Generating file names
- Quick checksums
Alternative Hash Functions
Better alternatives:
- SHA-256 β Secure, widely used
- SHA-512 β More secure, slower
- bcrypt β For password hashing
- Argon2 β Modern password hashing
In Level 23: MD5 is used for creating a predictable filename, not for security, so it's acceptable here.
Questions about Level 23, shell scripting, or MD5 hashing? Reach out directly:
- Email: m1k3@msquarellc.net
- Phone: (559) 670-3159
- Schedule: Book a free consultation
M Square LLC
Cybersecurity | Penetration Testing | No-Nonsense Advice