Published: 28 January 2020 at 14:54 UTC
Updated: 08 September 2020 at 12:22 UTC
As part of my recent research into obfuscating XSS payloads to bypass WAFs, I was looking at the SVG elements set
, animate
, animateTransform
and animateMotion
. I added a couple of known XSS vectors to the cheat sheet using those tags. Then focusing on the animate
tag I found an interesting XSS vector using the values
attribute. The values
attribute lets you specify a number of values for an SVG animation separated by semi-colons:
<svg><animate values="1;2;3" /></svg>
I wondered if I could include a JavaScript URL in the middle of the values attribute - that might confuse a lot of WAFs looking for the JavaScript protocol. The problem was, if I didn't set a duration then the first value would always be shown and if I did set a duration then the URL would cycle through the values and therefore not always show the JavaScript URL. Looking at the SVG specification I noticed that there's a keyTimes
attribute that allows you to control the pacing of the animation for each of the values. Using this with the repeatCount
attribute would enable the animation to always show the JavaScript URL. Here is the final XSS vector:
<svg><animate xlink:href=#xss attributeName=href dur=5s repeatCount=indefinite keytimes=0;0;1 values="https://portswigger.net?;javascript:alert(1);0" /><a id=xss><text x=20 y=20>XSS</text></a>
We have released an interactive XSS lab built around this technique in the Web Security Academy so you can try it out for yourself:
This vector will also shortly be integrated into our XSS cheat sheet. Enjoy!