angular.jsをやってみる (24) - ng-non-bindable -
angular.js JavaScript Ruby Rails
参考: AngularJSとサーバーサイドテンプレートの混在とngNonBindable
※上記の参考を必読することをオススメ
上記参考にも書いてるのですが、例えばクエリーなどにおいてangular.jsが処理されるような記法なクエリーが含まれているとXSSになるっていう話があるのですが、実際自分でやってみた。
※実検証はRails4を使ってやった
app/assets/javascripts/app.js
angular.module("app", [])
.controller("SampleController", function($scope) {
$scope.onClick = function() {
alert("click");
};
});
んまぁ適当に$scopeに関数を打ち込む。で例えばこのコントローラーの内部にサーバーサイドなテンプレートエンジンを利用してクエリーで指定したデータで<span style="color: red">"{% raw %}{{onClick()}}{% endraw %}"</span>がそのまま参照されたらどうなるのかっていう
app/controllers/sample_controller.rb
class SamplesController < ApplicationController
def show
@query = params[:query]
end
end
単純に<http://localhost:3000/sample.html?query={% raw %}{{onClick()}}{% endraw %}>のようなクエリーを送れるような形で、そのデータをビューにバインドする
app/views/sample/show.erb
<div ng-controller="SampleController">
<h2><%= @query %></h2>
</div>
終わり。でこのまま動かしてコントローラーのところに書いてるURL( <http://localhost:3000/sample.html?query={% raw %}{{onClick()}}{% endraw %}> ) にアクセスしてみると$scopeに突っ込んだ関数な処理が発生してしまう。つまりalertが出るっていうオチになる
っていうことでサーバーサイドからテンプレートエンジンを用いてレンダリングされる部分において、angular.jsで評価される可能性のあるのはng-non-bindableを指定すればいい模様。なので上記のビューを
<div ng-controller="SampleController">
<h2 ng-non-bindable><%= @query %></h2>
</div>
っていうように修正する。というようにすることでサーバーサイドでテンプレートエンジンを介してレンダリングされる場合でもangular.jsとして評価しないようにすることで対処することは可能らしい
ただしなんらかの形としてangular.js内部に影響を与えるような攻撃が今後も出てきてしまうっていうのも否定し難いので、こういうデータをレンダリングされる場合においては$interpolateProviderのstartSymbolとendSymbol(デフォルトはダブルカーリーブラケット)をエスケープするような対策が必要になるのではないかと
んまぁとりあえず読んでやってみただけなのですが一応メモっておく