HackTheBox: BountyHunter

Hack The Box on Twitter: "Wild, Wild Web! ☠️ BountyHunter #Easy #Linux  Machine created by ejedev will go live 24 July 2021 at 19:00:00 UTC.  Armageddon will be retired! Join now and

It’s been a while since I have last done a box on HackTheBox. My life at work has been a little bit busier than I expected. However, I wanted to get back into HackTheBox – so I used this box to get started again. I pwned it in the beginning of November, it was quite a nice box. This is my writeup for it!

Host Enumeration

As usual with HackTheBox we need to know what services are running before we can do some further enumeration. To do this, we can perform a simple port scan. I do an nmap scan on all ports (IP is 10.10.11.100). We see that there are two ports open:

  • 22: SSH (OpenSSH 8.2p1 Ubuntu)
  • 80: HTTP (Apache httpd 2.4.41 (Ubuntu))
Port Scan

Enumeration – HTTP

Alright, we have two ports open and one of which is a web server. Let’s go and check it out! It seems that the people who host the website are bountyhunters – they say that they are security researchers and can run Burp(suite). On first glance, we can’t really see any hyperlinks to other pages – except the “Portal” link (/portal.php). But let’s get to that later.

HomePage

Before we start doing manual enumeration, lets kick off an automated scan of gobuster.

$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://10.10.11.100
GoBuster

We see that there are a couple of results. We can “filter out” the ones which have HTTP 403, we won’t have access to those. the /css, /js, and /server-status are typical web files and may not bee too interesting just yet. An interesting one is /resources ; so lets go and check it out.

/resources/

Hm that is indeed interesting. Let’s take a look at the README.txt

README.txt

Intrestingly, we see that there is a TODO list. The first one is arguably the most interesting; that there is a test account on the portal, that passwords are unhashed, and that nopass is enabled. I tried to login to the SSH service with “test” user and no password, but it failed. I guess the security researchers didn’t want to make it too easy for us.

Alright, we also see that there is a “submit script” to submit (we can assume) vulnerabilities. This may be the /portal.php page which I alluded to earlier. Let’s go check it out now.

The /portal.php page looks like it was not finished or that it is still under development. But there is a note in there and a hyperlink to the next page; /log_submit.php. The log_submit page is a pretty basic HTML form where we can submit vulnerabilities (to the security researchers).

portal.php
log_submit.php

Exploiting the Web Application

So, when we submit something in the form the web application actually tells us that there is no database setup, and that nothing happens as such right now. But let’s remember, the bountyhunters can use Burpsuite – and so can we! Let’s start some black-box testing.

It’s actually submitting XML content inside the web request in this format:

<bugreport>
  <title>XML not parsed appropriately</title>
  <cwe>611</cwe>
  <cvss>10</cvss>
  <reward>5000</reward>
</bugreport>

But the XML was actually Base64 encoded, and URL encoded on top of that, it looked like this:

data=PGJ1Z3JlcG9ydD4NCiAgPHRpdGxlPlhNTCBub3QgcGFyc2VkIGFwcHJvcHJpYXRlbHk8L3RpdGxlPg0KICA8Y3dlPjYxMTwvY3dlPg0KICA8Y3Zzcz4xMDwvY3Zzcz4NCiAgPHJld2FyZD41MDAwPC9yZXdhcmQ%2BDQo8L2J1Z3JlcG9ydD4%3D

So, we can send it to the Burp Repeater, and use some payloads from PayloadAllTheThings GitHub Repo. XML External Entities is of course what we are going for. Let’s first try to see if it even works, by performing a file injection attack. The code is listed below. If you do not know how the XXE works, the <reward> parameter includes the external entity “frosty”, which is a system call to include the contents of the /etc/passwd file.

<?xml version="1.0"?>
<!DOCTYPE root [!ENTITY frosty SYSTEM 'file:///etc/passwd'>]>
<bugreport>
  <title>XML not parsed appropriately</title>
  <cwe>611</cwe>
  <cvss>10</cvss>
  <reward>&frosty;</reward>
</bugreport>
File Injection Attack (before encoding data)
File Injection Attack (after encoding data)

And it works! We were able to include the injection and read files local to the system. The interesting thing here is that we see that there is a user ‘development’ on the server. We can use this to try to login to the SSH. Again, I tried without a password (because of the info in the TODO), but it didn’t work. So we need to keep looking.

When remembering the other information from the TODO list, we know that the passwords are not stored in a hashed state. I.e. they are in plaintext (or some sort of format where we will be able to achieve the plaintext). Instead of reading /etc/passwd, we will try to read the db.php file, by calling PHP and base64 encoding the result like so:

<?xml version="1.0"?>
<!DOCTYPE root [!ENTITY frosty SYSTEM 'php://filter/convert.base64-encode/resource=db.php'>]>
<bugreport>
  <title>XML not parsed appropriately</title>
  <cwe>611</cwe>
  <cvss>10</cvss>
  <reward>&frosty;</reward>
</bugreport>

We need to decode the result (use built-in Burp decoder):

So we have some creds. The password is m19RoAUOhP41A1sTsq6k.

I tried it on SSH with the username:password credentials: development:m19RoAUOhP41A1sTsq6k – and it works!


Privilege Escalation

This should be a simple privilege escalation because it is an “easy” rated box. Lets take some simple enumeration steps, before we try to go for an automated script (like LinPeas.sh). One of the first things that I like to try is sudo -l, in this case we see that we can run a python script as root – without requiring a password. Let’s hope that there is some sort of vulnerability in the script which we can exploit.

(root) NOPASSWD: /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py

Pretty much, we can run ticketValidator.py as root. This code evaluates tickets and then rates them accordingly based on their format. Lets take a look at the code in the screenshot below. Essentially, it checks that the first two lines begin with # Skytrain Inc and ## Ticket to privesc respectively. After that, it checks the __Ticket Code:__ and does some math functions on the ticket number. Pretty much, we just need to make a .md file, which meets the requirements of the script. We can inject an OS import in into the python code, to get it to execute bash.

ticketValidator.py
$ cat file.md

# Skytrain Inc 
## Ticket to privesc
__Ticket Code:__ 
**102+ 10 == 112 and __import__('os').system('/bin/bash') == False

Execute it like this:


Rooted!

That was a fun box! Thanks for reading!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.