セキュリティ : PHP
PHPのセキュリティについてのメモ。
PHPのセキュリティ設定
PHPのセキュリティ対策は設定ファイルによる対策とPHPコードでの対策の2通りがある。
-
設定ファイルを使ったセキュリティ対策
php.iniまたはhtaccessで行なう。PHPの設定はphpinfo関数で設定を確認できる[1]。 - PHPコードでのセキュリティ対策(本記事の内容)。
PHPコードでのセキュリティ対策
Webプログラミングのセキュリティーの問題の多くは外部からのリクエスト(GETやPOST)をプログラム内部で処理する際にプログラム作成者の意図していない(悪意のある)リクエストを送信されることより発生する。プログラム作成者は常に$value = $_GET['key']や$value=$_POST['key']で取得する外部リクエストの値($value)に悪意のあるデータが含まれている可能性を考える必要がある。
取得した外部リクエストの値に有害なデータが含まれる可能性を考えてデータをエスケープしたりHTML実体参照に変更するなどの対策(無害化:サニタイズ)がWebプログラミングでのセキュリティーの中心となる。
セキュリティの簡単な例
----- HTML -----
<textarea name="msg"></textarea>
----- PHP -----
$msg = $_POST['msg'];
print($msg);
----- テキストエリアの入力 ---
<script type="text/javascript">alert("Hello World");</script>
上記の例ではテキストエリアにJavascriptを記述して送信できる。PHPは送信された外部リクエストをそのまま出力する。 その結果出力ページにアクセスした人に対してJavascriptが実行される。
PHPの簡単なセキュリティ対策の実例
HTMLフォームの入力データをPHPで処理してHTML出力する過程で施すべき基本的なセキュリティ対策をまとめる。
対策の流れ
- Javascriptが入力された場合は除去
- SQLインジェクション対策
- 出力時にHTMLタグは実体参照へ変換する
- 入力時の改行は、改行コード<br />へ変換して出力
HTMLフォームの入力は$inputに格納されているものとします。
Javascriptの除去
preg_replace('/javascript/i','',preg_replace('/[\x00-\x20\x22\x27]/','',$input));
SQLインジェクション対策
$input = addslashes($input); //DB処理
HTMLタグを実体参照へ
$output = htmlspecialchars($output)
改行を<br />へ
$output = nl2br($output)
セキュリティの前提知識
Webプログラミングのセキュリティーを考える上で必要になる知識を簡単にまとめている。
リクエスト変数
外部リクエスト変数(GET,POST,COOKIE)にはクライアント・サイド・スクリプトを埋めこむことができる。 同様に$_SERVER['PHP_SELF']等の一部のSERVER変数にもクライアント・サイド・スクリプトを埋めこむことができる。 よってセキュリティー対策をしないで外部リクエストをそのまま出力(表示)することはクライアント・サイド・スクリプトを実行する危険性がある。
クライアント・サイド・スクリプト
クライアント・サイド・スクリプトは通常JavaScript。対策もJavaScriptを念頭に置く。 JavaScriptはURLの転送やクッキーの送信などを行うことができるのでクライアントの情報を不正に外部へ送信する危険を生む。
サニタイズ
サニタイズはデータの無効化・無害化を意味する。代表的なサニタイズとしてHTMLサニタイズとSQLサニタイズがある。
HTMLサニタイズ
HTMLサニタイズとはHTMLで特別な意味をもつ<や>を通常の文字として扱われるHTML実体参照>や<に変換することである。
SQLサニタイズ
SQLサニタイズはSQL文で文字列の区切り文字として使われる’(シングルクウォート)や”(ダブルクウォート)を\でエスケープすることである[2]。 外部リクエストをSQL文として利用する場面で対策を行う。
Javascriptの記述位置
HTMLファイルにJavascriptを記述する方法は大きく2種類ある。
- (1)HTMLファイルのhead部やbody部に<script>Javascriptコード</script>と記述する。
- (2)HTMLファイルでURLが記述可能な場所にjavascript:擬似プロトコルを使って記述する。 <a href=”javascript : Javascriptコード”>リンク</a>
悪意のあるJavascriptへの基本的的な対策は出力の際に下記の対策を行う。
(1)にはhtmlspecialchars関数を使ってHTMLサニタイズを行う。
(2)にはpreg_replace関数を使ってHTMLサニタイズを行う。
preg_replace('/javascript/i','',preg_replace('/[x00-x20x22x27]/','',$url));
preg_replaceはPerl互換の正規表現置換関数であり、正規表現の16進数表記は\xで始まる。
\x00~\x20は正規表現の16進数表記で制御コード(\x00はヌルバイト)を表す。
\x22は”(ダブルクウォート),\x27は’(シングルクウォート) を表す。
ヌルバイト
\x00や\0をヌルバイトと呼ぶ。PHPはヌルバイトを文字列の終端とみなさないバイナリセーフな関数と、文字列の終端とみなすバイナリセーフでない関数が存在する。 ヌルバイト攻撃とはバイナリセーフな関数とバイナリーセーフでない関数がPHPで混在して存在することより発生する。
PHPのダブルクウォート文字列での16進数表記は\xではじまる。
ヌルバイト\x00や\0をURLエンコーディングすると%00になる。
ホワイトリスト法
ホワイトリスト法とは外部リクエスト変数チェックで、指定した値のみを許可する方法。ブラックリスト法よりも厳しいチェックになる。
$list = array("a","A");
$v = $_GET['alphabet'];
if(!in_array($v,$list)) {
exit;
}
a,Aのみ許可する。
ブラックリスト法
ブラックリスト法とは外部リクエスト変数チェックで、指定した値のみ禁止する方法。ホワイトリストよりも緩やかなチェックになる。
$list = array("a","A");
$v = $_GET['alphabet'];
if(in_array($v,$list)) {
exit;
}
a,Aのみ禁止する。
公開ディレクトリと非公開ディレクトリ
公開ディレクトリと非公開ディレクトリを明確に分ける必要がある。 インターネットに直接公開する必要のないファイルは非公開ディレクトリへ配置する。 詳しくはURL(Uniform Resource Locator) : HTTPを参照。
HTTPリクエスト,HTTPレスポンス
WebプログラミングではHTTPを理解しておくと良い。HTTPについての詳細はHTTPの基礎事項を参照。
eval関数
eval関数は引数に与えられた文字列をPHPコードとして実行する。外部リクエストを引数として利用するようなコードはユーザーにあらゆるPHPコードを実行される可能性がある。 できるかぎりeval関数は利用しないほうが良い。
セキュリティ関連の関数
必要になる関数の一覧をまとめています。
- htmlspechialchars関数
-
ENT_QUOTESが設定されている場合は、シングルクオートとダブルクオートが共に変換されます。ENT_NOQUOTESが設定されている場合は、シングルクオートとダブルクオートは共に変換されません。
変換対象となる文字は以下の通りです。
‘&’(アンパサンド)は’&’になります。
ENT_NOQUOTESが設定されていない場合、’"’(ダブルクォート)は’"”になります。
ENT_QUOTESが設定されている場合のみ、”’(シングルクオート)は’'’になります。
‘<’(小なり)は’<’になります。’>’(大なり)は’>’になります。 - strip_tags関数
- 第一引数で指定した文字列の中から、第二引数で指定したタグ以外のHTMLタグを取り除く。第二引数が省略された場合は全てのタグを取り除く。
- どのようなHTMLタグにもJavascriptが含まれる可能性があるためHTMLサニタイズはstrip_tags関数ではなくhtmlspechialchars関数を使う。
- addslashes関数
- ",’,\,ヌルバイト(\x00,\0)をエスケープする。
- eval関数
- 引数(文字列)をPHPコードとして実行する。
- preg_replace関数
- Perl互換正規表現置換関数
mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit] )
pattern : 正規表現パターン ex) ‘/\d{4}.\d{2}.\d{2}/’など
replacement : 置き換える文字列 \\nまたは$nによってマッチした文字列を参照できる
subject : 置換対象文字列
※正規表現に関しては本ブログのテーマ『正規表現』を参照
正規表現パターンのオプション
e : 置換後の文字列をプログラムコードとみなす。
s : ドット(.)を改行ともマッチさせる。
April1,2003
PHP公式マニュアル から引用
$string = "April 15, 2003";
$pattern = "/(\w+) (\d+), (\d+)/i";
$replacement = "\${1}1,\$3";
echo preg_replace($pattern, $replacement, $string);
出力結果
※\${1}1や\$3の\はダブルクウォート文字列内で変数展開を防ぐため$をエスケープしている。 - usort関数
- コールバック関数。第1引数で指定された配列を第2引数で指定した関数名で定義された関数によってソートする。
- call_user_func
- 第1引数で指定したユーザー関数を呼び出す。第2引数以降の引数は第1引数で指定された関数に渡される。
- passhru関数
- 引数で指定されたコマンドを実行する。
PHPのセキュリティー対策リンク集
総合
- PHPとWEBアプリケーションのセキュリティーについてのメモ
- E-3 Inc セキュリティガイドライン
- IPA ISEC セキュアWEBプログラミング
- @IT WEBアプリケーションに潜むセキュリティーホール
クロス・サイト・スクリプティング
- @IT:クロスサイトスクリプティング対策の基本
- クロスサイトスクリプティング
- 鶴丸@ぐろっさり -クロスサイトスクリプティング
クロス・サイト・リクエスト・フォージェリ
[1] php.ini・htaccessの主なセキュリティ項目。register_global, allow_url_fopen, session.use_trans_idなど
[2] DBの文字リテラルはシングルクォーテーション(‘)またはダブルクォーテーション(“)で囲む。多くのDBはどちらを用いても良い。慣用的にシングルクォーテーションを使う場合が多い。
関連記事
- 関連記事は見つかりませんでした。
検索ボックスからの検索もお試しください。
コメント
コメントはまだありません。
コメントの投稿
改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。
トラックバックURL
http://www.findxfine.com/programming/php/723.html/trackback