Hack Yourself First (Module 2 - XSS)

This morning I started my day off with a lovely pilates session accompanied by a beautiful sunrise. Something about waking up when it’s pitch black and cold outside gives me a feeling of tranquillity.

As the sunlight seeps through the dark skies and the fog fades, I finished my Pilates practice, sat down on my desk with a delicious cup of matcha and got stuck into studying.

Important side-note: Although I just found out that this course was published in 2013 and might be slightly out-dated, I really wanted to complete it. I think it still has a lot of value and will be a great add-on to complement future courses I’ll take. Along the way, I’ll try my best to take note and mention what parts might be obsolete/irrelevant. If I’ve missed anything out, please do feel free to leave a comment. Thank you and happy reading!

Module 2: Cross-Site Scripting (XSS)

Source: https://www.wpexplorer.com/cross-site-scripting-wordpress/

Understanding untrusted data and sanitisation

Untrusted data:

  1. The integrity is not verifiable
  2. The intent may be malicious
  3. The data may include payloads such as SQL Injection, XSS, binaries containing malware, etc

Common sources of untrusted data:
From User:
In the URL via query string or route
- Form data in a post request

From Browser:
- In cookies or other parts of the request headers

From other locations:
- External services
- Your own database

Input Sanitisation:

  • Characters that might need to be rejected: <>’/“\
  • Be explicit in what specific characters to reject → but it’s easy to forget or provide an incomplete list
  • Explicitly state what specific characters to accept → A lot more comprehensive and lower risk approach

Establishing input sanitisation practices

There are sometimes gaps in the sanitisation process. Exploring the search function:
- Look at what characters the search function might filter out
- Using Regex can help with defining what characters to allow

Source: Pluralsight Hack Yourself First

Understanding XSS and output encoding

Source: Pluralsight Hack Yourself First

When we can actually pass untrusted data to the system, and change the behaviour of the page, we have a very serious risk
- In the example, the search term was never intended to be markup → it should only be intended for data
- XSS attacks are possible as the app allows XSS payload to break out of the data context and change the markup context
-To mitigate the risk, we need to ensure that the search term escapes certain characters so that it’s reflected exactly as it’s typed, onto the screen and not into the markup

Source: Pluralsight Hack Yourself First

For example: <I>Enzo</I> should be written as &lt;i&gt;enzo&lt;/I&gt; in HTML

Source: Pluralsight Hack Yourself First

The way data needs to be encoded changes depending on the context:

  • Identifying the use of output encoding
  • Be wary of the page inspector when inspecting the elements tab in DevTools and refer to the HTML source instead, to see the escape characters
Search term in elements tab — Source: Pluralsight Hack Yourself First
Search term in HTML source Source: Pluralsight Hack Yourself First
  • Even though in HTML the “/“ character is being encoded, the JavaScript, the search term isn’t being encoded
Search term in JavaScipt not being encoded properly — Source: Pluralsight Hack Yourself First

Delivering a payload via reflected XSS

  • When untrusted data provided by the user to the system, wasn’t properly sanitised/ encoded and the untrusted data was able to reach the server as the victim submits the data with the malicious payload
The query string in a form can be written as a malicious payload — Source: Pluralsight Hack Yourself First
The attacker can then submit the malicious payload via the query string input — Source: Pluralsight Hack Yourself First
  • Use a trusted library to help with JavaScript encoding to make things easier for us

Testing for the risk of persistent XSS

  • What already sits in the database coming from another way
  • The user can input markup via the comments form
Comment form — Source: Pluralsight Hack Yourself First
  • When we go back to the homepage, then visit the supercar website again, the server is pulling the data submitted by the user from the database
The text shown in the DOM is in Italics — Source: Pluralsight Hack Yourself First
  • This means the data is not being encoded properly for the HTML output context before it loads it onto the page → risk of persistent XSS via the comments form

Don’t just assume you can take anything from the database and push it to the screen → Extremely important to remember this for every single piece of data we pull from the database

  1. Check if we can go to any field in the system (firstly through the web interface) and inject XSS into the system
  2. If we circumvent those controls and go directly to the database → if we put HTML markup into the database, do they render directly onto the screen, or do they actually cause the markup and structure of the page to change

Most web frameworks these days provide very easy and streamlined ways of implementing output encoding (many even by default!)

The X-XSS-Protection header

  • Reflective XSS adheres to a relatively predictable pattern
  • Browsers can protect users against potential XSS risks
    E.g. if the browser sees a potentially malicious search term passed in the query string in a link from an external resource, and then reflect onto the page, the browser can assume that it’s a reflective XSS → the browser can then provide a layer of protection
  • As a developer, you can never rely on that → We must work on the assumption that the application itself in isolation needs to be secure
Response Headers with X-XSS-Protection set to 0 — Source: Pluralsight Hack Yourself First

When a response header starts with an “X”, it’s a non-HTTP spec standard header (a.k.a non-standard headers implemented by web server providers or to target specific features of the browser)

Internet Explorer can disable X-XSS-Protection → Not that great from a security perspective

If you didn’t disable it, IE10 will let you know by showing a notification at the bottom → Getting rid of that error is really important. Instead of disabling this layer of security, maybe we can find another way to mitigate this XSS vulnerability

Cross-Site Scripting notification — Source: Pluralsight Hack Yourself First

Side-note from MDN Web Docs:
The HTTP X-XSS-Protection response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. Although these protections are largely unnecessary in modern browsers when sites implement a strong Content-Security-Policy that disables the use of inline JavaScript ('unsafe-inline'), they can still provide protections for users of older web browsers that don't yet support CSP.

This means that if you do not need to support legacy browsers, it is recommended that you use Content-Security-Policy without allowing unsafe-inline scripts instead.”

Source: MDN Web Docs


  • Sanitisation is our first line of defence
  • Output encoding is absolutely critical
  • Don’t trust your own data (due to persistent XSS)
  • Native browser defences are great for additional protection



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store