|
| 1 | +--- |
| 2 | +title: "OverTheWire Bandit: Level 16 to Level 17" |
| 3 | +date: 2026-06-28 09:23:00 +0500 |
| 4 | +categories: [CTF, Bandit] |
| 5 | +tags: [linux, nmap, openssl, tls, port-scanning, ssh, private-key, overthewire, beginner] |
| 6 | +--- |
| 7 | + |
| 8 | +## The Goal |
| 9 | + |
| 10 | +Find which port in the range 31000-32000 on localhost is running an SSL/TLS service that will return the next credentials when given the current password. The other ports either don't speak TLS or just echo back whatever you send them. |
| 11 | + |
| 12 | +## What I Did |
| 13 | + |
| 14 | +### Step 1 — Port Scan |
| 15 | + |
| 16 | +First I needed to find which ports in the range were even open. Used nmap: |
| 17 | + |
| 18 | +```bash |
| 19 | +bandit16@bandit:~$ nmap -p 31000-32000 localhost |
| 20 | +``` |
| 21 | + |
| 22 | +Five ports came back open: |
| 23 | +``` |
| 24 | +31046/tcp open |
| 25 | +31518/tcp open |
| 26 | +31691/tcp open |
| 27 | +31790/tcp open |
| 28 | +31960/tcp open |
| 29 | +``` |
| 30 | + |
| 31 | +### Step 2 — Test Each Port for TLS |
| 32 | + |
| 33 | +Tested each port with `openssl s_client`. Three of them (31046, 31691, 31960) failed immediately with: |
| 34 | + |
| 35 | +``` |
| 36 | +error:0A0000F4:SSL routines:ossl_statem_client_read_transition:unexpected message |
| 37 | +New, (NONE), Cipher is (NONE) |
| 38 | +``` |
| 39 | + |
| 40 | +No certificate, no cipher — these ports don't speak TLS at all. |
| 41 | + |
| 42 | +Two ports (31518 and 31790) completed a full TLS handshake, showing the SnakeOil self-signed certificate and negotiating `TLS_AES_256_GCM_SHA384`. |
| 43 | + |
| 44 | +### Step 3 — Find the Right Port |
| 45 | + |
| 46 | +Tried submitting the password to port 31518 — it echoed the password back and closed. Echo server. |
| 47 | + |
| 48 | +Tried port 31790 interactively — kept getting `Wrong! Please enter the correct current password` even with the correct password. After debugging, the issue was that `openssl s_client` in interactive mode was sending extra characters — specifically pressing the up arrow key accidentally sent `^[[A` to the server alongside the password. |
| 49 | + |
| 50 | +Fixed it by piping the password directly: |
| 51 | + |
| 52 | +```bash |
| 53 | +echo "kS0Hf0u5HiXFwKMKFqXvPdOTNGGa0X8V" | openssl s_client -connect localhost:31790 -quiet |
| 54 | +``` |
| 55 | + |
| 56 | +The server accepted it and returned a private SSH key for bandit17. |
| 57 | + |
| 58 | +### Step 4 — Save the Key and Connect |
| 59 | + |
| 60 | +Copied the private key to my local machine, set correct permissions, and connected as bandit17: |
| 61 | + |
| 62 | +```bash |
| 63 | +chmod 600 bandit17.key |
| 64 | +ssh -i bandit17.key bandit17@bandit.labs.overthewire.org -p 2220 |
| 65 | +``` |
| 66 | + |
| 67 | +## What KEYUPDATE Is |
| 68 | + |
| 69 | +KEYUPDATE appeared in the output and caused confusion. It's a TLS 1.3 feature where the server rotates the session encryption keys mid-connection for additional security. It has nothing to do with whether your password was correct — it just means the server refreshed its encryption state. You can't control it and it doesn't require any action. |
| 70 | + |
| 71 | +## Why Piping Fixed the Interactive Issue |
| 72 | + |
| 73 | +In interactive mode, `openssl s_client` processes everything you type including control characters. Pressing the up arrow sends the escape sequence `^[[A` which gets transmitted to the server as part of your input. The server sees `kS0Hf0u5HiXFwKMKFqXvPdOTNGGa0X8V^[[A` instead of just the password. |
| 74 | + |
| 75 | +Piping with `echo` sends exactly the string you specify plus a newline — nothing else. Cleaner, safer, and scriptable. |
| 76 | + |
| 77 | +## How I Identified Echo Servers vs the Real Server |
| 78 | + |
| 79 | +- **Echo servers** — send back whatever you type. Port 31518 returned the password straight back. |
| 80 | +- **Real server** — validates the input and responds differently. Port 31790 said `Wrong!` when the password was malformed, and returned the private key when it was correct. |
| 81 | + |
| 82 | +The `Wrong!` message was actually useful — it confirmed port 31790 was the checking server, not an echo server. Echo servers don't have logic to validate input. |
| 83 | + |
| 84 | +## Difference From Previous Levels |
| 85 | + |
| 86 | +This level introduced two new concepts on top of what Level 15 taught: |
| 87 | + |
| 88 | +**Port scanning** — instead of being told exactly which port to connect to, you have to discover it yourself. `nmap` scans a range and reports which ports have services listening. |
| 89 | + |
| 90 | +**Echo servers as distractors** — not every open port is the answer. Identifying which services do what requires testing each one, not just connecting to the first open port. |
| 91 | + |
| 92 | +## Commands Used |
| 93 | + |
| 94 | +| Command | What it did | |
| 95 | +|---|---| |
| 96 | +| `nmap -p 31000-32000 localhost` | Found 5 open ports in the range | |
| 97 | +| `openssl s_client -connect localhost:PORT` | Tested each port for TLS support | |
| 98 | +| `echo "password" \| openssl s_client -connect localhost:31790 -quiet` | Sent password cleanly without extra characters | |
| 99 | +| `chmod 600 bandit17.key` | Set correct permissions on the private key | |
| 100 | +| `ssh -i bandit17.key bandit17@...` | Logged into bandit17 using the key | |
0 commit comments