Kitty
Enumeration
Nmap scan:
There is a Login page login.php:
There is also a register page register.php:
We can see that the tech stack used is PHP + Apache 2.4.41 + Ubuntu.
Probably the database engine is MySQL!
If we try to register a new user with username
test and password test
we receive the following error:
Password must have atleast 6 characters!
Creating an account test:testtest and login we came to welcome.php:
Try to register another user with name test:
We receive a HTTP 200 status code response with message "This username is already taken".
Instead if we use a correct username (test) but a bad password like in login form we obtain always HTTP 200 status code response with message "Invalid username or password":
Try to enumerate some hidden directories and files:
Exploit Blind SQL injection
Intercept the Login HTTP request in BurpSuite:
If we try a simple SQL injection like ' OR 1=1 ; -- #
in order to exploit a SQL statement like this one we obtain an error message about SQL injection attempt:
If we try to inject SQL on username field we have instead a success:
Now we can try to inject some SQL code, starting from UNION attacks and using the response code 302 returned when login is successfull.
First enumerate the number of columns requested with original SELECT by variably incrementing the number of NULL columns in order to spot the original columns requested (4 is the correct number of null to use!):
So we have a Blind SQL Injection and we need to retrieve information from database only using the HTTP response code.
Try to enumerate the database name using SQL function SUBSTRING()
and built-in MySQL function database()
:
By asking the DB engine if the first character of the database name in use is greater than the character 'a' the response code is 302. If, on the other hand, we set the condition to be less than the character 'a' i.e., a nonprintable ASCII character, the response code becomes 200:
The payload to use to enumerate each character of database()
function output is this one:
We must use a Cluster Bomb type attack since the index of the substring()
function will have to be incremented only after comparing the corresponding character with all possible printable ASCII characters. For example we will have queries executed in this order:
... substring(database(),1,1) = 'a' ...
... substring(database(),1,1) = 'b' ...
.
.
.
... substring(database(),1,1) = 'z' ...
And then I increment the index:
... substring(database(),2,1) = 'a' ...
... substring(database(),2,1) = 'b' ...
.
.
.
... substring(database(),2,1) = 'z' ...
The first payload set (index):
The second payload set (character):
The attack work in the way explained above:
Filter using only 302 response code:
As we can see, the name of the extracted database turns out to be MYWEBSITE
ormywebsite
. Both forms in BurpSuite turn out to be valid because the comparison operations in MySQL, such as those used in WHERE
clauses, are typically case insensitive by default, depending on the collation used for the column or database. To avoid false positives in the output, it is necessary to use the keyword BINARY:
Database name: mywebsite
Try to enumerate the user using user() function:
Username: kitty
Try to enumerate the table name:
Filter as always for only 302 response code:
In this case we only have the table name in lower case since table names in MySQL are case sensitive!
table name: siteusers
Try to enumerate the columns name using the following payload:
In this case we only have the column name in lower and upper case since column names in MySQL are case IN-sensitive!
At the cost of making testing manual (one solution might be to use Python) we enumerate the first character first and then increment the substring length:
The second character for the targeted column is 'r':
and so on...
The resulting columns name are:
created_at
id
username
passwords
Enumerate the password of user kitty previously discovered:
As we can see we've a problem here because function SUBSTRING() is CASE INSENSITIVE so both upper and lower case return 302 Response code.
We need to use BINARY keyword:
password of kitty: L0ng_Liv3_KittY
Connect to machine using ssh and get user flag:
Privilege Escalation
Some manual searching & enumeration on file system:
Connect to mysql locally using these credentials:
Notice that there are 2 different directories development
and html
:
the only file that differs between the two folders is this logged
that is empty.
If we inspect the socket opens with ss
:
We see that there is a listen socket on port 8080 that's not reachable from external machines. We need to establish an SSH tunnel to this port, since we can’t just access it externally:
The site seems to work exactly like the first one.
Try to search under other directories...like /opt
for example:
If we can write inside the logged file, it will be used as the source of the $ip input and we can try to break the command "echo $ip..." and get a shell as root.
There is no cronjob but presumably this script is executed by the root user. Let's check using pspy64, by copying it on victim machine and analyze the processes:
Every minute this script is executed by user root (UID=0).
The problem here is that only www-data
can write to this file:
Seeing the development code, we note that:
There are defined patterns that triggers Apache to write the IP passed with HTTP Header X-Forwarded-For.
Note that this portion of code there isn't in website currently running on port 80:
Force the write of IP address by triggering some of these patterns using OR keyword for example:
But as we can see, the client doesn't send automatically the X-Forwarded-For
HTTP header, so we need to modify with BurpSuite the request like this one, using 1.1.1.1 as test for our privilege escalation:
And finally here we can see that IP is written to the logged
file:
The command execution to evade is this:
We can test it on our Kali machine and see the result. The ls -la
need to be substitute with the command to spawn a reverse shell:
The command that we want to obtain is like this one:
On the victim machine there is netcat:
But there isn't the option -c
:
So we need to change the payload as this one:
To reach this result we need to send IP formatted as below:
On victim machine we obtain the payload reflected inside logged
file:
We put the Kali listen on port 7777:
Last updated