This article describes examples of XSS attack. The usage of script tag is probably the most known case, but there also other possibilities. You can change the content of a website on your own using image tag or pure CSS.

This is educational material and you should remember that
hacking is illegal if you are caught red-handed. :)

Website code

To present attack we create a simple website based on PHP. I very like separate logic and view in code, but for simplicity and to minimize the number of lines of code we mixed in and all website code is placed in index.php. To get the vulnerability website to have to be able to save text from user to database and display it on screen without filtering of this.

Again for the case of simplicity and clarity, we abandon best practices and use JSON file instead of a database. First file of
our project is db.json

db.json
["First comment","Second one"]

To save users comment send by PHP script do the following things:

index.php

<?php
$comments = json_decode(file_get_contents('db.json'));

if($_SERVER["REQUEST_METHOD"] === "POST") {
    $comments[] = $_POST["comment"];
    file_put_contents('db.json', json_encode($comments));
}
  • Read the content of db.json file and convert it to PHP array.
  • Check if user send the request by method POST - it means to send a form
  • If yes  Append comment send by a user to an array Override file db.json by JSON encoding array with a new comment  

Independent from the method of request script goes on and display form and list of comments

index.php
echo '<form action="" method="post">
    <input type="text" name="comment">
    <input type="submit" value="send">
</form>
<ul>';

foreach ($comments as $comment) {
    echo "<li>".$comment."</li>";
}
echo '</ul>';

The created website looks like the following

It is fully functional, allow to add a comment, save it in JSON
and display list of comments. If users want to add text, not hack it could be the end of our adventure. But we should assume that at least one user of the website wants to hack it. :)

How to hack it?

This flow of data - saving on the server and displaying on client make possible XSS attack if the text is not properly filtered. XSS means Cross-site scripting and enables attackers to inject client-side scripts into web pages viewed by other users.

Appended executable code is interpreted by browser, not server so we cannot conquer server by it but can exchange client behavior. Exemplary benefits for the attacker are the following:

  • stealing cookies (session) - taking control over (logged in) session of victim
  • dynamic change of website content
  • enabling key logger in the browser

The script can be stored on a server or included in the link. In our case, we want to save the script to JSON file by typing comment. We are interested in change content of the website to "Hacked by Daniel". In any case of presented below attack method website will look like this:

Script

The simplest way is append script that dynamically after sile load
change his content to required. Try add comment:

<script>document.querySelector('html').innerHTML="Hacked By Daniel"</script>

This code select HTML - it means all page, and change his content using innerHTML property.

Style

Other method works even if javascript tags are stripped and
javascript is disabled in the browser.

<style>html::before {content: "Hacked By Daniel";} body {display: none;}</style>

We defined two rules for styling of a website. First one tells a browser to append text Hacked By Daniel before the body of the website. The second one to do not display body.

We defined two rules for styling of a website. First one tells a browser to append text Hacked By Daniel before the body of the website. The second one to do not display body.

Image

Of course, if we block script tag and style tag in our comments
it is not enough, because we can run script also in other tags.

<img src=undefined onerror='document.querySelector("html").innerHTML="Hacked By Daniel"'>

This is an example of an image that has an invalid address. If an address is an invalid browser run script being the value of attribute onerror.

How to defense?

To defend this attack we need to filter comments of our users and strip HTML tags. We can do it changing the code in  index.php`
as below

-      $comments[] = $_POST["comment"];
+      $comments[] = htmlspecialchars($_POST["comment"]);

After applying this fix text written in form will be
displayed in comments lists literally equal text typed by the user, and will be not interpreted as HTML tag.

Summary

We showed simple examples of XSS attack. If you use a framework like Symfony then framework have security mechanism build in his structure, but you should remember about htmlspecialchars function if you write in pure PHP.