Webアプリケーションのセキュリティ対策まとめ

Webアプリケーションのセキュリティ対策本として定番の「体系的に学ぶ 安全なWebアプリケーションの作り方」を読みました。

Rails等のWebアプリケーション・フレームワークやHerokuのようなPaaSの存在により、個人でもWebアプリケーションを作って公開できる環境が整いつつあります。

しかし、十分なセキュリティ対策ができるか心配で踏み出せないという人は多いのではないでしょうか。

ここでは、「体系的に学ぶ 安全なWebアプリケーションの作り方」から、具体的にどのようなセキュリティ対策を施せば良いのかという点にフォーカスして、要点をまとめたいと思います。

Webアプリケーションのセキュリティ基礎

セッション管理

URLにセッションIDや秘密情報を含めると、Referer経由で外部に漏洩し、成りすましに悪用される可能性がある。

セッションIDは十分な桁数の乱数(なるべく自作ではなくツールで提供される機能)でクッキーに保存する。

秘密情報はセッション変数に保存する。

クッキー

セッションやサーバをまたがって情報を保存する必要がある場合(セッションIDなど)のみクッキーを使用する。

クッキーはデータ量に制限があることや、利用者が参照・変更できてしまうことから、上記以外はセッション変数を使用する。

クッキーの属性設定

Domain属性

  • クッキーを複数のサーバに送信させたい場合のみ設定する
  • 通常は設定しない

HttpOnly属性

  • JavaScriptからクッキーへのアクセスを禁止する
  • JavaScriptからのアクセスが必要がない場合、常に設定するのが望ましい

Secure属性

  • HTTPSの場合のみクッキーをサーバに送信する
  • セッションIDなどの秘密情報の盗聴を防ぐため、常に設定するのが望ましい

HTTPとHTTPSのページが混在しており、セッションIDを保存したクッキーにセキュア属性が付けられない場合、セキュア属性付きのトークンを別途発行して、HTTPSページでのセッションハイジャックを防止する方法がある。

入力処理

入力値に対して以下の処理を行う。

  • 文字コードを使った攻撃を防ぐため、エンコーディングの妥当性を検証する
    (開発言語毎の関数を使用)
  • 必要に応じてエンコーディングを変換する
    (開発言語毎の関数を使用)
  • 入力値の妥当性を検証する
    (正規表現を使用)

正規表現の先頭と末尾は「^」「$」ではなく「\A」と「\z」で示す。(「$」は改行にマッチするため不具合が生じる場合がある)

ブラウザ上で変更できない値(ラジオボタンの選択値、hiddenパラメータなど)もツールによって書き換え可能なので注意する。

全てのパラメータについて最大文字数を仕様として定義する。

文字エンコーディングの中ではUTF-8がもっとも扱いやすく安全な方式。「尾骶骨」という3文字をデータベースに登録した後画面に表示させることで、データベースが一貫してUnicodeで設定されているか確認することができる。

Webアプリケーションの脆弱性別対策

XSS対策

HTML要素の内容は以下のエスケープを行う。

< → &lt;
& → &amp;

HTML属性値はダブルクォートで囲い、以下のエスケープを行う。

< → &lt;
" → &quot;
& → &amp;

JavaScript文字列リテラルは以下のエスケープを行い、さらにHTMLエスケープする。

\    → \\
'    → \'
"    → \"
改行 → \n

URLをプログラムで生成する場合は、「http」「https」「/」で始まるURLのみを許可する。

SQLインジェクション対策

静的プレースホルダを使用してSQLを実行する。

詳細なエラーメッセージを抑止することで、万一SQLインジェクション脆弱性の対策漏れがあっても、被害にあいにくくすることができる。

データベースユーザに対しては、必要最小限な権限のみを与える。

CSRF対策

第三者に予測不可能なトークンを要求することにより、CSRF攻撃を防ぐことができる。

推測可能なセッションIDによる脆弱性を作りこまないためには、セッション管理機構を自作せず、実績のある言語やミドルウェアが提供するセッション管理機構を使用する。

他に、利用者の意図したリクエストであることを確認する方法として、パスワードの再入力を求める方法がある。

セッションIDの固定化攻撃対策

認証後にセッションIDを変更する。

セッションIDを明示的に変更できない場合は、認証後にトークンを生成してクッキーとセッション変数の両方に記憶させ、以降これを比較する。

HTTPヘッダ・インジェクション対策

HTTPヘッダの出力部分を手作りせず、ヘッダ出力用のライブラリやAPIを利用する。

文字列中に改行コードが含まれている場合は、エラーとして処理を中止する。

メールヘッダ・インジェクション対策

メール送信にsendmailコマンドなどではなく、専用のライブラリを使用する。

文字列中に改行コードが含まれている場合は、エラーとして処理を中止する。

ディレクトリ・トラバーサル対策

ファイル名を外部から指定することを避ける。

ファイル名の文字種を英数字に限定する。

意図しないファイル公開対策

非公開ファイルを公開ディレクトリに置かない。

サーバの設定でディレクトリ・リスティングを無効にする

httpd.conf 設定例
    <Directory パス指定>
        Options -Indexes その他のオプション
        その他の設定
    </Directory>

.htaccess 設定例
    Options -Indexes

ファイルの閲覧を禁止する。

.htaccess 設定例
    <Files "*.txt">
        deny from all
    </Files>

OSコマンド・インジェクション対策

OSコマンドを呼び出さない。(シェルを呼び出せる機能を利用しない)

コマンドラインにパラメータを渡さない。

アップロード機能に対するDoS攻撃対策

サーバの設定でリクエストボディサイズを絞る。

httpd.conf 設定例
    LimitRequestBody 102400

アップロードファイルによるスクリプト実行対策

アップロードされたファイルは公開ディレクトリにおかず、スクリプト経由で閲覧させる。

アップロードできるファイルの拡張子を制限する。

ファイルダウンロードによるXSS脆弱性対策

ファイルアップロード時の対策
  • 拡張子が許可されたものかチェック
  • 画像の場合は、マジックバイト(ファイルの識別に使用できる固定先頭文字列)を確認

IE7以前ではContent-Typeとマジックバイトが一致しない場合、ファイルタイプの判定でファイルの中身が優先され、画像に偽装したHTMLやJavaScriptが実行される可能性がある。

このため、拡張子に対応する正しいマジックバイトが設定されていることを確認する必要がある。

ファイルダウンロード時の対策
  • Content-Typeを正しく設定する
  • 画像の場合は、マジックバイトを確認

または、以下のヘッダを設定してアプリケーションで開かずダウンロードさせる方法がある。

Content-Disposition: attachment
Content-Type: application/octet-stream

evalインジェクション対策

evalを使わない。

evalの引数に外部からのパラメータを使わない。

外部からのパラメータを英数字に制限する。

ヌルバイト攻撃対策

入力値に制御文字が混入していないことを確認する。

正規表現では[:^cntrl:]というPOSIX文字クラスにより制御文字以外という指定が可能。

textarea要素では/\A[\r\n\r[:^cntrl:]]{1,400}\z/のようにして改行・タブを許可することができる。

ハッシュ解読対策

パスワードなどをハッシュで保存する場合、ハッシュを生成する元データに文字列(ソルト)を追加する。

これによりパスワードを長くするとともに、ソルトをユーザ毎に異なるものにすることで、パスワードが同じでも異なるハッシュ値が生成されるようになる。

ソルトにはユーザIDを使用すると、別途ソルトを保存する必要がなく便利。

権限書き換え対策

権限情報はセッション変数に保持することで、利用者によって書き換えられないようにする。

処理や表示の直前に権限の確認をする。

メールの第三者への送信予防

メールアドレスを登録・変更する際には、メールを利用者自信が受信できることを確認する。

確認方法として以下の2種類がある。(フィッシング予防の観点から、後者の方が望ましい)

  • メールにトークン付きURLを記載し、そのURLから処理を継続する
  • メールにトークンを記載し、トークンを画面に入力させる

通信の盗聴・改ざん対策

HTTPSのページでは、画像やCSS、JavaScriptなども改ざんを防ぐためHTTPSで指定する。

一つのページにHTTPとHTTPSが混在していると、ブラウザによってはアラートメッセージが表示される。(例:「このページにはセキュリティで保護されている項目と保護されていない項目が含まれています。保護されていない項目を表示しますか?」)

イスラエルのStartComという企業は、無料のサーバー証明書を発行している。

関連ページ

おわりに

体系的に学ぶ 安全なWebアプリケーションの作り方」では、このほか脆弱性の原理や攻撃手法についても詳しく解説されています。

ただ、なにぶん分厚くて、すべてを覚えるのは大変なので、チートシートのようなものが作れればよいなと思い、本記事では対策部分を中心にまとめました。

なお、ここでの内容はあくまで私個人が気になった点についてまとめたもので、書籍の内容を網羅したものではないのでご注意下さい。

blog comments powered by Disqus