3-1 フィルタリング [PHPセキュリティー]
フィルタリングとは
- フィルタとはデータを期待した内容に強制すること
- フィルタはセキュリティーの要
- すべての入力データにフィルタを行う
フィルタとは汚染リスクのあるデータを期待した内容に強制し信頼できるデータにすることです。
例えば、HTMLフォームに電話番号入力欄があるとします。開発者はこの textarea に半角数値を期待しているとします。ですが、ユーザーは全角数値を入力するかもしれません。あるいは、悪意のあるjavascriptコードを入力するかもしれません。ユーザーが意図するしないに関わらず、そのようなデータが入力され送信された場合、PHPでは受け付けないように処理する必要があります。「半角数値のみ有効」という処理を行うことで、期待したデータへ強制させる必要があります。
フィルタは非常に大切であり、セキュリティーの要となります。フィルタはデータの発信元の如何を問わず、すべての入力データに対して行いましょう。そうすることで、データの汚染リスクを排除することが出来ます。フィルタされたデータのみを使えば、多くの脆弱性からアプリケーションを守ることが出来ます。
では、どのようなデータが汚染リスクのある入力データなのか、また、入力データをどのようにフィルタするのか、以下で具体的に紹介したいと思います。
入力フィルタの三段階
- 入力の識別
- 入力フィルタ
- フィルタされたデータと汚染リスクがあるデータの区別
最初に入力を識別する必要があります。どのデータがどのから来た入力データなのかを識別しましょう。そして入力と識別されたデータを適切にフィルタ処理して汚染リスクを排除します。最後に、フィルタしたクリーンなデータとそうでないデータを区別して、混同しないようにしましょう。せっかく入力データをフィルタ処理してクリーンなデータを作っても、誤って汚染リスクのあるデータを使用してしまっては元も子もありませんからね。
入力の識別
- 入力の識別
- 入力とはリモートソースを起源とするデータのこと
- リモートソースとはhttpクライアント、データベース、セッションコンテナなど
入力とはリモートソースを起源とする任意のデータのことです。リモートソースとは、httpクライアント、データベース、セッションデータコンテナ、RSSフィード、APIなどで取得したデータ、などのことです。PHP自身で作成したデータ以外はすべて入力データとなります。
入力の識別とは、上記したリモートソースを追跡して、データがどこから来たのか、どこに保存されているのか、を識別することです。
ブラウザから送信されてきたデータ、URLから送信されてきたデータ、データベースに保存されているデータ、セッションデータコンテナに保存されているデータ、このようにそのデータがどこを起源とするデータであるのかを識別することが、入力の識別です。
入力データ
- 入力データとは、HTMLフォーム、URL、クッキーなどhttpクライアントから送信されるデータ、データベースやセッションコンテナから取得したデータ、RSSやAPIから取得したデータ、これらリモートソースを起源とするデータのこと
- 入力データはPHP自身で作成したデータ以外すべて
HTMLフォームやURL等から渡されてくるデータ $_POST や $_GETなど、あるいは、クッキーから渡されてくるデータ $_COOKIE、データベースから取得したデータ、セッションコンテナから取得したデータ $_SESSION、これらすべては入力データデータであり、汚染されている可能性があります。
つまり、入力データとはアプリケーション自身で作成したデータ以外のことです。リモートソースを起源とするデータです。
入力データ
1 2 3 4 | echo $_POST['name']; echo $_GET['name']; echo $_COOKIE['name']; echo $_SESSION['name']; |
PHP自身で作成したデータ
1 | $mail = 'mail@wepicks.net'; |
入力のフィルタ
- 入力のフィルタで不正なデータを検出する
- ホワイトリスト方式
- フィルタでデータの修正をしない
入力のフィルタは、サニタイズ、バリデート、クリーニング、スクラッブなどといいます。動的な文字列などは正規表現でフィルタを行います。正規表現で入力データをチェックする場合は、しっかりと検証して不正なデータを検出できることを確実にしましょう。正規表現の例はこちらを参照下さい。
フィルタはホワイトリスト方式を利用しましょう。ホワイトリスト方式とは、「データが有効である」条件を定義して、その条件を満たさないデータはすべて無効にする方式のことです。
フィルタは入力データをチェックする機能のみとして、フィルタで無効なデータを修正しないようにしましょう。修正処理にミスがある場合は新たな脆弱性が発生することになります。
正規表現の例
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php //正規表現 ひらがな の判別 $checkStr = 'あいうえおかきくけこ'; if(preg_match('/[^ぁ-んー]/u',$checkStr)) echo 'すべて ひらがな でない'; else echo 'すべて ひらがな'; //正規表現 半角英字 の判別 $checkStr = 'あいうえおかきくけこ'; if(preg_match('/[^ぁ-んー]/u',$checkStr)) echo 'すべて ひらがな でない'; else echo 'すべて ひらがな'; //正規表現 数値 の判別 $checkStr = 123456789; if(!preg_match('/^[0-9]+$/', $checkStr)) echo 'すべて 数値 ではない'; else echo 'すべて 数値' ?> |
結果は
すべて ひらがな
すべて 数値
となります。
フォームからのデータをフィルタする
input.php 入力フォーム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php //input.php //フォーム ?> <form action="check.php" method="POST"> 趣味を選択して下さい。 <select name="hoby"> <option value="read">読書</option> <option value="music">音楽鑑賞</option> <option value="sports">スポーツ</option> </select> <input type="submit"> </form> <?php //この場合、クライアントからは$_POST['hoby']の値として、あらゆるデータを送信することが出来ます。 //入力データには適切なフィルタを行う必要があります。 ?> |
↓
check.php フィルタ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php //check.php //フィルタ //初期化した汚染リスクのない変数を用意する $clean = array(); //フィルタ switch($_POST['hoby']){ case 'read': case 'music': case 'sports': $clean['hoby'] = $_POST['hoby'];//初期化した変数に代入 break; } //httpクライアントへ出力 $clean['hoby']は汚染リスクのない信頼できるデータ echo $clean['hoby']; ?> |
フィルタはホワイトリスト方式
- フィルタはホワイトリスト方式を利用する
フィルタはホワイトリスト方式を利用しましょう。ホワイトリスト方式とは、「データが有効である」条件を定義して、その条件を満たさないデータはすべて無効にする方式のことです。以下にホワイトリスト方式を利用したフィルタ処理を紹介します。
フィルタの例
下記の例では、有効である場合に限り初期化した変数$capitalCityへ入力データ$_POST[‘capitalCity’]を代入しています。代入されなければ、初期化した変数$capitalCityが出力されるだけなので安全です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <h3>ホワイトリスト方式</h3> <?php //変数初期化 $capitalCity = ''; //入力データ フォーム等で入力された$_POST['capitalCity']は汚染リスクがあるデータ $_POST['capitalCity'] = 'Tokyo'; //入力フィルタ ホワイトリスト方式 if($_POST['capitalCity'] === 'Tokyo' || $_POST['capitalCity'] === 'London' || $_POST['capitalCity'] === 'Washington'){ $capitalCity = $_POST['capitalCity'];//有効である場合に限り初期化した変数に代入 } //httpクライアントへ出力 $capitalCityは汚染リスクのない信頼できるデータ echo '$capitalCity:'.$capitalCity; ?> <h3>ホワイトリスト方式</h3> <?php //変数初期化 $capitalCity = ''; //入力データ フォーム等で入力された$_POST['capitalCity']は汚染リスクがあるデータ $_POST['capitalCity'] = 'New York'; //入力フィルタ ホワイトリスト方式 switch($_POST['capitalCity']){ case 'Tokyo': case 'London': case 'Washington': $capitalCity = $_POST['capitalCity'];//有効である場合に限り初期化した変数に代入 break; } //httpクライアントへ出力 $capitalCityは汚染リスクのない信頼できるデータ echo '$capitalCity:'.$capitalCity; ?> |
結果は
$capitalCity:Tokyo
ホワイトリスト方式
$capitalCity:
となります。
フィルタで無効なデータを修正しない
- フィルタで無効なデータを修正しない
フィルタは入力データをチェックする機能のみとして、フィルタで無効なデータを修正しないようにしましょう。修正処理にミスがある場合は新たな脆弱性が発生することになります。
フィルタされたデータと汚染リスクがあるデータの区別
- 初期化した変数へフィルタしたデータを代入
フィルタされたデータを汚染リスクのない初期化した変数に代入してしっかりと区別しましょう。
初期化した変数へフィルタ後のデータを格納する
1 2 3 4 5 6 7 | <?php //変数初期化 $clean = array(); //フィルタ処理を行った後に汚染リスクのない初期化した変数へ代入し区別する $clean['userid'] = $_POST['userid']; ?> |
変数の初期化
1 2 3 4 5 6 7 8 | <?php $str = "";//文字列(string)初期化 $int = 0;//数値(integer)初期化 $dble = 0.0;//浮動小数点(double)初期化 $ary = array();//配列(array)初期化 $bln = true;//理論値(boolean)初期化 $obj = NULL;//オブジェクト(object)初期化 ?> |
タグ(=記事関連ワード)
日付
最終更新日:2017年08月09日