← Back to list

OverTheWire Bandit: Levels 17 to 22 — Day 4 of the Wargame

Series: Daily Bandit — N levels a day until I finish all 34.

Justin Jude Cabodil · 2026-06-09 01:29 · 4 claps · 3.3 min read
#linux #terminal #bash #bandit-walkthrough
Open on Medium ↗
Wiki topics: 🔓 · Open Source

OverTheWire Bandit: Levels 17 to 22 — Day 4 of the Wargame

Series: Daily Bandit — N levels a day until I finish all 34.

Day 3 was about unraveling compressed data. Day 4 is about privilege — running commands as someone else, bypassing a hostile shell, and following the trail of automated scripts.

This batch introduced setuid binaries, cron jobs, and the art of reading the system to find what wasn’t handed to you.

Level 16 → Level 17: Diff Two Files

Log in as bandit17 using the private key from the previous level.

bandit17@bandit:~$ ls
passwords.new  passwords.old

Two files. Nearly identical. The password is the only line that changed between them.

bandit17@bandit:~$ diff passwords.new passwords.old
42c42
< x2gLTTjFwMOhQ8oWNbMN362QKxfRqGlO
---
> KxOU4IzbXM8j8HeAWPAXTd1eC77mp1qV

diff compares line by line. < marks lines only in the first file, > marks lines only in the second. The new password is the one that doesn't exist in the old file.

Lesson learned: diff file1 file2 shows what changed. < is the first file, > is the second.

Password: x2gLTTjFwMOhQ8oWNbMN362QKxfRqGlO

Level 17 → Level 18: Bypassing .bashrc

$ ssh -p 2220 bandit18@bandit.labs.overthewire.org

I logged in and immediately got:

Byebye !
Connection closed.

The challenge says someone modified .bashrc to log you out on SSH login. SSH runs the shell, the shell sources .bashrc, .bashrc exits. The fix is to skip the shell entirely:

$ ssh -p 2220 -t bandit18@bandit.labs.overthewire.org bash --norc --noprofile

--norc skips .bashrc. --noprofile skips .profile. Combined, they give me a bare shell with no initialization scripts.

bash-5.2$ ls
readme
bash-5.2$ cat readme
cGWpMaKXVwDUNgPAVJbWYuGHVn9zl3j8

Lesson learned: SSH runs your shell, which runs your rc files. bash --norc --noprofile gives you a clean shell that ignores all startup scripts.

Password: cGWpMaKXVwDUNgPAVJbWYuGHVn9zl3j8

Level 18 → Level 19: Setuid Binaries

bandit19@bandit:~$ ls
bandit20-do

A single binary. Running it without arguments gives a hint:

bandit19@bandit:~$ ./bandit20-do
Run a command as another user.
Example: ./bandit20-do whoami

This is a setuid binary — notice the s in the permissions:

bandit19@bandit:~$ ls -l bandit20-do
-rwsr-x---  1 bandit20 bandit19 14888 Apr  3 15:17 bandit20-do

The s in the owner position means: when executed, it runs with the file owner's privileges (bandit20), not the user who ran it (bandit19). So I can run commands as bandit20.

bandit19@bandit:~$ ./bandit20-do whoami
bandit20
bandit19@bandit:~$ ./bandit20-do cat /etc/bandit_pass/bandit20
0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO

Lesson learned: Setuid binaries (permission rws instead of rwx) execute with the owner's privileges. Used correctly, they're essential for controlled privilege escalation.

Password: 0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO

Level 19 → Level 20: Netcat Listener

bandit20@bandit:~$ ls
suconnect

This binary connects to a port on localhost, reads one line, and compares it to the current level’s password. If it matches, it sends back the next password.

I need two terminals. In one, I start a netcat listener on port 8888:

bandit20@bandit:~$ nc -lvnp 8888
Listening on 0.0.0.0 8888

In the other, I run suconnect targeting the same port:

bandit20@bandit:~$ ./suconnect 8888
Read: 0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO
Password matches, sending next password

Back in the first terminal, the listener received the connection, and I pasted the current password:

Connection received on 127.0.0.1 53504
0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO
EeoULMCra2q0dSkYj561DX7s1CpBuOBt

The suconnect binary read what I sent, verified it against the stored password, and sent back the next one.

Lesson learned: nc -lvnp <port> starts a TCP listener. Combined with a binary that connects to it, you can create simple client-server password verification loops.

Password: EeoULMCra2q0dSkYj561DX7s1CpBuOBt

Level 20 → Level 21: Cron Jobs

bandit21@bandit:~$

Nothing in the home directory. The password is managed by a cron job running as bandit22.

bandit21@bandit:/etc/cron.d$ cat cronjob_bandit22
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null

Every minute, bandit22 runs a script. Let’s read it:

bandit21@bandit:/etc/cron.d$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

The cron job writes the password to a world-readable temp file every minute. Since the file has chmod 644, anyone can read it:

bandit21@bandit:/etc/cron.d$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
tRae0UfB9v0UzbCdn9cY0gQnds9GF58Q

The trail was: cron config → shell script → temp file. Always follow the breadcrumbs.

Lesson learned: Cron jobs run scripts on a schedule. Check /etc/cron.d/ for configuration, then read the referenced scripts to understand what they do and where they leave data.

Password: tRae0UfB9v0UzbCdn9cY0gQnds9GF58Q

Wrapping Up Day 4

Five levels. Here’s the map:

  • Level 17→18 — File comparison: diff
  • Level 18→19 — Shell bypass: ssh -t bash --norc --noprofile
  • Level 19→20 — Setuid execution: ./bandit20-do cat /etc/bandit_pass/bandit20
  • Level 20→21 — TCP listener + client: nc -lvnp + ./suconnect
  • Level 21→22 — Cron analysis: /etc/cron.d/ → shell script → temp file

Three themes ran through this batch: running as someone else (setuid, cron), bypassing restrictions (shell rc, auto-logout), and following trails (config → script → data). The levels are teaching a mental model now, not just individual commands.

Next: Levels 22 → 27. More cron, more setuid, and the first glimpse of more and vim exploitation.

Cheatsheet

# Level 17 → 18
diff passwords.new passwords.old
# Level 18 → 19
ssh -p 2220 -t bandit18@bandit.labs.overthewire.org bash --norc --noprofile
# Level 19 → 20
./bandit20-do cat /etc/bandit_pass/bandit20
# Level 20 → 21 (Terminal 1)
nc -lvnp 8888
# (Terminal 2)
./suconnect 8888
# Then paste password into Terminal 1
# Level 21 → 22
cat /etc/cron.d/cronjob_bandit22
cat /usr/bin/cronjob_bandit22.sh
cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

메타데이터
post_id
23894e019fb3
slug
overthewire-bandit-levels-17-to-22-day-4-of-the-wargame-23894e019fb3
url
https://medium.com/@alph4r1us/overthewire-bandit-levels-17-to-22-day-4-of-the-wargame-23894e019fb3
canonical_url
https://medium.com/@alph4r1us/overthewire-bandit-levels-17-to-22-day-4-of-the-wargame-23894e019fb3
author_url
https://medium.com/@alph4r1us
status
ok
fetched_at
2026-07-17 12:05:36