Home > PHP

送信データのサニタイジング

 PHPでフォームからデータを送信する場合に注意しなくてはならないことは、そのデータがどこまで信用できるものであるのかということですが、不特定多数の方々がフォームから様々なデータを送信する場合にはそのデータ特有のサニタイジング(浄化)は正規表現などでも十分に可能です。例えばE-mailアドレスを送信してもらう場合はそれなりの正規表現でもってそのE-mailアドレスが信用性に妥当するかどうかを判定できます。また送信者が全角数字を使用したり半角数字を使用したりとばらつきがある場合(例によって、クライアントユーザーは全角数字と半角数字の区別は殆どしていないようです。)それらの数字をすべて半角数字に変換して揃えておく方がデータベースの処理としてはうまく機能します。逆にばらつきがある場合は処理に時間がかかったり、最悪の場合には機能しません。
 それぞれの入力データがどのようなものであれ、個々にそれらの値の信用性を判定しエラーメッセージなどで正しい情報を入力してもらうように極力努力しなければならないのですが、送信データのサニタイジングにおいて最も重要なのはクロスサイト・スクリプティングなどの悪意のあるコードを埋め込まれないようにすることです。送信データの内容によってはMySQLなどのデータベースを直接細工可能にするコードを埋め込まれる可能性がありますし、Javascriptなどを安易に読み込んでしまう可能性があるからです。
 これらを回避するためには、それなりの工夫が必要なのですが、いくつかの点に注意すれば十分対応が可能です。(あまりにも新種な手段にはさすがに対向できませんが、そのようなコードが発見され流行するのは多くとも年に数回です。)注意する項目は以下の通りになります。
  • メタ文字の排除(][}}{)(!"#$%&\\~|*+,/\^\'<>`;:\\=)
  • 改行文字と無駄なスペースの排除
の2点になります。これらを実行すれば大抵のことは大丈夫です。メタ文字については特に:(コロン)と;(セミコロン)に注意してください。数あるスクリプトの中でも;で改行や一つのコマンドの区切りをする言語はたくさんあります。これらを安易に入力可能にしておくと複数のコマンドを埋め込まれる可能性があります。また\(バックスラッシュ)や?(円)なども特殊な意味をもつ重要なメタ文字なので必ず削除しておきます。これらのメタ文字はお名前、住所、連絡先といった内容には全く関係のない文字なので排除することに何の躊躇もない筈です。
 改行文字はデータベースに入れる際に全く不必要な文字なので削除しておくのと、これも複数のコードを埋め込むのに便利なメタ文字だからです。ベースのサニタイジングとしてはこれを最低限おこなっておくのがよいです。

 またサニタイジングと同時にフォームデータの文字化けやフォーマットの不揃いから文字化けが起こったりデータのフォーマットにばらつきが出るのも嫌なものなので、それらも同時にある程度フォーマットしておくのがよいです。基本的には、
  • 文字コードの変換(指定の文字コードに変換しておく)
  • フィールドに入力されたデータの無駄なスペースを削除(特に前後のスペースは削除する)
  • 半角カタカナはトラブルの元になるので全角カタカナに変換しておく
  • 英文字、数字、ハイフン、アンダーハイフンは半角英数字に統一しておく
という風にするのが最良です。
 
 しかし勿論それだけのサニタイジングとフォーマットのみでフォームからの入力データがすべて信用に値するとは限りません。それそれのデータを検証するシステムが更に必要なのでご注意。
 これらの最低限のサニタイジングを実行するような関数は以下のような感じになります。

<?

function base_sanitize ($data) {
#=======================
# 基本的なサニタイジング
#=======================
    /*
    base_sanitize ver 2.0
    Copy Right (c)2008-2010 omnioolab All Right Reserve.
   
    ・フォームから値を受け取る際のスクリプト冒頭で使うと便利です。
    ・単独のinputフォームのテキストなどを対象としているので、textareaなどの改行を含むような場合には適していません。
    ・改行記号が削除されます。
    ・引数は配列で受け付けます。(たいていはPOSTとかGETとかCOOKIE)
    ・返り値も同様に配列です。返り値はサニタイジングされた値が返ります。
    ・入力文字の文字コードを設定して統一します。
   
    【機能】
    1. 文字コードの設定(デフォルトではUTF-8)
    2. HTMLタグを排除
    3. 不要な半角記号の排除 ][}}{)(!"#$%&\\~|*+,/^'<>`;:?\=を削除します。(現在\だけ削除できない。)
    4. 改行記号\t\f\n\r\vの削除
    5. 文字列前後の不要なスペースを排除
    6. 全角スペースは半角スペースに置換
    7. 半角カタカナは全角カタカナに置換
   
    【使用例】
    $return_value = base_sanitize ($_POST);
    foreach ($return_value as $k => $v) {
        print $k.' => '.$v.'<br />';
    }
    */
   
    #---------
    # 設定項目
    #---------
    $charset = 'UTF-8';            #-文字コード指定(HTMLヘッダに合わせてください。)UTF-8 EUC-JP SJISなど指定
    $original_charset = '';        #-送信元の文字コードを指定。(わからない場合は空に!)UTF-8 EUC-JP SJISなど指定
   
    #-----------------
    # Function本体開始
    #-----------------
    foreach ($data as $key => $value) {
       
        #------------------------
        # デバック用のコードの準備
        #------------------------
        # $pre_value = $value;#-サニタイジング前の値をキープ
       
        #-----------------
        # 文字コードの変換
        #-----------------
        $code = mb_internal_encoding($charset);//$codeはブール値(この場合はたいてい1)
        if ($original_charset == '') {
            $original_charset = 'auto';
        }
        # mb_convert_encoding("文字列","変換文字コード","元の文字コード")
        $value = mb_convert_encoding($value , $charset , $original_charset);
       
        #-----------
        #-タグを排除
        #-----------
        $value = strip_tags($value);
       
        #----------------
        # 不要な記号を削除
        #----------------
        $value = ereg_replace ('[][}}{)(!"#$%&~|*+,\^\'<>`;=\\\\]', '', $value);
        $value = preg_replace ('/[\t\f\n\r\v]/', '', $value);
       
        #-------------------------------
        # 文字列の前後のスペースを削除など
        #-------------------------------
        # (a)全角英数字を半角英数字に変換
        # (s)全角スペースを半角スペースに変換
        # (K)半角カタカナを全角カタカナに変換
        $value = mb_convert_kana($value,"asK",$charset);
        $value = trim($value);
       
        #----------------------------
        # 変換置換した値を配列に再格納
        #----------------------------
        $data[$key] = $value;
       
        #-------------------
        # デバック用のコード
        #-------------------
        //print $key.'=>'.$value.'<br />';                                        //サニタイジング後の文字列
        //print '['.$key.'] '.$pre_value.' <=> '.'['.$key.'] '.$value.'<br />';    //サニタイジング前とサニタイジング後の比較
    }
    return $data;
}
?>








プロフィール



  • Name :: 山上オサム ♂(37)
  • Hobby :: 武術
  • Work :: Web Designer