Webセキュリティメモ
何となく、自分の理解をまとめておきたくなったので、徒然と書き連ねます。
セッションとCookie
- 誰からのアクセスなのかを判別するためには何らかの識別子(ID)が必要である。それがセッションID。
- クライアントは、自分が誰であるのかを証明するために、通信の度にセッションIDをサーバへ送る必要がある。
- 毎回送るという特性に親和性が高いため、通常、セッションIDはCookieで管理される。
- セッションIDが盗まれると、セッションの有効期間が切れるまで、第三者が本人になりすまして不正アクセスすることが可能となる(セッションハイジャック)。
- HTTP通信の場合、Cookieは平文で流れる。つまりセッションIDも平文で流れることになり、盗聴の危険性が生じる。
- Cookieにsecure属性を指定すると、HTTPS通信の場合のみ、Cookieが送受信されるようになる。最近はHTTPS通信前提でウェブサービスが構築されることが多く(Twitter、Facebook、…)、secure属性は良く使われる。
- Cookieのexpires属性で有効期間を指定したほうが、万が一の時により安全ではあるが、最近はCookieで長い間セッションIDが維持される設計のウェブシステムが増えている。
AjaxとCookie
SSLとMITM
- SSLには「通信の暗号化」と「相手(通信先)が信頼できる(本物である)ことの証明」の2つの役割がある。
- 巷で使われるSSLは、主として「独自SSL」「共有SSL」「オレオレ証明書によるSSL」の3種類ある。
独自SSL
共有SSL
- SSLの微妙な形。
- サイトのドメインに対する、共有SSLのドメインの名前つけのルールが明確であれば、相手を信頼出来ないこともないが*2、証明書がレンタルサーバーのものである以上、根本的に信頼性が高いとはいえない。
- レンタルサーバーによっては、サブドメインを用いない名前つけをされることが有る*3。そのような場合、同一ホスト上の他サイトからCookieを閲覧されうるため、Cookieの使用は出来ないと考えたほうが良い。
- 実際の所、ウェブにかける予算の問題もあるので、残念ながら、個人や小企業では妥協することも多い。
- 最近では電話番号や住所程度なら平文(HTTP通信)でも割りと許容される傾向にある(?)
- パスワードを使うサービスはHTTPS前提で考えるのが正しい。
オレオレ証明書によるSSL
- SSLの一番アレゲな形。
- ほとんどのモダンブラウザで「信頼出来ない証明書」という警告が出る。
- フィンガープリントすら確認せずに、あのサイトは許可でオッケー、などと考えているとMITM(Man-in-the-Middle)攻撃(後述)を受けていることにすら気づくことが出来ないため危険。
- よって、歴とした団体でありたいなら、オレオレ証明書は使うべきではない。
∧_∧ カタカタ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ) ∧ ∧ < SSLには証明書が必要です…と。 ( ) (,,°Д°) \____________  ̄ ̄ ̄ ̄ ̄ (つ_つ____  ̄ ̄ ̄日∇ ̄\| VAIO |\  ̄ ========= \ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ | ほう、公開鍵暗号でセキュアプロトコルですか? \  ̄ ̄ ̄|/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ・∀・) ∧ ∧ < な、なんですか?あなた・・・ ( ⊃ ) (°Д°;) \____________  ̄ ̄ ̄ ̄ ̄ (つ_つ____  ̄ ̄ ̄日∇ ̄\| VAIO |\  ̄ ========= \ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ | 証明書は自分で作ってルート入れさせとけば無料ですませる… \  ̄ ̄ ̄|/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ・∀・) ∧ ∧ < それだとフィンガープリントの照合が必要になる… ( ) (;°Д°) \____________  ̄ ̄ ̄ ̄ ̄ (つ_つ____  ̄ ̄ ̄日∇ ̄\| VAIO |\  ̄ ========= \ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ | フィンガープリントもSSLで送れば大丈夫、と。 \  ̄ ̄ ̄|/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ・∀・) ∧ ∧ < フィンガープリント送るときのSSLの証明書も照合しなきゃだめでしょ!! ( ⊃ ) (°Д°;) \____________  ̄ ̄ ̄ ̄ ̄ (つ_つ____  ̄ ̄ ̄日∇ ̄\| VAIO |\  ̄ ========= \ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -http://takagi-hiromitsu.jp/diary/20050123.html#f01
MITM攻撃
- 信頼出来ない証明書を許容すると、SSLによる暗号化を破ることが出来る。
- MITM前提の設計をするのであれば、お金が絡む部分など、クリティカルな処理はサーバー側に集約する必要がある。
AliceとBobが、Bobのオレオレ証明書を使ったSSL通信を行う。 Eveは中間者でAliceとBobの暗号通信を盗聴する。 SSL(NAME) := NAMEのオレオレ証明書によるSSL通信 【通常の通信】 Alice ← SSL(Bob) → Bob 【MITM攻撃を受けている状態】 Alice ← SSL(Eve) → Eve ← SSL(Bob) → Bob AliceがBobのオレオレ証明書をいつも信頼していると、 Eveのオレオレ証明書にすり替わっていても、そのことに気づかない。
CSRF(Cross Site Request Forgeries)
- 端的に言えば「ユーザの意図しない自動投稿(submit)」。
- 攻撃者は、CSRF対策されていないサイトに対して、適切なパラメータで適切なURLにGET/POSTするプログラムを書き、ばら撒く。
- 最も手軽なのは、JavaScriptでAjaxで自動投稿するプログラムを書き、罠サイトを用意し、URLを拡散する方法。
- GET/POSTが出来さえすれば良いので、もちろんネイティブアプリで拡散しても良い。
- 一般ユーザがばら撒かれたプログラムを実行すると、そのユーザのアクションとして、何らかのGET/POSTが行われる。
- 対策の方針は「GET/POSTリクエストが正規のものであるかをチェックすること」
- 一番お手軽な罠サイトのパターンを防ぐのであれば、リファラチェックが有効。
- Ajaxには前述の通りXMLHttpRequest#setRequestHeaderというメソッドがあるが、refererはセキュリティの都合上セットできない。(参考:セットできないヘッダのリスト)
- リファラが空の場合は拒否しなければならない。この点については賛否両論ある。
- リファラは偽装できるので、リファラチェックだけでは、リファラを偽装する専用ツールに対抗できない。
- 専用ツール対策としてはhiddenフィールドを使った固定トークン方式が一般的。
- セッションIDは固定トークンであるが、HTMLのソース自体が流出する可能性も無いとはいえないので*5、セッションIDとは別の専用IDを作成して利用したほうが無難。
- クリティカルな処理の最後のステップでパスワードを入れさせるという手法もある。
- ワンタイムトークンを使う方法もある。
- 一番お手軽な罠サイトのパターンを防ぐのであれば、リファラチェックが有効。
- 警察が殺人予告などにシビアになっているため、今後は、特に一般に投稿メッセージが公開される系のウェブサービスでは、対策が必須になるか。
- 参考
- 開発者のための正しいCSRF対策
- 高木浩光@自宅の日記 - クロスサイトリクエストフォージェリ(CSRF)の正しい対策方法
- 安全なWebアプリケーションの作り方 初版 4.5章 (p.141)、徳丸浩、2011
XSS(Cross Site Scripting)
外部からの入力シリーズ1
- システム外からの入力を用いてHTMLなどを構成し出力する時に起きうる脆弱性。
- 一番単純な例「GETやPOSTで受け取ったパラメータを、そのままHTML出力する。」
- script要素を含んだパラメータを送ることで、レスポンス表示時に任意のプログラムをWebサイトに組み込み、実行することが可能。
- 罠サイトを用意して、攻撃スクリプトを含むパラメータでGET/POSTすれば、セッションハイジャック等ができる仕組み。
- DBを経由するなど、間接的に入ってくる場合もある。
- 一番単純な例「GETやPOSTで受け取ったパラメータを、そのままHTML出力する。」
- 対策方法は、出力時に適切にエスケープを行うこと。
- 多重エスケープしないように、出力時にのみ行うように習慣づけることが重要。
- HTML以外でもスクリプトを実行する手段があるので、注意する。
- ex. IEはCSSでJavaScriptを実行できる。
SQLインジェクション
外部からの入力シリーズ2
- システム外からの入力を用いてSQLクエリを構成し実行する時に起きうる脆弱性。
- 対策としては、DBのPrepared StatementのPlaceholder機能を使うのが鉄板。
- 手動でのエスケープは、DBによってエスケープの仕方が異なるなど、非常に危険。エスケープするにしても、DB提供のライブラリを使うべき。(ex. mysql_real_escape_string)
- Prepared Statementを使っていても、NULL文字関係で脆弱性が生じることがあるので注意。
言うまでもないが、SQLのみならず、いわゆるeval関数やsystem関数などでも注意が必要。
バッファオーバーフロー
もしくはバッファオーバーラン。
- 低レイヤの脆弱性。
- 典型的な例としては、想定よりも長い文字列が与えられて、スタックを上書きしてしまうなど。
- とにかくポインタを扱う時は注意が必要ということ。
- バッファオーバーラン*7ではないが、最近のSSLのheartbleed脆弱性も似たようなお話。
その他
思いついたら書きます。