London: 020 0200 8142

Introduction & XSS Post #1: The Basics

Hello and welcome to the new Perspective Risk blog! I thought I’d begin with a series of posts on Cross Site Scripting (XSS) as this is an area of web security I’m particularly interested in. We’re going to start with the very basics, by taking a look at what XSS actually is and the three different varieties of it.


Cross Site Scripting (XSS) attacks occur when a website fails to properly prevent attackers from inserting malicious code into an area that takes user provided data, such as form fields on a webpage, HTTP headers, URLs etc. This code is then used to attack other users, rather than the actual website or the server it’s hosted on. This leads many to underestimate the dangers of XSS, despite the fact that an XSS flaw could allow attackers to record what users are typing, redirect users to malicious sites to capture their credentials and change the content of pages to defraud users, to name but a few.   There are three main types of XSS attacks, reflected, stored and DOM based. Reflected are the most common, whilst stored are the most deadly.

Reflected XSS

These occur when the attack is reflected off a webserver, via a search result, error message or any response which echoes the user provided data back to the user. Reflected attacks are normally delivered via a link and therefore require some amount of coercion, such as tricking the victim into clicking a link sent to them in an email.   So say if a search function on a website was vulnerable to XSS, i.e.   Then we could enter as a search term:

Which is a really small JavaScript script that popups an alert box, saying boom!   Thus if we then send the entire link to someone else, i.e.:<script>alert(‘boom!’)</script>   They’ll see that the host is, think it’s a legitimate site and click it, and then fall victim to the popup box of doom!      Ok maybe not of doom, but this is most common way of testing for XSS flaws, via these alert boxes. Once a flaw is confirmed, more malicious attacks can be demonstrated. You can see where the name ‘reflected’ comes from too, as you need a vulnerable site to ‘reflect’ the attack off.   Let’s work through an example using Damn Vulnerable Web Application (DVWA), which I will be using for all my demonstrating. I highly recommend it as a surface for practicing on; you can host it locally and it’s easy get up and running. Download it here and follow the install instructions here (or follow the install video here). Don’t forget to login with admin:password and then change the DVWA security level in the security settings tab to low (as the default high is invulnerable to all attacks).   Note, if you would rather practice these skills online, i.e. without installing DVWA, you can try reflected XSS attacks here. All my screenshots are of DVWA, but the same XSS strings and principles will work in the online practice environments too.   So head over to the Reflected XSS section and enter some text. The first thing we notice it that what we entered is being echoed exactly back to us on the page: Our next step is to confirm whether the page is performing any sort of filtering of the JavaScript syntax required for our malicious script to work. From the above XSS string, you can see that we use the angle bracket symbols, < >. These are essential to JavaScript as they indicate to the browser that what it’s reading is a line of code, as opposed to just text. Without the angle brackets our code won’t be read as JavaScript and so our attack will fail. Because of this, angle brackets are commonly removed from user supplied input, or are encoded in such a way that the browser won’t read them as code, such as HTML entity encoding. Similarly, the word ‘script’ is often treated in the same way, as some (but not all!) XSS attacks rely on it. This process is known as sanitization or filtering. So let’s try entering <script>: As you can see, <script> is not displayed, because it’s being read as part of the source of the webpage. If we check the source we can see that it’s there and that there’s no encoding taking place either. Cue rush of adrenaline because we’ve found an XSS flaw! So now all we have to do is pop an alert box to confirm…     Boom! As expected, our script is being entered directly into the source and is thus being executed by the browser, so popping up an alert box! Also, you may notice I have added a ‘;’ at the end of our statement within the script tags. JavaScript normally requires a ‘;’ after every statement, to indicate that the line of code has ended. For example, if we wished to have two consecutive popups display ‘Hey’ ‘There’, our code would be:

So we have two JavaScript statements in one script, separated by ‘;’. Fortunately, JavaScript repairs little syntax errors like forgetting the closing ‘;’ for us, so we don’t have to worry about it. (This often proves useful when filter evading too, which will be covered in a later post.)   That’s reflected covered, now onto its less common but far more deadly friend, stored XSS!

Stored XSS

Stored XSS relies on exactly the same principle as reflected XSS; you’re trying to insert your own malicious code into the source, so when a victim visits that page, their browser will execute your code. The only difference, and the reason why they are so much more dangerous, is that your code will be permanently stored on the page. As a result, anyone who subsequently visits that page will trigger the attack; no coercion is required by you at all. They have traditionally often been found on message boards, public guestbooks etc.   Let’s give it a go! We’ll be using DVWA again, so we head to the stored section and immediately we see that big juicy text box, crying out for some JavaScript to be entered into it! We put in our script and…

There it is, being entered directly into the source, with no encoding or filtering. Thus from now on, whenever we revisit the page we will be XSSed, as the browser re-executes the code in the source every time you visit. (Note if you wish to stop this happening on DVWA, go to Setup > Create/Reset Database and it will revert the database back to its original state).   So last of all:


This is getting into a relatively advanced area now, with regards to the concept of the Document Object Model. A detailed explanation is beyond the scope of this post, but just remember that it’s a platform and language independent interface that allows scripts to dynamically update a page’s content, structure and style. This updating can also be done real time, i.e. on the page being viewed currently, so requires no refreshing of the page. A good example of this is the Google auto search function, every time you type the page you are viewing gets updated with the new results, without requiring a refresh or being forwarded to a new page. This is where DOM based XSS differs from the above, the server is not required for the XSS payload to take effect; instead the attacker abuses the runtime embedding of user supplied data in the page.   To illustrate how the DOM works, we’ll have a quick look at WebGoat, which is another vulnerable application similar to DVWA. You can download it here and then follow the install instructions here. Once installed, fire it up and enter guest:guest if prompted. Then click on AJAX security (you don’t need to know what AJAX is in detail, just know that it’s one of the methods in which we can update the DOM on the fly) and select the first entry. Ignore the challenge there for now, just type in your name and immediately you see that as soon as you enter a letter, it gets displayed back to you, without the page being refreshed or a new page being opened. This is the DOM at work, and is similar to the Google auto search function described above.

Right now our hacker alarm bells should be ringing! What we’re entering is being echoed directly back to us! So let’s try our standard XSS string and then right click inspect the element using Firebug (a Firefox add-on for inspecting the DOM). Also, please note there’s no need to press submit solution, as that’s just to solve the challenge. The page is updated on the fly remember!

How strange! Our viable string is clearly in the DOM, but there’s no popup. This is because <script> tags are only executed by the browser when the page first loads, not when only some of the page content is just updated in the DOM, as it is here. To exploit the XSS flaw here, we would need the use of event handlers, which are special JavaScript functions that listen continuously on a page for certain changes, such as onmouseover (when you move the cursor over something), onerror (when an error is produced) or onclick (when you click something). These will be covered in detail in my next blog post though, which you can read here.   Note, for some further info on XSS, see the Wikipedia page and the OWASP page. If you’re still struggling to understand the concept, don’t fret! It took me a while to grasp it as well. I actually found that one day it suddenly clicked, and from then on I had no problems in finding and exploiting XSS flaws. A big help for me was learning the basics of the JavaScript language and the theory behind how it’s used in webpages, so if need be check out the W3 Schools’s tutorial or have a Google!

We are Perspective Risk

  • Information security is crucial to every aspect of your business – operational efficiency, profitability, business continuity, customer confidence, brand loyalty, protection against fraud and meeting regulatory requirements.

    Our penetration testing, pen testing, pen tests and cyber security testing has proven time and time again to be an effective security assessment of business IT infrastructure.

    Perspective Risk provides in-depth security assessments, risk management and compliance solutions to help you keep your confidential information safe and your critical systems secure. We’re innovative, flexible and supportive, helping you through any information security issues to deliver real business benefits and excellent value.

  • Call Me

    Pop your details in below and we’ll be in touch soon!

    • This field is for validation purposes and should be left unchanged.

    Get Quote
    • This field is for validation purposes and should be left unchanged.