Post

OverTheWire Bandit: Level 15 to Level 16

OverTheWire Bandit: Level 15 to Level 16

The Goal

Same as the previous level — submit the current password to a port on localhost — but this time the connection must use SSL/TLS encryption. Plain nc won’t work here.

What I Did

Read the man pages for all the commands listed — nmap, netstat, ss, ncat, openssl — and also read the Wikipedia article on TLS to understand what was actually happening before touching the terminal.

Tried a few wrong syntax attempts with openssl s_client first:

1
2
3
4
5
openssl s_client localhost -connect 30001 pbLYuZtTg4MgaqfJx8jbA9gKKGqM68A7
# s_client: Extra option: "localhost"

openssl s_client -connect 30001 pbLYuZtTg4MgaqfJx8jbA9gKKGqM68A7
# s_client: cannot provide both -connect option and target parameter

The -connect flag takes host:port format, not separate arguments. Correct command:

1
openssl s_client -connect localhost:30001

The connection opened, showing a wall of TLS handshake information. Then I typed the password and got the next one back:

1
2
3
pbLYuZtTg4MgaqfJx8jbA9gKKGqM68A7
Correct!
kS0Hf0u5HiXFwKMKFqXvPdOTNGGa0X8V

Understanding the TLS Handshake Output

The output from openssl s_client shows every step of the TLS handshake. Here’s what each part meant:

The cipher negotiated:

1
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384

The server and client agreed on TLS 1.3 using AES-256-GCM for encryption and SHA-384 for hashing. This is the cipher suite — the combination of algorithms both sides agreed to use.

The server’s certificate:

1
2
3
4
5
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=CN=SnakeOil
issuer=CN=SnakeOil

The server sent its certificate to prove its identity. The Common Name is SnakeOil — a joke name signalling this is a fake, untrusted certificate. Both the subject (who the cert belongs to) and the issuer (who signed it) are the same: SnakeOil. That means the server signed its own certificate.

The verification error:

1
2
verify error:num=18:self-signed certificate
Verification error: self-signed certificate

Normally a Certificate Authority — a trusted third party like DigiCert or Let’s Encrypt — signs a server’s certificate. Your browser or client has a list of trusted CAs. If the certificate is signed by one of them, verification passes.

Here the server signed its own certificate with no CA involved. The client has no way to verify it’s legitimate. This is the same vulnerability that enabled the DigiNotar breach I wrote about in my CS50 HTTPS post — the trust chain matters.

The connection still works despite the error — openssl s_client warns you but proceeds. In a real browser visiting a real website, you’d see a “Your connection is not private” warning.

The key exchange:

1
Negotiated TLS1.3 group: X25519MLKEM768

X25519 is elliptic-curve Diffie-Hellman. So the key exchange used the DH method, not the older random-number-encrypted-with-public-key method. This gives forward secrecy — even if the server’s private key is stolen later, past sessions cannot be decrypted because the session key was never transmitted, only derived.

Why Plain nc Didn’t Work

nc opens a raw TCP connection with no encryption. The service on port 30001 requires TLS — it expects the connection to start with a TLS handshake. If you connected with nc, the server would be waiting for a TLS ClientHello message and you’d be sending plain text. The connection would go nowhere.

openssl s_client handles the TLS handshake automatically, then gives you an interactive prompt where whatever you type is encrypted and sent through the secure channel.

What I Learned

TLS handshake order: client sends supported cipher suites → server picks one and sends its certificate → key exchange happens → session key derived → encrypted communication begins.

Self-signed certificates bypass the CA trust chain. They encrypt the connection just as well but cannot prove the server is who it claims to be. Fine for internal tools, not acceptable for public websites.

Elliptic-curve Diffie-Hellman provides forward secrecy. The session key is derived on both sides independently — it’s never sent over the network. Even if an attacker records the encrypted session and later obtains the private key, they still cannot decrypt it.

openssl s_client is the standard tool for testing TLS connections manually. It shows the full handshake, certificate details, and cipher negotiation — invaluable for debugging SSL/TLS issues in real security work.

Commands Used

CommandWhat it did
openssl s_client -connect localhost:30001Opened a TLS connection to port 30001
Typed the passwordSent it through the encrypted channel
Read the responseReceived the next level’s password
This post is licensed under CC BY 4.0 by the author.