Poison is relatively easy and the only FreeBSD box released to date

Poison is a clever, yet very solve-able box on HackTheBox. It’s a great starting point, or just a great way to learn about some different technologies you may be unfamiliar with.

My basic setup for any Hack The Box is a Kali VM running in VirtualBox on MacOS. In the Documents directory I create additional individual directories for each box.

Recon

As with every HTB, I started with a Nmap scan along with the options that the popular YouTube channel IppSec commonly uses.

nmap -sC -sV -oA nmap/initial 10.10.10.84

-sC specifies default scripts

specifies default scripts -sV probes each port for services

probes each port for services -oA outputs to all major file types

outputs to all major file types nmap/initial specifies the directory in which to output the scan

Nmap scan report for 10.10.10.84

Host is up (0.27s latency).

Not shown: 998 closed ports

PORT STATE SERVICE VERSION

22/tcp open ssh OpenSSH 7.2 (FreeBSD 20161230; protocol 2.0)

| ssh-hostkey:

| 2048 e3:3b:7d:3c:8f:4b:8c:f9:cd:7f:d2:3a:ce:2d:ff:bb (RSA)

| 256 4c:e8:c6:02:bd:fc:83:ff:c9:80:01:54:7d:22:81:72 (ECDSA)

|_ 256 0b:8f:d5:71:85:90:13:85:61:8b:eb:34:13:5f:94:3b (ED25519)

80/tcp open http Apache httpd 2.4.29 ((FreeBSD) PHP/5.6.32)

|_http-server-header: Apache/2.4.29 (FreeBSD) PHP/5.6.32

|_http-title: Site doesn't have a title (text/html; charset=UTF-8).

Service Info: OS: FreeBSD; CPE: cpe:/o:freebsd:freebsd

Nmap done: 1 IP address (1 host up) scanned in 21.68 seconds Service detection performed. Please report any incorrect results at https://nmap.org/submit/ Nmap done: 1 IP address (1 host up) scanned in 21.68 seconds

The default Nmap scan only scans the 1000 most commonly used TCP ports. In this case, it’s revealed two listening services: SSH and HTTP.

We can check HTTP by simply opening the site IP in a web browser.

Checking the page HTTP source is a good next step, but in this case, reveals nothing useful. At this stage, we might as well try actually using the application.

Getting the User Password

As one might expect, allowing unauthenticated users to run arbitrary php scripts may lead to unintended and undesirable consequences for the server owner. Trying each of the files in turn reveals nothing of interest though until “listfiles.php.”

This list of files includes the intriguing pwdbackup.txt

Opening that file by entering its name in the scriptname field reveals a mystery string and a note.

The “=” at the end of the string is a hint that this may be encoded base64. All base64 encoded strings have a multiple of four characters and the “=” is used as padding if the text is too short otherwise.

This string can be decoded manually using an online tool, or through a Python script such as this one:

import base64 inp_string = "Vm0wd2QyUXlVWGxWV0d4WFlURndVRlpzWkZOalJsWjBUVlpPV0ZKc2JETlhhMk0xVmpKS1IySkVUbGhoTVVwVVZtcEdZV015U2tWVQpiR2hvVFZWd1ZWWnRjRWRUTWxKSVZtdGtXQXBpUm5CUFdWZDBSbVZHV25SalJYUlVUVlUxU1ZadGRGZFZaM0JwVmxad1dWWnRNVFJqCk1EQjRXa1prWVZKR1NsVlVWM040VGtaa2NtRkdaR2hWV0VKVVdXeGFTMVZHWkZoTlZGSlRDazFFUWpSV01qVlRZVEZLYzJOSVRsWmkKV0doNlZHeGFZVk5IVWtsVWJXaFdWMFZLVlZkWGVHRlRNbEY0VjI1U2ExSXdXbUZEYkZwelYyeG9XR0V4Y0hKWFZscExVakZPZEZKcwpaR2dLWVRCWk1GWkhkR0ZaVms1R1RsWmtZVkl5YUZkV01GWkxWbFprV0dWSFJsUk5WbkJZVmpKMGExWnRSWHBWYmtKRVlYcEdlVmxyClVsTldNREZ4Vm10NFYwMXVUak5hVm1SSFVqRldjd3BqUjJ0TFZXMDFRMkl4WkhOYVJGSlhUV3hLUjFSc1dtdFpWa2w1WVVaT1YwMUcKV2t4V2JGcHJWMGRXU0dSSGJFNWlSWEEyVmpKMFlXRXhXblJTV0hCV1ltczFSVmxzVm5kWFJsbDVDbVJIT1ZkTlJFWjRWbTEwTkZkRwpXbk5qUlhoV1lXdGFVRmw2UmxkamQzQlhZa2RPVEZkWGRHOVJiVlp6VjI1U2FsSlhVbGRVVmxwelRrWlplVTVWT1ZwV2EydzFXVlZhCmExWXdNVWNLVjJ0NFYySkdjR2hhUlZWNFZsWkdkR1JGTldoTmJtTjNWbXBLTUdJeFVYaGlSbVJWWVRKb1YxbHJWVEZTVm14elZteHcKVG1KR2NEQkRiVlpJVDFaa2FWWllRa3BYVmxadlpERlpkd3BOV0VaVFlrZG9hRlZzWkZOWFJsWnhVbXM1YW1RelFtaFZiVEZQVkVaawpXR1ZHV210TmJFWTBWakowVjFVeVNraFZiRnBWVmpOU00xcFhlRmRYUjFaSFdrWldhVkpZUW1GV2EyUXdDazVHU2tkalJGbExWRlZTCmMxSkdjRFpOUkd4RVdub3dPVU5uUFQwSwo=" times = 13 for i in range(times):

inp_string = base64.b64decode(inp_string) out_string = inp_string.decode('UTF-8')

print(out_string)

Which gets us: Charix!2#4%6&8(0

Getting A Username

We now have a password, but no username. It’s possible that the password is for the root user, but let’s look a little closer before we resort to that.

It’s clear that we can read arbitrary files from the Scriptname field. Linux systems store user names along with other information in /etc/passwd . Entering that path gives us:

# $FreeBSD: releng/11.1/etc/master.passwd 299365 2016-05-10 12:47:36Z bcr $ # root:*:0:0:Charlie &:/root:/bin/csh toor:*:0:0:Bourne-again Superuser:/root: daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin operator:*:2:5:System &:/:/usr/sbin/nologin bin:*:3:7:Binaries Commands and Source:/:/usr/sbin/nologin tty:*:4:65533:Tty Sandbox:/:/usr/sbin/nologin kmem:*:5:65533:KMem Sandbox:/:/usr/sbin/nologin games:*:7:13:Games pseudo-user:/:/usr/sbin/nologin news:*:8:8:News Subsystem:/:/usr/sbin/nologin man:*:9:9:Mister Man Pages:/usr/share/man:/usr/sbin/nologin sshd:*:22:22:Secure Shell Daemon:/var/empty:/usr/sbin/nologin smmsp:*:25:25:Sendmail Submission User:/var/spool/clientmqueue:/usr/sbin/nologin mailnull:*:26:26:Sendmail Default User:/var/spool/mqueue:/usr/sbin/nologin bind:*:53:53:Bind Sandbox:/:/usr/sbin/nologin unbound:*:59:59:Unbound DNS Resolver:/var/unbound:/usr/sbin/nologin proxy:*:62:62:Packet Filter pseudo-user:/nonexistent:/usr/sbin/nologin _pflogd:*:64:64:pflogd privsep user:/var/empty:/usr/sbin/nologin _dhcp:*:65:65:dhcp programs:/var/empty:/usr/sbin/nologin uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico pop:*:68:6:Post Office Owner:/nonexistent:/usr/sbin/nologin auditdistd:*:78:77:Auditdistd unprivileged user:/var/empty:/usr/sbin/nologin www:*:80:80:World Wide Web Owner:/nonexistent:/usr/sbin/nologin _ypldap:*:160:160:YP LDAP unprivileged user:/var/empty:/usr/sbin/nologin hast:*:845:845:HAST unprivileged user:/var/empty:/usr/sbin/nologin nobody:*:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin _tss:*:601:601:TrouSerS user:/var/empty:/usr/sbin/nologin messagebus:*:556:556:D-BUS Daemon User:/nonexistent:/usr/sbin/nologin avahi:*:558:558:Avahi Daemon User:/nonexistent:/usr/sbin/nologin cups:*:193:193:Cups Owner:/nonexistent:/usr/sbin/nologin charix:*:1001:1001:charix:/home/charix:/bin/csh

This is a lot of information, though one of the first items that stands out is the username charix at the end— let’s try that along with the password we decoded earlier.

We haven’t found an admin console in the web app, but we do know that SSH is open.

ssh charix@10.10.10.84

Then agree to accept the key, and enter the password.

“I’m in”

As an aside, this is the part that gave me the most trouble getting user. I couldn’t figure out which username to try, and I was having trouble making sure I was copy + pasting the password correctly.

Since were able to grab a SSH password, we don’t need to worry about using Meterpreter or crafting a reverse shell. A quick cat user.txt is enough to grab the user flag now that we’re in.

Secret.zip

Privilege escalation on this box took me essentially a full day — it’s one of those things where I had all the pieces, but there were lots of finicky bits that kept going wrong.

The first thing I did was a simple ls to see what files are in the user’s home directory. In addition to user.txt , secret.zip is also present. The file command reveals nothing except that it is a a Zip file, as expected. Attempting to unzip it on the Poison disk only prompts for a password. Let’s copy it over to our Kali VM and see if we can make any more headway.

scp charix@10.10.10.84:secret.zip .

Running unzip locally again prompts for a password. Let’s try the user password we used earlier to SSH in.

root@kali:~/Documents/poison# unzip secret.zip

Archive: secret.zip

[secret.zip] secret password:

extracting: secret

And… we’re in!

Unfortunately, this file appears to be nonsense: ��[|Ֆz! . Let’s see what else we have to work with and if we can’t find somewhere to use this information.

Process Enumeration

A good starting point for priv esc on most boxes is to see what processes are currently running. To do so, I ran the following:

ps -aux

ps displays currently running processes

displays currently running processes -a displays processes for all users

displays processes for all users -u displays each processes’ owner

displays each processes’ owner -x also shows processes not attached to a terminal

There are a few processes running on the box, but the one that immediately caught my eye was an application I didn’t recognize, running as root.

root 529 0.0 0.9 23620 9040 v0- I 03:32 0:00.09 Xvnc :1 -desktop X -httpd /usr/local/share/tightvnc/classes -auth /root/.Xauthority -geometry 1280x800 -depth 24 -rfbwait2909 4- S 0:00.04 Xvnc :4 -desktop X -httpd /usr/local/share/tightvnc/classes -auth /home/charix/.Xauthority -geometry 1024x768 -depth 24 -rfbwait 120000 -rfbauth /home/charix/.vnc/passwd -rfbport 5904

A quick Google search reveals that Xvnc is a VNC server. For those unfamiliar, VNC is a system that allows remote graphical control of another computer using a client-server relationship. To connect to the server, we’ll need to setup the client on our local machine. From this we can see that it’s running on TCP port 5904. Running vncviewer 10.10.10.84:5904 should be sufficient to connect to a VNC server, but it simply returns an error.

vncviewer: ConnectToTcpAddr: connect: Connection refused

Unable to connect to VNC server

Getting Root

This was the part that I found the most difficult about getting root. A Google search regarding VNC and SSH (the most seemingly relevant services running on the device) reveals this web page regarding tunneling SSH over VNC. As the website explains, this is typically used for encrypting and compressing the VNC connection. This is accomplished by proxying the VNCViewer to a locally running SSH instance, which is connected to Poison. This is necessary because the VNC Server is only exposed locally on Poison.

I first tried setting up the SSH connection as specified on the given page, but it prompts for a root login by default. Instead, I modified it slightly to use the user login.

ssh -L 5904:localhost:5901 charix@10.10.10.84

Enter in the user password, and it’ll open up another user SSH shell. However, behind the scenes, it will also proxy any traffic we send it.

Now, we’ll need to open a second window and run vncviewer on localhost and a specified port like in the example. It should open up and prompt for a password — but what could it be?

A-ha! This is where the secret file from earlier comes in. Similar to a private SSH key, VNC can be authenticated via password file. We’ll need to add a -passwd flag and specify the decrypted secret password file.

vncviewer -passwd secret localhost:5904

This will reveal a remote visual desktop logged in as root.

Insert Hackerman gif here

Conclusion

Poison is fairly straightforward, though it did give me a fair amount of trouble at a few points. Much like the real world, the largest difficulties were in getting things to work correctly once I saw a potential vuln, and filtering out the noise caused by other users. I learned a few things about SSH, VNC, and BSD along the way, and getting root via a VNC window is one of the coolest HTB payoffs I’ve seen.

Happy hunting.