XSSって何??Sinatraでの対策
XSSって何?簡単に説明すると...
XSS(クロスサイトスクリプティング)は、悪意のある人がウェブサイトに悪意のあるコードを忍び込ませる攻撃方法です。
簡単に言えば、ウェブサイトの掲示板に「こんにちは」と書く代わりに、(悪巧みのための)JavaScriptのコードを書き込むようなものです。
なぜ危険なの?
- ユーザーの個人情報を盗まれる可能性がある
- ウェブサイトの見た目や動きを勝手に変えてしまう
- ユーザーのブラウザで勝手に操作を行う
XSSはどこで起こる?
主に以下のような場所で起こります
- コメント欄
- 検索フォーム
- ユーザープロフィール
- URLパラメータ
つまり、ユーザーが「何かを入力できる場所」」が危険です!!!
XSSってどうやって仕込まれる?
XSSの攻撃ベクトルについて(OWASP)
XSSの種類
-
反射型XSS: URLに悪意のあるコードを含めて、そのページを開いたときに発動
- 例)GETパラメータにスクリプトを含める
-
格納型XSS: 悪意のあるコードをサーバーに保存して、後でそのページを見た人に対して発動
- 例)コメント欄に<script>を含むコードをPOSTして埋め込む
- DOM型XSS: JavaScriptが動的にページの内容を変更するときに発動
XSS攻撃から保護されているかをテストしてみよう
様々な入力パターンの入力をしてみる
<script>alert('XSS')</script>
javascript:alert('XSS')
<img src="x" onerror="alert('XSS')">
理想的なXSS対策が実装されたアプリケーションでは、これらのテストを行っても悪意のあるスクリプトが実行されることはありません。
代わりに、サニタイズされたコンテンツが安全に表示されるか、または完全にブロックされるはずです。
SinatraアプリケーションでのXSS対策
XSSを防ぐには悪意のある入力をフィルタリングすることと、画面への出力をエスケープすることが極めて重要です。
SinatraでXSS対策を行うためには、以下の方法を使用できます。
1. エスケープ処理を行う
<script>alert('XSS');</script>という投稿が送られてきた際に、ブラウザ側で『プログラムではなく「<script>alert(‘XSS’);</script>」という文字列』として認識するよう設定することでスクリプトは実行されずに無害な文字列として扱われます。
特殊文字をHTMLエンティティに変換することで、ブラウザがそれらを通常のテキストとして解釈するようにします。
[利点]
シンプルで効果的
全ての特殊文字を安全に変換
[欠点]
HTMLの書式設定が全て無効になる
RailsではデフォルトでERBテンプレートにおいて<%= %>を使用しているHTMLを自動的にエスケープしますが、Sinatraでは、ERBテンプレートを使用する際に自動的にHTMLエスケープが行われません。
そのため、明示的にエスケープ処理を行う必要があります。
require 'sinatra'
require 'erb'
get '/' do
@user_input = params[:message]
erb :index
end
index.erbファイル
<h1>メッセージ</h1>
<p><%= ERB::Util.html_escape(@user_input) %></p>
または、ヘルパーメソッドRack::Utils.escape_htmlを定義して使用することもできます。
require 'rack'
helpers do
def h(text)
Rack::Utils.escape_html(text)
end
end
テンプレートで以下のように使用します
<p><%= h(@user_input) %></p>
参考:Rack::Utils.escape_htmlについて
2. 入力のサニタイズ
ユーザーからの入力を受け取る際に、不要なHTMLタグやJavaScriptを除去します。
危険なHTMLタグや属性を除去または変換しつつ、安全なHTMLを許可します。
require 'sanitize'
post '/comment' do
@comment = Sanitize.fragment(params[:comment])
# コメントを保存する処理
end
3. 使い分け
[エスケープ処理]
プレーンテキストとして表示したい場合
ユーザーにHTMLの使用を許可しない場合
[サニタイズ処理]
リッチテキストエディタを使用している場合
一部のHTML書式を許可したい場合
4.その他の対策
悪意のある入力をフィルタリングする
悪意のある入力がそもそもDBに登録されてしまうことを防ぎます。
特定の入力を禁止するのではきりがないため、特定の入力だけを許可することが重要です。
事前に定義した特定のタグ以外を遮断することでフィルタが正常に機能します。
適切なContent-Typeを設定する
レスポンスのContent-Typeを適切に設定することで、ブラウザがコンテンツを正しく解釈できるようになります。
get '/' do
content_type :html
erb :index
end
まとめ
セキュリティは常に変化するため、最新の脅威と対策方法について、常に情報をアップデートすることが重要!!!
Discussion