University CTF 2022 — HTB

Abdul Wassay (Hot Plugin)
6 min readDec 4, 2022

--

The Magic Informer (WEB)

The Magic Informer is the only byte-sized wizarding newspaper that brings the best magical news to you at your fingertips! Due to popular demand and bold headlines, we are often targeted by wizards and hackers alike. We need you to pentest our news portal and see if you can gain access to our server.

Solution

Starting the challenge we get the following home page.

At the end of the page, there’s a button that redirects to register page.

After registering new account we are redirected to login page.

After logging in we are given the following form what have some details and an upload button.

On uploading a file, we are given link to the uploaded file. The extension and name of the file is also change.

When clicking on give link the file is downloaded. Upon looking in proxy, we can see that the name of file is passed via resume parameter. Here we can test for directory traversal.

Trying simple payload, it can be seen that a filter is inplaced which strips the ../ in file name. However, it does not do this recursively, so upon some modification we can successfully read files from target.

Next, i tried to read flag but could not find the file.

So, i started to download the source code of application to further analyze it. First is index.js file.

In index.js, some other files are mentioned so let’s download them.

The debug.env file contains some debug pass, it might come handy later.

Other than that the routes index.js file contains names of some middleware file and jwt helper. So, i also downloaded them.

These are all the files that are download from web server.

Looking at the routes, we can see that there’s some functionality which is only accessible by admin. This access control is done by Admin middleware. So let’s look at it how it is implemented.

Looking at the Admin middleware, it is only decoding the JWT and checking the username from it that if it is admin or not. As it is not verifying the JWT, we can modify it and get admin.

We just need to change the username to admin in our current JWT.

https://jwt.io/

Replacing the new JWT in our cookies and reloading the page we get redirected to admin page. Here we can see other functions as well.

Again looking at the routes we can see that /debug/sql/exec endpoint takes two POST parameters, sql and password. The password is then compared to the debug password. We already have this debug password. Next it replaces all double quotes from sql and creates a command and passes it into execSync which executes it. Here we can have command injection since we can control sql paramter. But the problem is that it requires local middleware.

Looking at local middleware, we can see that this endpoint can only be accessed from localhost.

We can see that in the browser

And also in our proxy.

Again looking at the source code, we can see that there’s an endpoint /api/sms/test which takes url, headers and params and other things and uses axios to send request. Axios is promise based HTTP client for the browser and node.js. This is a SSRF (Server Side Request Forgery). We can it with command injection by supplying it the url to /debug/sql/exec path.

First lets see if we can get home page using it.

And here we can see that it returns the html of home page.

Also in the proxy, we can see that it is send HTTP verb, param, header in the request.

So, we modify the verb to POST, provide it url to the sql/exec path and supply the parameters sql and password. Also we need to set the header of content type to json and admin jwt in cookies header. Sending the request, we successfully get the result of sql query.

Again looking at the code, we can see that it is creating oneliner bash command to execute. I tried to escape the double quotes to injection another command but it did not work since it is replacing the double quotes with single.

However, i got the idea that we can run local system command from sql prompt. I just needed to google the syntax and found that we can run system command from sqlite prompt using .shell <command>. So, i replaced this in the sql parameter and got command execution.

Looking at the root, we can see that there’s file name readflag. However this is not a text file but an actual elf binary.

So, upon executing this binary, we get the flag.

Thanks.

--

--