20080521-Ruby-on-Rails-Security
-
Upload
koji-shimada -
Category
Technology
-
view
3.860 -
download
0
description
Transcript of 20080521-Ruby-on-Rails-Security
2008-05-21(水); Apple Store SapporoRuby Sapporo Night vol.6
Ruby on Rails Security
島田浩二SHIMADA Koji; Nihon Ruby-no-kai; RubySapporo
日本Rubyの会Ruby札幌[email protected]
入門 Railsセキュリティ
Tell The Topic of Ruby, RubySapporo!
Ruby札幌、Rubyの話しろ!
しまだこうじhttp://iddy.jp/profile/snoozer05
✓ ふつうのフリーランス・プログラマ✓ 日本Rubyの会
✓ Ruby札幌 運営✓ RubyKaigi スタッフ/実行委員
✓ プログラミングの楽しさを共有したい✓ 自分の知らないコトやヒトに出会いたい
どうぞよろしくお願いします
まとめ
✓ Railsは標準でさまざまなセキュリティ対策をサポートしている
✓ 重要なのはRailsによる対策のポイントを理解すること
✓ 用法・用量を守って正しくお使い下さい
今日のゴール
✓ Railsアプリがセキュアかどうかを確認するための、いくつかの基本的なチェック項目について知る
✓ それぞれのチェック項目を満たすための作戦を知る
チェックリスト
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
一つずつ
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
見せなくてよい情報を公開していないか
チェック項目1
見せなくてよい情報を公開していないか
見せなくてよい情報を公開していないか
見せなくてよい情報を公開していないか
見せなくてよい情報を公開していないか
見せなくてよい情報を公開していないか
422ステータスのテンプレートがデフォルトで用意されているのは
Rails2.0~
何が起きるか✓ 攻撃者に攻撃方法を考えるヒントを与えてしまう✓ フレームワークや固有のバージョンの脆弱性をつかれる可能性がある
対策✓ 攻撃のヒントになる可能性のある情報は、極力表に出さない✓ デフォルトのページなどをそのままにしない✓ アクセス制御をきちんと
ActionController::Routing:: Routes.draw do |map| … map.root :controller => "welcome" …end
config/routes.rb
トップページが指定された場合のルーティング先を定義
対策
各種デフォルトのテンプレートをきちんと差し替える
対策
…<DirectoryMatch "^/.*/\.svn/"> ErrorDocument 403 /404.html Order allow,deny Deny from all Satisfy All </DirectoryMatch>…
httpd.conf
Webサーバでファイルのアクセスに関する適切な設定を行う
対策
✓ 攻撃のヒントになる可能性のある情報は、極力表に出さない✓ デフォルトのページなどをそのままにしない✓ ステータスページ等
✓ アクセス制御をきちんと✓ サーバの設定などをきちんと確認
見せなくてよい情報を公開していないか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
重要なモデル属性を保護できているか
チェック項目2
create_table :users do |t| t.string :login t.string :name t.string :password t.integer :admin, :default => 0end
db/migrate/00X_create_users.rb
class Users < ActiveRecord::Baseend
制御に絡む属性app/models/user.rb
重要なモデル属性を保護できているか
create_table :users do |t| t.string :login t.string :name t.string :password t.integer :admin, :default => 0end
db/migrate/00X_create_users.rb
class Users < ActiveRecord::Baseend
制御に絡む属性app/models/user.rb
重要なモデル属性を保護できているか
何のガードもしていない
http://example.com/users/new
重要なモデル属性を保護できているか
http://example.com/users/new
重要なモデル属性を保護できているか
何が起きるか✓ 攻撃者の視点✓ このフォームを使って何か攻撃できないか✓ フィールドにありそうな属性でも追加してみるか
✓ ユーザ情報だったら管理者権限か✓ とりあえずadminあたりから
何が起きるか
<form action="/users" method="post"> <input name="user[login]" type="text" /> <input name="user[name]" type="text" /> <input name="user[password]" type="text" /> <input name="commit" type="submit" value="Create" /></form>
オリジナルのフォーム
何が起きるか
改変されたフォーム
<form action="/users" method="post"> <input name="user[login]" type="text" /> <input name="user[name]" type="text" /> <input name="user[password]" type="text" /> <input name="user[admin]" type="text" /> <input name="commit" type="submit" value="Create" /></form>
何が起きるか
改変されたフォーム
<form action="/users" method="post"> <input name="user[login]" type="text" /> <input name="user[name]" type="text" /> <input name="user[password]" type="text" /> <input name="user[admin]" type="text" /> <input name="commit" type="submit" value="Create" /></form>
フォームを改変されて使用されると公開していない属性でも上書きされてしまう
対策✓ 制御に絡む属性はきちんと保護する✓ フォームからのリクエストで直で更新しない✓ ARが提供している仕組みを利用する✓attr_protected, attr_accesible
class Users < ActiveRecord::Base attr_protected :adminend
attr_protectedのサンプル
class Users < ActiveRecord::Base attr_accesible :login, :name, :passwordend
指定した属性以外は一括代入時には無視される
対策
attr_accesibleのサンプル
指定した属性は一括代入時には無視される
✓ 制御に絡む属性はきちんと保護する✓ フォームからのリクエストで直で更新しない✓ ARが提供している仕組みを利用する✓attr_protected, attr_accesible✓開発当初はattr_protectedを使用し、開発が進み制御に絡む属性が増えてきたらattr_accesibleへ切り替えるのが吉
重要なモデル属性を保護できているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
コントローラメソッドが公開されていないか
チェック項目3
app/controllers/users_controller.rb
class UsersController < ApplicationController # 外部に公開しているアクション def activate mark_as_activate if valid_request end # 具体的にアクティベート化を行う処理 def mark_as_activate ... endend
publicメソッドとして定義してしまっている
コントローラメソッドが公開されていないか
何が起きるか✓ 内部処理が外部からアクションとして呼べてしまう✓ ブラウザ等から容易に実行できてしまう✓ 悪意がなくても踏んでしまう危険性がある
✓ 一度でも呼ばれると、システムの整合性は保証できない
対策✓ コントローラメソッドのアクセス制御をきちんと管理する✓ アクションではないメソッドはpublicにしない
✓ アクセス制御の明示✓private, protected
対策
class UsersController < ApplicationController def activate mark_as_activate if valid_request end
private def mark_as_activate ... endend
app/controllers/users_controller.rb
コントローラメソッドが公開されていないか
✓ コントローラメソッドのアクセス制御をきちんと管理する✓ アクションではないメソッドはpublicにしない
✓ アクセス制御の明示✓private, protected
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
出力ページのエスケープ処理に漏れはないか
チェック項目4
app/views/users/show.erb.rhtml
...<p> <b>Name:<b> <%= @user.name %></p> ...
hメソッドによる、特殊文字のHTMLエンティティとしてのエスケープ処理が漏れている
出力ページのエスケープ処理に漏れはないか
何が起きるか✓ クロスサイト・スクリプティング攻撃(XSS)✓ 攻撃者が埋め込んだ任意のスクリプトが出力ページ内に挿入されてしまう
✓ ページの訪問者のCookie情報が盗み取られる等、致命的な被害を引き起こす入り口
対策✓ 出力ページのエスケープ処理について漏れがないことを確認する✓ SafeERBプラグインを使用しエスケープ漏れを検出
✓ sanitizeメソッドを使用しホワイトリスト形式で出力時にスクリプトを除去
対策✓ SafeERB✓ http://agilewebdevelopment.com/plugins/safe_erb✓ taint機構を使ってエスケープ漏れをチェック
✓ エスケープ漏れがあると例外✓ SQLiteから取り出した値はtaintedではないので例外が出ないので注意→確認する場合はPostgresやMySQLで
対策✓ sanitizeメソッド✓ ホワイトリスト方式を使用し任意のタグを除去
...<p> <b>Name:<b> <%= sanitaize(@user.name) %></p> ...
app/views/users/show.erb.rhtml
✓ 出力ページのエスケープ処理について漏れがないことを確認する✓ SafeERBプラグインを使用しエスケープ漏れを検出
✓ sanitizeメソッドを使用しホワイトリスト形式で出力時にスクリプトを除去
出力ページのエスケープ処理に漏れはないか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
DBへ渡す入力のエスケープ処理に漏れはないか
チェック項目5
app/controllers/user_controller.rb
DBへ渡す入力のエスケープ処理に漏れはないか
app/controllers/user_controller.rb
ユーザ入力をそのままSQLへ変換してしまっているためエスケープ処理が行われていない
DBへ渡す入力のエスケープ処理に漏れはないか
app/controllers/user_controller.rb
ユーザ入力をそのままSQLへ変換してしまっているためエスケープ処理が行われていない
DBへ渡す入力のエスケープ処理に漏れはないか
何が起きるか✓ SQLインジェクション✓ サーバ上で実行されるSQLを攻撃者が制御可能になってしまう
✓ データベースを不正操作され致命的な被害を引き起こす
対策✓ SQLの組み立てにはバインド変数を使用しSQLのメタ文字をエスケープする✓ ?プレースホルダの使用して値を指定✓ 名前付きバインド変数のハッシュを使用
✓ プレースホルダの使用
対策
User.find(:first, :conditions => [“name = ?”, params[:name]])
User.find(:all, :conditions => [“category IN (?)”,[1, 2, 3]])
✓ 名前付きバインド変数の使用
対策
User.find(:first, :name => params[:name], :password => params[:password])
User.find(:first, :conditions => [“name = :name”, :name => params[:name]])
✓ SQLの組み立てにはバインド変数を使用しSQLのメタ文字をエスケープする✓ ?プレースホルダの使用して値を指定✓ 名前付きバインド変数のハッシュを使用
DBへ渡す入力のエスケープ処理に漏れはないか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
外部ページからの不正なリクエストをガードできているか
チェック項目7
外部からの不正なリクエストをガードできているか
class BlogsController < ApplicationController ... def update ... end ...end
app/controllers/blogs_controller.rb
<% form_for(@blog) do |f| %> ...<% end %>
app/views/blog/edit.rhtml
リクエスト処理に対して何もガードをかけていない
何が起きるか✓ クロスサイトリクエストフォージ(CSRF)✓ 攻撃者の誘導により、ユーザが外部ページから攻撃者の用意したリクエストを実行してしまう
対策✓ リクエストの有効性を検証する✓ Rails2.0からはデフォルトで対策の処理が入っている✓ protect_from_forgery✓ ApplicationControllerクラスで指定✓ Railsの生成するフォームと対で検証用のトークンを持ち、それらを比較することでリクエストの有効性を評価
✓ protect_from_forgeryの使用
対策
class ApplicationController < ActionController::Base protect_from_forgery end
class BlogController < ApplicationController::Base protect_from_forgery :only => [:create,:update] end
✓ リクエストの有効性を検証する✓ Rails2.0からはデフォルトで対策の処理が入っている✓ protect_from_forgery✓ ApplicationControllerクラスで指定✓ Railsの生成するフォームと対で検証用のトークンを持ち、それらを比較することでリクエストの有効性を評価
外部からの不正なリクエストをガードできているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
チェックリスト
1. 見せなくてよい情報を公開していないか
2. 重要なモデル属性を保護できているか
3. コントローラメソッドが公開されていないか
4. 出力ページのエスケープ処理に漏れはないか
5. DBへ渡す入力のエスケープ処理に漏れはないか
6. 外部ページからの不正なリクエストをガードできているか
今日のゴール
✓ Railsアプリがセキュアかどうかを確認するための、いくつかの基本的なチェック項目について知る
✓ それぞれのチェック項目を満たすための作戦を知る
OSC2008-doRuby/Railsセキュリティハンズオン(仮)開催日:2008年6月28日(土) 場所:さっぽろ産業振興センター参加費:無料
セキュリティについてもう少し知りたくなったら
セキュリティ以外について知りたくなったら
Railsレシピブック高橋征義, 諸橋恭介(著)発売日:2008年5月31日出版社:ソフトバンククリエイティブ 価格:2940円(税込)
まとめ
✓ Railsは標準でさまざまなセキュリティ対策をサポートしている
✓ 重要なのはRailsによる対策のポイントを理解すること
✓ 用法・用量を守って正しくお使い下さい
ご清聴ありがとうございました