ウェブアプリケーションにおける脆弱性対策について、その性質を基に「根本的解決」
と「保険的対策」の 2 つに分類しています。
根本的解決
本書における「根本的解決」は、「脆弱性を作り込まない実装」を実現する手法です。根本的解決を
実施することにより、その脆弱性を狙った攻撃が無効化されることを期待できます。
■ 保険的対策
本書における「保険的対策」は、「攻撃による影響を軽減する対策」です。根本的解決とは違って、
脆弱性の原因そのものを無くすものではありませんが、攻撃から被害までの次の各フェーズにおいて、
それぞれの影響を軽減できます。
攻撃される可能性を低減する
(例:攻撃につながるヒントを与えない)
攻撃された場合に、脆弱性を突かれる可能性を低減する
(例:入力から攻撃に使われるデータをサニタイズ(無効化)する)
脆弱性を突かれた場合に、被害範囲を最小化する
(例:アクセス制御)
被害が生じた場合に、早期に知る
(例:事後通知)
保険的対策は、対策の内容によっては、本来の機能を制限することになるものもあるので、そのような副作用の影響も考慮する必要があります。
1. ウェブアプリケーションのセキュリティ実装
1) SQL インジェクション
・SQL 文の組み立て方法に問題がある場合、攻撃によってデータベースの不正利用をまねく可能性があります。このような問題を「SQL インジェクションの脆弱性」と呼びます。
・対応方法
→ SQL 文の組み立ては全てプレースホルダで実装する。
→ SQL 文の組み立てを文字列連結により行う場合は、エスケープ処理等を行うデータベースエンジンの API を用いて、SQL 文のリテラルを正しく構成する。
2) OS コマンド・インジェクション
・ウェブアプリケーションによっては、外部からの攻撃により、ウェブサーバの OS コマンドを不正に実行
・対応方法
→ ウェブアプリケーションに利用されている言語によっては、シェルを起動できる機能を持つものがあります。たとえば、Perl の open 関数等です。Perl の open 関数は、引数として与えるファイルパスに「|」(パイプ)を使うことで OS コマンドを実行できるため、外部からの入力値を引数として利用する実装は危険です。シェルを起動できる言語機能の利用は避けて、他の関数等で代替してください。Perl でファイルを開く場合、sysopen 関数を利用すればシェルを起動することはありません。
→ シェルを起動できる言語機能の引数を構成する変数に対し、引数に埋め込む前にチェックをかけ、本来想定する動作のみを実行するように実装
3) パス名パラメータの未チェック/ディレクトリ・トラバーサル
・外部からのパラメータにウェブサーバ内のファイル名を直接指定しているものがあります。このようなウェブアプリケーションでは、ファイル名指定の実装に問題がある場合、攻撃者に任意のファイルを指定され、ウェブアプリケーションが意図しない処理を行ってしまう可能性があります。
・対応方法
→ ウェブサーバ内に保管しているファイルへのアクセス権限が正しく管理
→ 入力パラメータの値から、「/」、「../」、「..\」等、OS のパス名解釈でディレクトリを指定できる文字列を検出した場合は、処理を中止します。
4) セッション管理の不備
・セッション ID の発行や管理に不備がある場合、悪意のある人にログイン中の利用者のセッション ID を不正に取得され、その利用者になりすましてアクセスされてしまう可能性があります。この問題を悪用した攻撃手法を、「セッション・ハイジャック」と呼びます。
・対応方法
→ セッション ID を推測が困難なものにする。
→ セッション ID を URL パラメータに格納しない。
→ HTTPS 通信で利用する Cookie には secure 属性を加える。
→ ログイン成功後に、新しくセッションを開始する。
→ ログイン成功後に、既存のセッション ID とは別に秘密情報を発行し、ページの遷移
ごとにその値を確認する。
→ セッション ID を固定値にしない。
→ セッション ID を Cookie にセットする場合、有効期限の設定に注意する。
5) クロスサイト・スクリプティング
・ウェブページへの出力処理に問題がある場合、そのウェブページにスクリプト等を埋め込まれてしまいます。この問題を「クロスサイト・スクリプティングの脆弱性」と呼びます。
・対応方法
→ ウェブページに出力する全ての要素に対して、エスケープ処理を施す。
→ URL を出力するときは、「http://」や 「https://」で始まる URL のみを許可する。
→ script要素の内容を動的に生成しない。
→ スタイルシートを任意のサイトから取り込めるようにしない。
→ 入力値の内容チェックを行う。
→ 入力された HTML テキストから、スクリプトに該当する文字列を排除する。
→ HTTP レスポンスヘッダの Content-Type フィールドに文字コード(charset)を指定する。
6) CSRF(クロスサイト・リクエスト・フォージェリ)
・ウェブサイトの中には、サービスの提供に際しログイン機能を設けているものがあります。ここで、ログインした利用者からのリクエストについて、その利用者が意図したリクエストであるかどうかを識別する仕組みを持たないウェブサイトは、外部サイトを経由した悪意のあるリクエストを受け入れてしまう場合があります。このようなウェブサイトにログインした利用者は、悪意のある人が用意した罠により、利用者が予期しない処理を実行させられてしまう可能性があります。このような問題を「CSRF(Cross-Site RequestForgeries/クロスサイト・リクエスト・フォージェリ)の脆弱性」と呼び、これを悪用した攻撃を、「CSRF 攻撃」と呼びます。
・対応方法
→ 処理を実行するページを POST メソッドでアクセスするようにし、その「hidden パラメータ」に秘密情報が挿入されるよう、前のページを自動生成して、実行ページではその値が正しい場合のみ処理を実行する。
→ 処理を実行する直前のページで再度パスワードの入力を求め、実行ページでは、再度入力されたパスワードが正しい場合のみ処理を実行する。
→ Referer が正しいリンク元かを確認し、正しい場合のみ処理を実行する。
→ 重要な操作を行った際に、その旨を登録済みのメールアドレスに自動送信する。
7) HTTP ヘッダ・インジェクション
・対応方法
→ 改行コードを適切に処理するヘッダ出力用 API を利用できない場合は、改行を許可しないよう、開発者自身で適切な処理を実装する。
→ 外部からの入力の全てについて、改行コードを削除する。
8) メールヘッダ・インジェクション
・外部の利用者がこのメールアドレスを自由に指定できてしまう場合があります。このような問題を引き起こす脆弱性を「メールヘッダ・インジェクション」と呼びます。
・対応方法
→ メールヘッダを固定値にして、外部からの入力はすべてメール本文に出力する
→ メールヘッダを固定値にできない場合、ウェブアプリケーションの実行環境や言語に用意されているメール送信用 API を使用する。
→ HTML で宛先を指定しない。
→ 外部からの入力の全てについて、改行コードを削除する。
9) クリックジャッキング
・ウェブサイトの中には、ログイン機能を設け、ログインしている利用者のみが使用可能な機能を提供しているものがあります。該当する機能がマウス操作のみで使用可能な場合、細工された外部サイトを閲覧し操作することにより、利用者が誤操作し、意図しない機能を実行させられる可能性があります。このような問題を「クリックジャッキングの脆弱性」と呼びます。
・対応方法
→ HTTP レスポンスヘッダに、X-Frame-Options ヘッダフィールドを出力し、他ドメインのサイトからの frame 要素や iframe 要素による読み込みを制限する。
→ 処理を実行する直前のページで再度パスワードの入力を求め、実行ページでは、再度入力されたパスワードが正しい場合のみ処理を実行する。
→ 重要な処理は、一連の操作をマウスのみで実行できないようにする。
10)バッファオーバーフロー
・ウェブアプリケーションを含む、あらゆるプログラムは、指示された処理を行うためにメモリ上に自身が使用する領域を確保します。プログラムが入力されたデータを適切に扱わない場合、プログラムが確保したメモリの領域を超えて領域外のメモリを上書きされ、意図しないコードを実行してしまう可能性があります。このような問題を「バッファオーバーフローの脆弱性」と呼びます。
・対応方法
→ 直接メモリにアクセスできない言語で記述する。
→ 直接メモリにアクセスできる言語で記述する部分を最小限にする。
→ 脆弱性が修正されたバージョンのライブラリを使用する。
