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