更新:2016/12/30前回は一般的なアタック手法についてご説明しましたので、当記事では実際のプログラムに対策を適用していきます。実務でもセキュリティに配慮したプログラミングは重要ですので、これを期にぜひマスターしましょう。送信された値の中から、プログラムで使用する変数を明示することで、意図しない変数が紛れ込まないようにする手法です。対策をしない場合のリスク以下は、今までのメール送信プログラムから、『お名前』の項目を削除しようとした例です。HTMLからは削除したのですが、前半のロジックの部分から『お名前』を消すのを忘れてしまったとしましょう。–>というのは、HTMLを部分的にコメントアウトする記法です。"footer.php";?>上記では、プログラム部分の『お名前』のロジックが残っています。}このため、『偽装した通信内容を送り込まれると、お名前(uname)を検出して、プログラムの挙動に反映されてしまう』という問題が起こります。本質的には、個人情報漏洩や致命的なリスクにつながる脆弱性となり得ます。対策実施ホワイトリストを定義し、プログラムで利用する変数を明確化します。プログラム前半を以下のように修正することで、$requestという配列に、許可された変数だけを格納するようになります。"送信しました!";}?>※foreachという構文については、後ほど解説します。『配列の中身を取り出しながら繰り返すもの』として理解しておいてください。サニタイズ(サニタイジング)インターネットから送信されてくる値の中には、攻撃者がアタックコードを混入させた値が含まれる場合があります。攻撃手法としては、前記事の[中級]Webアプリケーションの脆弱性と対策でも触れていますが、『クロスサイトスクリプティング』『セッションハイジャック』『クロスサイトリクエストフォージェリ』が該当します。サニタイズを行うと、変数を無害化することで、不具合やセキュリティリスクを防ぐことができます。今回は、HTML上に変数を表示する際の対策についてご紹介します。対策をしない場合のリスク以下は、今までのメール送信プログラムに機能追加をし、メール送信後に『○○さん、送信ありがとうございました!』と表示するように修正したケースです。</p>で画面表示を行っているわけですが、これには大きな問題があります。それでは、クロスサイトスクリプティングのリスクを体験するための実験を行いますので、ローカル開発環境で以下をお試しください。クロスサイトスクリプティングの実験inquiry.phpを前述のものにして、お名前欄に、『<script>alert(“脆弱性!”);</script>』と入力して送信してみてください。すると、次のようなポップアップが表示されるはずです。任意のJavascriptコードを実行してしまいました!!これは、クロスサイトスクリプティングの標的になりうる状況です。実際の攻撃では、外部の掲示板やSNSや攻撃用サイトから、アタックコードを埋め込んだURLを設置されることになります。このアタック用URLを踏んだユーザーは、セッションの奪取や強制アクセスなどの被害を受けることになります。今回は、文字列を出力する際にサニタイズを行う方法で、対策したいと思います。具体的には、htmlentitiesという関数を利用します。</p>上記のようにすることで、文字列はHTMLエンティティに変換され、安全に画面出力を行えるようになります。第三引数の『UTF-8』は、文字コードがUTF-8であることを意味しています。※前者のENT_QUOTESは定数ですので、ダブルクォートやシングルクォートで囲む必要はありません。htmlentitiesについての詳細は、以下をご覧ください。htmlentitiesHTMLエンティティについてHTMLエンティティとは、『<、>、&、”』などのHTML上で意味のある文字を、安全な形式に置き換えた文字列になります。上記はそれぞれ、『&lt;、&gt;、&amp;、&#34;』と置き換えられることになります。HTMLソースコード上のHTMLエンティティは、実際の画面表示としては、『<、>、&、”』として表示されます。バリデート(バリデーション)Webアプリケーションに設置されたフォームにおいては、様々な情報の入力を受け付けます。ユーザーが入力してくる値は、アプリケーションで想定しているものとは限りません。そこで変数のバリデートを行うことで、入力された値が想定している形式であるかをチェックすることができます。対策をしない場合のリスクメールの送信者に対して、受信した旨のメールを返信するものとしましょう。$add_header);上記のように、管理者向けのメールを送信したあとに、ユーザーにもメールを送信するものとします。この場合のリスクとしては、『メールアドレス形式として誤った文字列を受け付けてしまう』『メールシステムへアタックコードが渡されてしまう』といったものがあります。チェックと正規表現を利用して、メールアドレスの正当性を確認します。入力必須チェックメールアドレスの項目を必須入力扱いにしたいと思います。そのため、以下のように修正します。red;}上記のように編集すると、フォームを送信する際に必須入力チェックが動作します。それでは、それぞれの行について説明します。}}上記では、送信実行モードの際に、emailが空白であるかをチェックしています。空白だった場合に、エラーメッセージ変数$page_errorをセットしています。{上記では、従来の送信モードチェックに加え、『$page_errorが空白であること』という条件を追加しています。『&&』は、左右の条件を両方満たすことが求められますので、エラーが発生している場合は、送信モードをスキップする動作となります。</p>上記では、エラーメッセージをサニタイズした上で表示しています。システムでセットされる変数についても、ちょっとしたミスでセキュリティホールになりえます。変数を画面表示する際は、必ずサニタイズをすることが推奨されます。class="attention">[必須]</span><br>上記では、メールアドレス項目に必須である旨を表示しています。red;}警告表示などを赤字にするため、スタイルを追加しています。正規表現での形式チェック必須入力チェックに加え、メールアドレスの形式チェック行うため、正規表現を行います。正規表現とは、『文字形式のルールを定義することで、ある文字列がルールに則っているものか』をチェックするためのものです。以下のようなケースに利用できます。電話番号のチェック(数字とハイフンのみ)メールアドレスのチェック(一般的なメールアドレス利用文字のみ)ログインIDのチェック(英数字のみ)パスワード堅牢性チェック(一定文字以上+英数字含む)正規表現でのチェックには、preg_matchという関数を利用します。それではさっそく、以下のようにコードを修正します。}}上記では、必須入力チェックが終了したあと、続けてpreg_matchによりメールアドレス形式のチェックを行っています。preg_matchの詳細については、以下をご確認ください。preg_match正規表現の詳細については、以下をご確認ください。正規表現ここで注意ですが、今回例としたメールアドレスについては、非常に様々な形式があるため、上記は完全な正規表現とは言えません。必要に応じて、正規表現の条件をカスタマイズしてご利用ください。(とはいえ上記でも、実用上不便はない範囲で、入力ミスをチェックするような役には立ちます)エラー時の初期表示をセットセキュリティ対策とは少々離れますが、現在はフォーム入力にエラーが発生すると、毎回すべての項目を入力しなおす必要があります。そこで、エラーで戻ってきた際は、前回の入力内容が維持されるようにします。"footer.php";?>上記のように編集すると、フォームを送信する際エラーとなった場合、初期値が入力項目にセットされるようになります。それでは修正箇所を個別に説明していきます。"UTF-8");}上記では、heというユーザー関数を定義しています。htmlentitiesは引数の指定も含めると煩雑になるため、he関数の追加でコーディングが簡単になりました。?></textarea>inputタグのvalue属性により、入力項目の初期値をセットしています。textareaタグについては、閉じタグの前に初期値を挟み込む形でセットしています。ヌルバイト除去PHP、およびPHP自体の開発に使われているC言語では、ヌルバイト(\0)を文字列の終端として扱う場合があります。そのためヌルバイトが変数に混入すると、予期せぬ動作を引き起こします。対策をしない場合のリスクヌルバイトの除去を行わないと、『文字列処理時の予期せぬ動作』『ミドルウェアの予期せぬ動作』などが発生し、セキュリティリスクになります。以下のようにコードを修正します。}}この対策により、プログラムで利用する変数からヌルバイトを除去できるようになりました。まとめ当記事では、メールフォームのセキュリティ対策を中心に説明しました。現状の最新のソースコードを添付しておきますので、動作確認などをしてみてください。無料でPHPを学んでWebエンジニアになる。