概要
\n
などの改行コードを含む文字列をhtml.erbファイルで表示させると改行が反映されない- 改行コードを
<br>
に置換してhtml_safe
で表示させると改行は反映される - しかしながら、この場合は他の特殊文字もそのまま表示されるのでXSSに対して脆弱
- そこで以下の手順をとる
- まず特殊文字をエスケープ
- 改行コードを
<br>
に変換 html_safe
やraw
で表示
改行コードは反映されない
改行コードを含む文字列をerbファイル中<%= ... %>
で表示させても、HTMLで解釈されないので改行されない。
1 2 3 4 |
<% str = "1行目\n2行目<script>alert()</script>" %> <%= str %> # 1行目 2行目 |
<br>タグに変換してもエスケープされる
erb側のセキュリティー対策のため、HTMLの特殊文字はエンティティ―でエスケープされる。なので改行コードを<br>
に変換するとそのままタグが表示される。
1 2 3 |
<%= str.gsub(/\n|\r|\r\n/, "<br>") %> # 1行目<br>2行目 |
html_safeやrawならタグとして機能する
html_safe
やraw
を使うと、タグをタグとして解釈してくれる。
1 2 3 4 5 6 7 8 9 |
<%= str.gsub(/\n|\r|\r\n/, "<br>").html_safe %> # 1行目 # 2行目 <%= raw str.gsub(/\n|\r|\r\n/, "<br>") %> # 1行目 # 2行目 |
この場合XSSに対して脆弱
ただし上記の方法では、<br>
以外のタグも機能してしまうので、XSSに対して脆弱。
1 2 3 4 5 6 7 |
<% str = "1行目\n2行目<script>alert()</script>" %> <%= str.gsub(/\n|\r|\r\n/, "<br>").html_safe %> # 表示はされるがスクリプトも実行されてしまう # 1行目 # 2行目 |
エスケープしてから改行コードを変換
以下の手順なら、改行コードから変換された<br>
以外はエスケープされる。
- まず
h
関数で特殊文字をエスケープ - その後改行コードを<br>タグに置換
- その結果を
html_safe
やraw
で表示させる
1 2 3 4 |
<%= h(str).gsub(/\n|\r|\r\n/, "<br>").html_safe %> # 1行目 # 2行目<script>alert()</script> |
ヘルパーにしておくと便利
上記の処理をヘルパーとして定義しておくと汎用的に使える。
1 2 3 4 5 6 7 8 |
def html_safe_newline(str) h(str).gsub(/\n|\r|\r\n/, "<br>").html_safe end <%= html_safe_newline(str) %> # 1行目 # 2行目<script>alert()</script> |