安全なプログラムの作り方

19,413 views

Published on

http://rubykaigi.org/2011/ja/schedule/details/17M01 での発表資料です。

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
19,413
On SlideShare
0
From Embeds
0
Number of Embeds
9
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

安全なプログラムの作り方

  1. 1. 安全なプログラムの作り方 Secure Programming 西山和広 (@znz) Good-Day Inc.Powered by Rabbit 0.9.2
  2. 2. Agenda prologue 具体例 まとめ 1/41
  3. 3. prologue (1) はじまり まだ javascript もなかった頃の話 掲示板 (伝言板) CGI がありました (twitter をもっと簡易にしたようなもの) 2/41
  4. 4. prologue (2) 掲示板 CGI HTML のタグを解析して A とか B とか HTML の構造が崩れないものを許可 それ以外のタグ HTML とか HEAD とか BODY とかはエスケープ エスケープするのは、ちゃんとした HTML を出力するため 3/41
  5. 5. prologue (3) 余談 hidden で埋め込んだ文字の文字コードで他 のフィールドの文字コード推定もうまくいか ないブラウザがあるとか 出力した HTML と同じ文字コードでフォー ムの内容も送ってくると思ったら、そうじゃ ないブラウザがあるとかそういう理由で文字コードは結局自動判別しかなかったというのはまた別のお話 4/41
  6. 6. prologue (4) 変化 javascript が普及 onclick などが指定できるようになる javascript: というリンクも使えるようになる 問題がなかったはずの掲示板が 何も変えていないのに 脆弱性のあるものになった 5/41
  7. 7. 結論永遠に安全なアプリケーションは困難 6/41
  8. 8. 対策 一般に 入力はちゃんとチェックする 出力はちゃんとエスケープする 多層の対策をするなど その他 環境の変化に注意する 7/41
  9. 9. 脆弱性じゃないものが脆弱性になったといえば
  10. 10. URL 入力欄 ブラウザの高機能化で脆弱性になったものと して URL 入力 問題点 「javascript:」で始まる URL で javascript が実 行できる 対策 外部へのリンクを意図した入力欄なら「 http: 」 または「 https: 」で始まる URL のみ許可 9/41
  11. 11. 逆に昔からダメだった 例として
  12. 12. GET は冪等に (1) 昔から言われていたこと GET で状態を変化させてはいけない GET は冪等 (同じリクエストには同じ応答) であ るべき 11/41
  13. 13. GET は冪等に (2) HTTP のリクエストメソッドは GET, POST, HEAD など GET や HEAD は何度リクエストを送っても同じ 結果を返すべき (羃等) 書き込みや削除には POST (や REST 風なら PUT や DELETE など) を使うべきGET で削除できるようにしていたら検索エンジンのクローラーに消されたという話も。 12/41
  14. 14. べきといえば
  15. 15. 例えば、/tmp を避け る
  16. 16. /tmp を避ける (1) /tmp 以下を直接使うのは避けるべき 一時ファイルを作るときなど 特に固定のファイル名で作るのは危険 問題の例 symlink attack の危険 Windows で困る 15/41
  17. 17. /tmp を避ける (2) 代わりに Rails なら Rails.root+tmp 以下 一般には tmpdir や tempfile などの標準添付ラ イブラリ 16/41
  18. 18. るびまの記事参照Rubyist Magazine - 標準添付ライブラリ紹介【第 15 回】 tmpdir, tempfile http://jp.rubyist.net/magazine/?0029-BundledLibraries 17/41
  19. 19. tmpdir と tempfile 歴史的理由により tmpdir は e なしの tmp tempfile は e ありの temp 覚え方 tmpdir は dir が 3 文字なので tmp も 3 文字 tempfile は file が 4 文字なので temp も 4 文 字 18/41
  20. 20. /tmp と いえば
  21. 21. パーミッションは最小限に 2006 年の JVN#27365476: the Minnus filer2 において、使用中のユーザの権限で別 のユーザに任意の Ruby スクリプトを実行さ れる脆弱性 http://jvn.jp//jp/ JVN27365476/index.html /tmp 以下に作成される外部との連携用の Unix Socket が誰でも読み書きできるパーミッションに なっていた ファイルを作成するときは umask などに注意 20/41
  22. 22. パーミッションとい えば
  23. 23. hiki 0.8.6 の脆弱性 2007 年の JVN#05187780: Hiki において 任意のファイルが削除可能な脆弱性 http:// jvn.jp//jp/JVN05187780/index.html 設置する人が出来るセキュリティ向上手 段 : ファイルの所有者と実行ユーザを分離 権限一緒 : hiki 本体も削除可能 権限分離 : データしか削除できない 22/41
  24. 24. hiki 0.8.6 の脆弱性の詳細hiki/session.rb の if /[0-9a-f]{16}/ =~ session_idが問題で if /A[0-9a-f]{16}z/ =~ session_idに修正 23/41
  25. 25. 正規表現といえば
  26. 26. 改行と正規表現 (1) ^ $ と A z (Z) を使い分ける ^ : 行頭 $ : 行末 A : 文字列の先頭 z : 文字列の末尾 Z : 文字列の末尾か末尾の改行の直前 25/41
  27. 27. 改行と正規表現 (2) ^ $ と A z (Z) を使い分ける Perl では /m を付けない限り ^ $ は文字列の先 頭と末尾 Ruby で同じ意味を持つものは A と Z 入力全体をチェックするに使うのは ^ $ で はなく A z 先ほどの hiki の例で ^ $ を使うと "任意n# {session_id}n任意" のように回避できてしまう 26/41
  28. 28. 正規表現と文字 予期しない文字を通してしまうと危険 何が何にマッチするのか知っておくのは重要 たとえば 英数字なら w は 1.9 だと あ などにはマッチしない [A-Za-z0-9] などのように書く方が確実 用途に応じて [[:alnum:]] とか p{Alnum} と か 27/41
  29. 29. 任意の正規表現 ユーザ入力から正規表現を作る場合 任意のユーザ入力から正規表現を生成するのは危 険 パターンによっては DoS 可能だと思っておいた 方が良い 28/41
  30. 30. 任意の入力 といえば
  31. 31. ログ出力 (1) WEBrickにエスケープシーケンス挿入の脆弱 性 http://www.ruby-lang.org/ja/ news/2010/01/10/webrick-escape- sequence-injection/ コンソールへの任意の出力を許すのは危険ら しい 30/41
  32. 32. ログ出力 (2) RVM がプロジェクトごとの .rvmrc ファイ ルを確認のため表示する 2011 年の JVN#30414126: Ruby Version Manager におけるエスケープシーケンスイ ンジェクションの脆弱性 http://jvn.jp//jp/ JVN30414126/index.html 31/41
  33. 33. ログ出力 (対策) 対策 外部入力をログ出力するときには String#dump などを使ってバイナリのまま出力しない コンソールへの出力でも外部入力を含んだりバイ ナリを含む場合はエスケープすべき 32/41
  34. 34. エスケープ といえば
  35. 35. エスケープは適切に エスケープは出力先に合わせた適切な場所で 適切なものを HTML の属性値なら ではなく "" でくくる エスケープ結果にあった文脈を用意することも必 要 <tag attr=#{CGI.escapeHTML (value)/> では意味がない javascript のエスケープをしてから HTML のエ スケープをするなど多段のエスケープが必要なこ とも 34/41
  36. 36. 多段のエスケープとい えば
  37. 37. コマンドライン処理 (1) 起動元プログラムの中での文字列としてのエ スケープ シェルを経由するならシェルが処理するエス ケープ 最終的に実行しようとしているプログラムの コマンドライン処理に対するエスケープ 36/41
  38. 38. コマンドライン処理 (2) コマンドラインを起動するとき 出来るだけ複数引数の system を使う シェルのエスケープによる面倒は避ける 例: system("svn", "ci", "-m", message, "--", *files) 37/41
  39. 39. コマンドライン処理 (3) チェックポイント ファイル名に空白が入っていても大丈夫か? ファイル名が - で始まっていても大丈夫か? ファイル名に ["*] などの記号が入っていても大 丈夫か? (そもそもそういうファイル名を許可する のか?) NUL 文字 (0) が入っていても大丈夫か? 38/41
  40. 40. コマンドライン処理 (4) 受け取る側 シェルやシェルスクリプトから起動するときに ちゃんと引数を渡せているか? 「alias p=ruby -e "p ARGV" --」のようなエイ リアスを作る 「foo=foo bar; p $foo; unset foo」などで確認 39/41
  41. 41. まとめ 永遠に安全なアプリはほぼ不可能 Web アプリならブラウザなど外部環境の変化 某キャリアの SSL ゲートウェイのような外部要因 入出力は特に気を付ける 入力はチェックする 出力はちゃんとエスケープする ファイル名やパーミッションにも気を付ける 40/41
  42. 42. Questions?

×