Lab 07 — Bandit 15 to 20: TLS, port scans, and borrowed privileges
0 / 5 steps
The goal
Starting from your Bandit level 15 login, work through five challenges to reach level 20. This stretch moves you off files and onto services and permissions: an encrypted connection, a port scan, spotting what changed, logging in without a shell, and borrowing another user’s privileges. Each level hands you the next password once you solve it — you are not told any of them here.
Where this runs. Everything below happens on OverTheWire’s Bandit server, which they built for exactly this. Step 02 includes a port scan — aimed only at localhost on the Bandit server, which is what the level asks for. Scanning anything else without permission is not part of this lab and not legal. This page publishes none of OverTheWire’s passwords or level text; their Bandit page is the source of truth.
What changes at level 15. Until now the answer has always been sitting in a file. From here it lives behind a network service, or behind a permission you do not have yet. That is a much closer match to real work: most of an investigation or a test is working out what is listening, how to talk to it, and whose rights you are running with.
Before you start. You should be at a Bandit level 15 prompt — which means Lab 05 is behind you, including talking to a port with nc. You also want your own Linux machine from Lab 00 open, because step 02 ends with a key you will use from there.
Steps
01Speak TLS to a port
In Lab 05 you sent the password to a local port with nc. Level 15 looks the same, except the service on port 30001 only talks over an encrypted TLS connection. nc sends plain text, so the service never understands you. You need a client that does the TLS handshake first.
$ openssl s_client -connect localhost:30001 -quiet
When it connects, paste your current password and press Enter. The reply is the next one. ncat --ssl localhost 30001 does the same job if you prefer it.
Why -quiet matters. Without it, s_client treats a line starting with certain letters as a command to itself — R renegotiates, Q quits, k updates keys — instead of sending it. If your password happens to start with one, it never arrives. -quiet switches that off and hides the certificate chatter.
Why this matters. HTTPS, SMTPS, LDAPS and a dozen others are ordinary plain-text conversations wrapped in TLS. openssl s_client is how you talk to any of them by hand — and how you read a server’s certificate when something about it looks wrong.
02Find the one port that matters
Level 16 gives you a range — ports 31000 to 32000 on localhost — and nothing else. Several of them are listening. Most just echo back whatever you send. One speaks TLS and answers the password with something useful. Your job is to find it without trying a thousand ports by hand.
$ nmap -sV -p 31000-32000 localhost
the shape of what comes back — your port numbers will differ PORT STATE SERVICE VERSION 3xxxx/tcp open echo 3xxxx/tcp open ssl/echo 3xxxx/tcp open ssl/unknown ...
Read the SERVICE column. Plain echo is out — no TLS. ssl/echo speaks TLS but only repeats you. The one nmap can’t name is your candidate. Connect to it exactly as in step 01, swapping in its port, and paste the password:
$ openssl s_client -connect localhost:PORT -quiet
The right port answers with a private key — a block starting -----BEGIN RSA PRIVATE KEY----- — instead of a password. That key logs you in as bandit17. Copy the whole block, both marker lines included, and save it on your own Linux machine, then lock it down and use it from there:
$ nano bandit17.key
$ chmod 600 bandit17.key && ssh -i bandit17.key -p 2220 bandit17@bandit.labs.overthewire.org
Why this matters. -sV is the difference between “something is listening” and “this is what it is” — the same flag from Lab 01, now doing real work. Mapping which services run on a machine you are already on is a standard move after getting a foothold, and a standard thing for defenders to watch for.
03Spot what changed
As bandit17 you have two files, passwords.old and passwords.new. They are nearly identical. The password is the one line that changed.
$ diff passwords.old passwords.new
diff prints only the lines that differ. Lines starting < come from the first file, lines starting > from the second. You want the > line — it is in the new file.
Heads up. When you log in as bandit18 you will be thrown straight back out with a goodbye message. That is not a mistake on your part — it is the next step.
Why this matters. “What changed?” is one of the most useful questions in security. Config drift, a tampered file, the one line an attacker added to a startup script — comparing a known-good copy with the current one finds all of them.
04Log in without a shell
Someone has edited bandit18’s .bashrc — the script that runs when an interactive shell starts — so that it logs you out immediately. You can’t fix it from inside, because you never get inside. So don’t ask for a shell at all.
$ ssh -p 2220 bandit18@bandit.labs.overthewire.org cat readme
Anything after the hostname is a command for ssh to run on the other end. It logs in, runs cat readme, prints the result and disconnects — no interactive shell, so the part of .bashrc that kicks you out never fires. Use ls in place of cat readme first if you want to look around.
Why this matters. Running one command over ssh is how most automation, backups and deployment scripts work. And the lesson cuts the other way too: a login script is a convenience, not a security control. Anything it “blocks”, someone can walk around.
05Borrow someone else’s permissions
bandit19’s home directory holds a program you can run but did not write. Look at its permissions:
$ ls -la
Where you would expect an x in the owner’s permissions, there is an s. That is the setuid bit: whoever runs the program, it runs with the owner’s rights — here, bandit20’s. Run it with no arguments to see how it wants to be used, then prove who it makes you:
$ ./bandit20-do id
Look for euid — the effective user — in the output. Now use those borrowed rights to read the one file you could not read as yourself:
$ ./bandit20-do cat /etc/bandit_pass/bandit20
Why this matters. setuid is how an ordinary user can change their own password in a file only root may write. It is also one of the classic ways to escalate privileges: a setuid program that lets you run other commands hands you its owner’s rights. Checking for unexpected setuid binaries is on every Linux privilege-escalation checklist for exactly this reason.
You have spoken TLS by hand, found a hidden service with a version scan, logged in with a key you were handed, spotted a single changed line, run a command through ssh without a shell, and borrowed another user’s rights with setuid. That is a real recon-to-privilege chain in miniature.
If it didn’t work
- s_client prints RENEGOTIATING, KEYUPDATE or DONE instead of an answer. You left off -quiet and your password starts with a letter s_client treats as a command. Add the flag and try again.
- The nmap scan crawls. -sV probes every open port it finds, which takes a minute or two here. Let it finish. If you are impatient, scan without -sV first to list the open ports, then run -sV on just those.
- ssh says “UNPROTECTED PRIVATE KEY FILE”. The key is readable by others. chmod 600 bandit17.key.
- “Load key … invalid format” or “error in libcrypto”. The key didn’t survive the copy. It needs both -----BEGIN and -----END lines, no extra spaces, and a line break at the very end. Copy it again and paste into nano on Linux rather than a Windows text editor.
- bandit18 still logs you out. The command has to be on the same line as the ssh login, after the hostname — not typed afterwards.
- “Permission denied” reading the bandit20 password. You ran cat on its own. It only works through the setuid program: ./bandit20-do cat ….
Your turn — no walkthrough
Hunt setuid on your own machine. On your Kali VM, list every setuid binary on the system — one find command with a permission filter does it, and Lab 03 taught you the rest. For each one, decide whether it should be setuid. Then look one up on GTFOBins and work out what would happen if an ordinary program like find were setuid root. You can test that safely on your own VM by giving a copy of a binary the bit — never the original.
Keep the evidence. Your list of setuid binaries, one flagged as “expected” with the reason, and one sentence on how you would detect a new one appearing. That last line is a real detection idea.
Clean up
Remove any setuid test copy you made on Kali with sudo rm. Delete bandit17.key from your machine once you are past level 17 — it is a practice key, and practice keys should never linger. Type exit to leave Bandit, and keep the passwords to yourself.
Before you leave — prove it
Without scrolling up: one, why can’t nc talk to the level 15 service? Two, in the nmap output, what told you which port to try? Three, when you run a setuid program, whose permissions does it use — and why is that dangerous if the program can run other commands?
If the third answer came easily, you already understand the core of Linux privilege escalation.
What you learned
- openssl s_client — talking to a TLS service by hand, and why -quiet matters
- nmap -sV on a port range — finding the one service that isn’t like the others
- SSH keys you didn’t make — saving, locking down and using a key you were handed
- diff — finding exactly what changed between two files
- ssh remote commands — running one command without an interactive shell
- setuid — borrowed privileges, euid, and why they are a privilege-escalation favourite
Put it on your resume. Completed OverTheWire Bandit levels 15–20: TLS connections with openssl, port scanning, diff, and setuid privilege use. Change it to match what you actually did.
Tried it? Tell us
Nova built this lab from Steven’s ideas, and most StashGrid labs haven’t had a full run yet. If a step broke, behaved differently for you, or you know a better way, tell us. Ideas for the next lab are welcome too — no promises on timing.
NextLab 08 — Watch your own machine with a Wazuh agent→
Go deeper
- OverTheWire Bandit — the wargame itself, free and community-run
- Bandit 10–15 for the levels just before this one
- Nmap cheat sheet and common ports for everything step 02 touched
- Linux privilege escalation cheat sheet — where step 05 leads
Original walkthrough. The wargame belongs to the OverTheWire community; this page reproduces none of their level text and none of their passwords, in line with their rules for content creators. Commands were checked against their documented behaviour — but Bandit changes, so if a step here no longer matches what you see, tell me and I will fix it.