PHPのセキュリティメモ。
PHPのセキュリティ対策は各種設定ファイルによる対策とPHPコードによる対策のがある。
Webプログラミングのセキュリティーの問題の多くは外部からのプログラム作成者の意図していない(悪意のある)リクエストから発生する。
プログラム作成者は常に下記のような外部リクエストの値($value)に悪意のあるデータが含まれている可能性を考える必要がある。
$value = $_GET['key']; $value = $_POST['key'];
外部リクエストの値には有害なデータが含まれる可能性を考えてデータを出力するときにHTMLエンティティへエスケープする。
----- HTML ----- <textarea name="msg"></textarea> ----- PHP ----- $msg = $_POST['msg']; print($msg); ----- テキストエリアの入力 --- <script type="text/javascript">window.loacation.href="http://www.example.com";</script>
上記はテキストエリアにJavascriptを記述して送信しPHPは外部リクエストをそのまま出力する。
その結果、出力ページにアクセスしたユーザーはwww.example.comへリダイレクトされる。
入力データをPHPで処理してHTML出力する過程で施すべき基本的なセキュリティ対策をまとめる。
Webプログラミングのセキュリティーで必要になる知識を簡単にまとめている。
外部リクエスト変数(GET,POST,COOKIE)にはクライアント・サイド・スクリプトを埋めこむことができる。
同様に$_SERVER[‘PHP_SELF’]等の一部のSERVER変数にもクライアント・サイド・スクリプトを埋めこむことができる。
セキュリティー対策をしないで外部リクエストをそのまま出力(表示)することはScript Insertionの危険性がある。
クライアント・サイド・スクリプトというときJavaScriptを指す。対策もJavaScriptを念頭に置く。
JavaScriptはURLの転送やクッキーの送信を行うことがでクライアント情報を不正に外部へ送信する危険がある。
サニタイズはデータの無効化・無害化を意味する。代表的なサニタイズとしてHTMLサニタイズとSQLサニタイズがある。
HTMLサニタイズとはHTMLで特別な意味をもつ<>&”‘をHTMLエンティティHTML><&などにに変換することである。
SQLサニタイズはSQL文で文字列の区切り文字として使われる'(シングルクウォート)や”(ダブルクウォート)をでエスケープすることである[2]。
外部リクエストをSQL文として利用する場面で対策を行う。[追記 2012.11.01 現在はプリペアードステートメントを使う。
HTMLファイルにJavascriptを記述する方法は大きく2種類ある。
悪意のあるJavascriptへの基本的的な対策は出力の際に適切にエスケープを行う。
preg_replace('/javascript/i','',preg_replace('/[x00-x20x22x27]/','',$url));
preg_replaceはPerl互換の正規表現置換関数であり、正規表現の16進数表記はxで始まる。
x00~x20は正規表現の16進数表記で制御コード(x00はヌルバイト)を表す。
x22は”(ダブルクウォート),x27は'(シングルクウォート) を表す。
x00や をヌルバイトと呼ぶ。PHPはヌルバイトを文字列の終端とみなさないバイナリセーフな関数と、文字列の終端とみなすバイナリセーフでない関数が存在する。
ヌルバイト攻撃とはバイナリセーフな関数とバイナリーセーフでない関数がPHPで混在して存在することより発生する。
PHPのダブルクウォート文字列での16進数表記はxではじまる。
ヌルバイトx00や を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を参照。
WebプログラミングではHTTPを理解しておくと良い。HTTPについての詳細はHTTPの基礎事項を参照。
eval関数は引数に与えられた文字列をPHPコードとして実行する。外部リクエストを引数として利用するようなコードはユーザーにあらゆるPHPコードを実行される可能性がある。
できるかぎりeval関数は利用しないほうが良い。
必要になる関数の一覧をまとめています。
ENT_QUOTESが設定されている場合は、シングルクオートとダブルクオートが共に変換されます。ENT_NOQUOTESが設定されている場合は、シングルクオートとダブルクオートは共に変換されません。
変換対象となる文字は以下の通りです。
‘&'(アンパサンド)は’&’になります。
ENT_NOQUOTESが設定されていない場合、’"'(ダブルクォート)は’"”になります。
ENT_QUOTESが設定されている場合のみ、”'(シングルクオート)は’'’になります。
‘<‘(小なり)は’<’になります。’>'(大なり)は’>’になります。
pattern : 正規表現パターン ex) ‘/d{4}.d{2}.d{2}/’など
replacement : 置き換える文字列 \nまたは$nによってマッチした文字列を参照できる
subject : 置換対象文字列
※正規表現に関しては本ブログのテーマ『正規表現』を参照
正規表現パターンのオプション
e : 置換後の文字列をプログラムコードとみなす。
s : ドット(.)を改行ともマッチさせる。
PHP公式マニュアル
から引用
$string = "April 15, 2003";
$pattern = "/(w+) (d+), (d+)/i";
$replacement = "${1}1,$3";
echo preg_replace($pattern, $replacement, $string);
出力結果 April1,2003
※${1}1や$3のはダブルクウォート文字列内で変数展開を防ぐため$をエスケープしている。
[1] php.ini・htaccessの主なセキュリティ項目。register_global, allow_url_fopen, session.use_trans_idなど
[2] DBの文字リテラルはシングルクォーテーション(‘)またはダブルクォーテーション(“)で囲む。多くのDBはどちらを用いても良い。慣用的にシングルクォーテーションを使う場合が多い。
No comments yet.
改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。