2013/06/30 Category : 覚書 development Webアプリのセキュリティ対策に関する簡単なまとめ 今のところ、私の知る限り以下のような脅威が存在する。各脅威の詳細についてはそのうち書くかもしれない。ここでは、結局どうすればいいのかをメモ程度にざっくりまとめる。攻撃1.xss(クロスサイトスクリプティング)2.CSRF(クロスサイトリクエストフォージェリ)3.ディレクトリトラバーサル4.クリックジャッキング5.セッションハイジャッキング6.IPスプーフィング7.SQLインジェクション8.バッファオーバーフロー9.OSコマンドインジェクション10.HTTPヘッダーインジェクション11.DNSリバインディング12.hashdos攻撃13.メールヘッダインジェクション対策まず、大前提として、「外部から入ってきたリクエストやファイルは全て汚染されている」と考え、以下を実施する。・リクエスト値の正常性(型、サイズ)をチェックする・レスポンスとして出力するもの全て(ヘッダ、ボディ)にエスケープ処理を施す ・ヘッダ → URL(スキームやクエリストリング含む)、クッキーの値 ・ボディ → html特殊文字の無効化 ・JS → JSONP対策・外部サイトのファイル(javascriptやcssなど)は原則として読み込まないその上で、個別対策として、以下を施す。1.xss(クロスサイトスクリプティング)・<script>要素の内容を動的に生成しない・JavaScriptからcookieを取り出せないようにする 例)プログラムでクッキーをセットする際、HttpOnly属性をつける ※アドレスバーに javascript:document.cookie と打って確認する・レスポンスヘッダのContent-Typeに文字コードの指定を含める 例)プログラム側で header['Content-Type'] = 'text/html; charset=UTF-8'・念のため、レスポンスヘッダにXSS対策をしておく 例)nginxに設定する場合 add_header X-XSS-Protection "1; mode=block";2.CSRF(クロスサイトリクエストフォージェリ)・ユーザ固有のトークン(必ずしもワンタイムである必要はない)をセッションに格納しておく。・ユーザ入力はPOSTで受けるようにし、その中にhiddenパラメータでトークンを仕込み、セッションに格納したトークンと同じかどうか確認。(同一性確認)・処理を実行する直前のページでパスワードの入力を求める(ユーザの意思の再確認)・Refererが正しいリンク元かを確認する(同一性確認)・重要な処理をした後は、ユーザ宛にメールを送信する(ユーザの意思の再確認。対策とまでは言えないが、被害を最小限にとどめる)3.ディレクトリトラバーサル・外部からのパラメータでファイルを直接開くような実装をしない。 例)File.open(params['filename'])4.クリックジャッキング・レスポンスヘッダにframe表示を許可しないことを明示する。サーバ側でやってもいいし、プログラムでやってもいい。 例)nginxに設定する場合 add_header X-Frame-Options DENY;5.セッションハイジャッキング・セッションIDを複雑で推測しづらいものにする(総当たり対策)・セッションIDをGET変数で渡さない(盗聴対策)・HTTPSの場合はcookieにsecure属性をつける(盗聴対策)・ログイン成功時に、新しくセッションを開始する(session fixation対策)・Webサーバの設定でTRACEメソッドを許可しない(cookie盗難対策) ※nginxは元々TRACEメソッドを許可しない。apacheは設定が必要。6.IPスプーフィング・サーバOSがunix系なら/etc/sysctl.confのrp_filterを有効にして送信元IPアドレスの偽装を防止する(不正侵入対策)。 例) net.ipv4.conf.all.rp_filter = 1 ※記入後、再起動することによって有効になる。・アプリケーションで不用意にIPアドレスによる認可をするような仕組みを作らない。・サーバ監視ツール等で怪しい動きをしているIPをブロックする。・IPSpoofing + DoS攻撃に対する根本的な対策は今のところないので、上記のようなサーバ監視で対処する。・Rackには対策ミドルウェアがあるので、Rackを使う場合はそれを使う(が、万能ではない)。7.SQLインジェクション・ユーザ入力値をSQL文生成に利用する際はプレースホルダを使う。8.バッファオーバーフロー 入力値チェックの際、サイズのチェックもする。9.OSコマンドインジェクション 外部からのパラメータで、実行する関数を直接指定出来てしまうような実装をしない。 例) exec(params[command])10.HTTPヘッダーインジェクション ヘッダの出力にはアプリケーションや言語に用意されているAPIを利用する。 ヘッダ生成の際、外部からのパラメータをそのまま使わない。 改行コードをサニタイズする(cookie含む。APIがサニタイズ出来ない場合は自前で実装する)。11.DNSリバインディング ダミーのバーチャルホストを用意する。nginxなら以下のようにダミー専用サーバをおけばオッケー。server {listen 80 default_server;server_name _;return 444;}12.hashdos攻撃 Rubyなら 1.9.0以降を使う。13.メールヘッダインジェクション 外部入力はメールボディにのみ出力し、ヘッダは固定値にする 出来るだけ開発環境や言語に用意されているメール送信用APIを使用する HTMLで宛先を指定しないこれらをしっかり行うことにより、大抵の攻撃から身を守ることが出来る。 PR