OWASP top 10 by Example: XSS exploits

Updated on October 15,2022

The Open Web Application Security Project (OWASP) is an open community dedicated to enabling organizations to develop, purchase, and maintain secure applications and APIs.The community periodically publishes The OWASP Top 10,  which is a powerful awareness document for web application security. The document represents a broad consensus about the most critical security risks to web applications. Cross-Site Scripting (XSS) attacks are the second most prevalent issue in the OWASP top 10 (after injection attacks), and it’s found in two-thirds of all applications.

What is Cross-Site Scripting?

There is a saying among web developers that goes, “never trust the user.” Any source of data input from a user, be it a signup/login form, a comment field or a normal URI,  must never be trusted by the developer. When a user exploits such fields by pouring in malicious code, and without any sanitizations or validations by the application, the code is used to generate an output making a web application vulnerable to XSS attacks. The aftermath of the attack is very daunting and repercussions include website defacement (when an ‘ugly’ message is permanently displayed on your website), session hijacking through cookie stealing (these lead to account takeovers), database deletion through stored XSS attacks, MFA bypass, DOM node replacement or defacement (such as trojan login panels), malicious software downloads, keylogging and other client-side attacks.

XSS attack diagram

XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end-user. The actual attack occurs when the victim visits the webpage that executes the malicious script. 

Categories of XSS attacks

There are three forms of XSS attacks namely reflected, stored, and DOM.

Reflected XSS: 

Occurs when a web application includes unvalidated and unescaped (or simply unsanitized) user input as part of HTML output. Usually,  the user will need to interact with some malicious link that points to an attacker-controlled page.

Stored XSS: 

The application or API stores unsanitized user input in the database that is viewed at a later time by another user or an administrator. This is a persistent threat and is often considered a critical risk for it may continue for a very long time without notice.


 JavaScript frameworks, single-page applications, and APIs that dynamically include attacker-controllable data to a page are vulnerable to DOM XSS. Ideally, the application would not send attacker-controllable data to unsafe JavaScript APIs.

Environment setup

  • You’ll need a local webserver downloaded and installed. You could use XAMPP.
  • A text editor of choice. I prefer SublimeText.
  • PHP basics
  • Download the zipped source file. Instructions on how to set up the database are included in the README.txt file.

XSS in Action

Vulnerable search form

An easy way to know if your application is vulnerable to XSS attacks is by testing if it’s very easy to deface. Temporary website defacement is done by typing malicious input and seeing how the input affects your web layout. It’s only effective if the input is reflected in the output without sanitization.  Below we will create a vulnerable search form. The complete code and setup is included in the zipped file as “searchform.php”

1. Assumption: You have already set up your local environment and created the databases using the SQL file provided.

2. Create a php file in your text editor named “connect_db.php”. It is for establishing a connection to the database and update it with the code below:


$servername = "localhost";
$username = "root";
$password = "";
$dbname = "xss";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
	die("Connection failed: " . $conn->connect_error);

3. Create another file named “searchform.php” and copy-paste the following code into it.

5. With everything set up correctly, if you visit http://localhost/xss/searchform.php, you should see the form as displayed below.


After that, try searching for the legit queries like “kenya”, “book”, “oludhe”, “gikuyu” in order. Do not include double-quotes.

  • Vulnerable Signup form

    This forum consists of the following users


    The form should display as below:


    When you sign up with valid credentials, your record will be added to the database and then your name shall be displayed on the right pane. When you attempt to use “” as your username, it will be successfully added to the database. When it gets displayed, however, your browser will execute it a javascript code. Although benign, when crafted carefully, one can store a cookie stealing code say through a forum comment field. Every time a user visits the comment page, their cookie is stolen and sent to the hacker's website who can then use the cookie to login and pretend to be the user. With this, they can change the password and lock you out of your own account. Cookie stealing will be discussed in a future article.

    Award-winning XSS attack: Via image

    Images exist on almost all web applications. They come in various formats e.g jpg, jpeg, png, gif, svg e.t.c. Generally, a hacker will hide a malicious link in an image so that when clicked, the victim is redirected to the malicious link. SVG images, however, expose more than meets the eye. Scalable Vector Graphics (SVG) is an XML-based markup language for describing two-dimensional based vector graphics. Since it uses XML to construct the image, JavaScript statements are also evaluated as valid constructs. The code below creates a basic rectangle with an inscribed circle upon which is written “SVG”.

    One can literally append a script tag within the SVG tags to create an XSS attack. Append the code below and then save the file with the “svg” extension, and then open the image in a browser to see the script being executed within the image.


More in this category: Arduino as an ISP for AVR Microcontrollers (Atmega32) »