4-1 エスケープ処理 [PHPセキュリティー]
エスケープとは
- エスケープは出力先に合わせてデータを適切な形にすること
エスケープは非常に大切であり、セキュリティーの要となります。エスケープとは出力先であるリモートソースに合わせてデータの内容を適切な形にすることです。例えば、httpクライアント(ブラウザ)への出力時、データベースへ送信時、など、PHPから別の場所にデータを送信する際には、そのデータを適切にエスケープ処理する必要がある。出力先で誤った解釈をさせるとアプリケーションに重大な脆弱性が発生する可能性があります。
出力エスケープの三段階
- 出力の識別
- 出力のエスケープ
- エスケープされたデータとそうでないデータの区別
最初に出力を識別する必要があります。どのデータをどこへ出力するのか識別しましょう。そして出力と識別されたデータを適切にエスケープ処理ます。最後に、エスケープしたデータとそうでないデータを区別して、混同しないようにしましょう。
出力の識別
- 出力の識別
- 主な出力先は、httpクライアント、URL、データベース
出力とは、PHP以外のリモートソースにデータを送信することです。主な出力先(リモートソース)は、httpクライアント、URL、データベース、などです。
httpクライアント
1 2 3 | echo 出力データ; print 出力データ; <?= 出力データ ?> |
等を使用します。echo や print を使用して、httpクライアントへデータを出力していることになります。この場合、httpクライアントへデータを出力しているという識別が出来ます。
URLの場合
1 | <a href="出力データ">TRY PHP</a> |
や
1 2 3 | <?php header("Location: 出力データ"); ?> |
等を使用します。上記の場合はURLへデータが出力されるという識別が出来ます。
データベース
1 2 3 | <?php mysqli_query(出力データ); ?> |
出力のエスケープ
- 出力のエスケープ
- htmlentities() mysqli_real_escape_string() urlencode()
上記で示したように出力と識別されたデータは適切にエスケープする必要があります。出力のエスケープとは、出力先であるリモートソースに合わせてデータを適切な形に変更することです。
httpクライアント(ブラウザ)出力時のエスケープ
- htmlentities()
httpクライアントへ送信するデータをエスケープする場合、PHPの関数 htmlentities() を使用しましょう。この関数でデータをエスケープすることで、htmlとして意味のある文字列が変換されて無効化されます。
1 | string htmlentities ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' [, bool $double_encode = true ]]] ) |
※[ ]は省略可能
例
1 2 3 4 5 6 | <?php //文字列をエスケープ $escapeString = htmlentities($string, ENT_QUOTES, 'UTF-8'); //httpクライアントへ出力 echo $escapeString; ?> |
この関数を使用する場合、オプションの引数を2つ付けて、「引数様式」と「文字セット」を指定すると適切にエスケープできます。
引数様式は、ENT_QUOTES を指定してシングルクォートとダブルクォートも変換しましょう。文字セットは Content-Type に一致させましょう。
頻繁に出力する送信先の httpクライアント、データベース、URL などに対して、エスケープするための固有の関数がPHPで用意されています。
データベースエスケープ
- mysqli_real_escape_string()
データベースへデータを送信する際のエスケープ関数は mysqli_real_escape_string()です。
この関数は以下の文字について先頭にバックスラッシュを付加し、データベースで意味のある文字列を無効化します。
1 2 3 4 5 6 7 | \x00 \n \r \ ' " \x1a |
1 2 3 4 5 6 7 8 | <?php //エスケープ処理 $escapeString= mysqli_real_escape_string($string, $dbConnect); //クエリ文字列作成 $query = "SELECT id, name, age FROM users ORDER BY id where name = ".$escapeString; //データベースへ送信 mysqli_query($query, $dbconnect); ?> |
URLのエスケープ
- urlencode()
- htmlentities()
例
1 2 3 4 | <?php $value = 'トライピーエイチピー'; echo '<a href="https://wepicks.net/index.php?var='.$string.'">URL</a>'; ?> |
この例は $string に対して2種類のエスケープを考慮する必要があります。
$string は、URLのクエリ文字列であると同時にHTMLのデータでもあります。
下記のエスケープ処理が必要になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 | //変数初期化 $url = array(); $html = array(); $link = ''; //URLエスケープ URLエンコード処理 $url['value'] = urlencode($value); //リンク文字列作成 $link = "https://wepicks.net/index.php?var={$url['value']}"; //httpクライアントエスケープ $html['link'] = htmlentities($link, ENT_QUOTES, 'UTF-8'); //出力 echo '<a href="'.$html['link'].'">URL</a>'; |
エスケープされたデータとそうでないデータの区別
- エスケープされたデータとそうでないデータを区別する
エスケープされたデータを汚染リスクのない初期化した変数に代入してしっかりと区別しましょう。
初期化した変数へエスケープ後のデータを格納します。
1 2 3 4 5 6 7 | <?php //変数初期化 $html = array(); //エスケープ処理を行った後に汚染リスクのない初期化した変数へ代入し区別する $html['username'] = $_POST['username']; ?> |
タグ(=記事関連ワード)
日付
最終更新日:2017年08月09日