bodyカラムに下記が登録されていると過程する
<script type=”text/javascript”>
alert(“バカ”);
</script>
viewで表示する時にエスケープ処理をしつつ、改行すべきところに<br>
を入れる方法を考える
まずはNGパターンをいくつか試す
- view
<%= @message.body.gsub(/\n/, '<br />') %>
- ブラウザ表示
<script type=”text/javascript”> <br />alert(“バカ”); <br /></script>
- HTMLソース
<%= %>
で囲っているので自動的にエスケープされているためjavascriptは実行
されないが、改行して表示したい<br>
タグもエスケープされてしまっている。
<script type=”text/javascript”><br />alert(“バカ”);<br /></script>
- view
<%= raw(@message.body.gsub(/\n/, '<br />')) %>
- ブラウザ表示
rawメソッドにて<%= >
が自動で行うエスケープ処理をバイパスしたため、クロスサイトスクリプティングが
発生してしまう。
- view
<%= html_escape(@message.body).gsub(/\n/, '<br />') %>
- ブラウザ表示
<script type=”text/javascript”> <br />alert(“バカ”); <br /></script>
- HTMLソース
javascriptの箇所は二重エスケープ(html_escap
と<%= %>
)になっており、
html_escape
後に改行コード\n
を変換した<br />
タグは<%= %>
により
エスケープされて表示されてしまっている。
&lt;script type=”text/javascript”&gt;<br />alert(“バカ”);<br />&lt;/script&gt;
- view
<%= raw(html_escape(@message.body).gsub(/\n/, '<br />')) %>
- ブラウザ表示
<script type=”text/javascript”>
alert(“バカ”);
</script>
- HTMLソース
エスケープすべきところhtml_escape
で事前にエスケープし、その後
改行コード\n
を<br>
タグに変換。
表示の際は<%= %>
でエスケープ処理がされないように、raw
メソッドで
処理している。
<script type=”text/javascript”><br />alert(“バカ”);<br /></script>
OKパターンのraw
メソッドは、自作ビューヘルパ定義や、プレゼンターで利用した方が良く
viewでは<%== %>
を使った方がシンプルで良いと言われている。
viewで使う場合とプレゼンターで使う場合の例はそれぞれ下記のようになる。
- view
<%== html_escape(@message.body).gsub(/\n/, '<br />') %>
- presenter
def formatted_body
raw(ERB::Util.html_escape(body).gsub(/\n/, '<br />'))
end