Protecting against XSS in SVG

Thurs 16th Aug 18

This research started while I was doing some testing for a client whose requirement was to allow SVG files to be uploaded and displayed on their site. Most people assume SVG files are image files in the same way as PNG or GIF, but really they are XML files which describe an image. The bit that interests security people is that can also contain JavaScript which is executed when the image is rendered. This is a good introduction from w3schools.com.

Because of this ability to contain JavaScript, they are a perfect attack vector for Cross-Site Scripting on sites which allow either arbitrary file uploads or limit the file types to images and accept SVGs, here are a few examples of sites which have been hit by the issue:

As my client's requirement was fixed, I had to come up with some recommendations on ways they could defend against XSS attacks while allowing the functionality (remember, security should enable, not say "no"). After some discussions on the SANS GPWN list we came up with the following ways a file could be accessed or displayed, as you can see, some were safe but some were not and the JavaScript was executed.

  • Direct view - vulnerable - The file is linked to directly.
  • Direct view with content-disposition: attachment - not vulnerable - Headers are sent to force the file to be downloaded.
  • Direct view with CSP - not vulnerable - The Content Security Policy is set to disallow inline JavaScript.
  • Image Tags - not vulnerable - The SVG is referenced through image tags which prevent scripts.
  • Tags With CSP - not vulnerable - Image tags and the same CSP as above for double protection.
  • Sanitised through Inkscape - vulnerable - This is a direct view but the file has been processed by the following command:
    inkscape --file="xss.svg" --verb="FileVacuum" --export-plain-svg="sanitised.svg"
    It was expected that this would remove the JavaScript but it did not.
  • Image in an iframe - vulnerable - The SVG is loaded as the source for the iframe with no special attributes set.
  • Image in a sandboxed iframe - not vulnerable - The SVG is loaded as the source for the iframe but the sandbox attribute is set to block scripts.

As you can see, there are a number of options which allow the files to be safely uploaded and displayed which meant the client could happily keep their functionality while also keeping themselves, and their users, safe.

If you want to see these in action, I've put together the following demo SVG XSS Defence Scenarios which implements all the above scenarios. You can also get a full copy of the code from my GitHub repo.