PHPのセキュリティ対策のまとめ
PHPなどのサーバーサイド・スクリプト言語でWebサイトを作成するに当たり、セキュリティ対策を実施する必要があります。セキュリティホール(脆弱性)の有名なもので「SQLインジェクション」や「クロスサイト・スクリプティング(XSS)」、「クロスサイト・リクエスト・フォージェリ(CSRF)」などが挙げられます。
この記事ではセキュリティホール、セキュリティ対策の「簡潔なまとめ」を目的としています。詳細はリンク先などを各自でご覧ください。
Webサイトに潜むセキュリティホール
・SQLインジェクション
・クロスサイト・スクリプティング(XSS)
・クロスサイト・リクエスト・フォージェリ(CSRF)
・OSコマンドインジェクション
・ディレクトリ・リスティング
・ディレクトリ・トラバーサル
・メールヘッダ・インジェクション
・HTTPヘッダ・インジェクション
などが挙げられます。次章から簡単に解説していきます。
SQLインジェクション
SQLインジェクションとはWebサイトの不備により、利用者がデータベースを操作できる状態になる事です。主にサーバーサイド側の処理で、GETやPOSTデータをそのままSQL文に埋め込む場合などに発生しやすいです。
PHP言語でSQLを発行する際にはバインド機能を使用すると安全にGET/POSTデータをSQLに埋め込む事が出来ます。次のコードはmysqliのバインド機能を使った例です。
/* mst_bookテーブルのtitleに既に同一名称があるか確認しています。*/ // TRUE 同一名称のデータがある FALSE 同一名称のデータがない function IsSameTitle($mysqli,$title){ $sql = "SELECT title FROM mst_book WHERE title= ?"; // プリペアステートメント if ($stmt = $mysqli->prepare($sql)) { // パラメータに変数をバインド // ※第一引数は型指定(s= string d= double i=integer b=blob) if ($stmt->bind_param("s",$title)){ // SQLの実行 if ($stmt->execute()){ // 結果フェチ if($stmt->bind_result($str)){ while ($row = $stmt->fetch()) {} $stmt->close(); if(isset($str)) return TRUE; else return FALSE; } } } } // エラーの場合はTRUEとする return TRUE; }
もちろん、標準のバインド機能を使用しなくて自前の関数で似たような機能を作成する事も可能です。その際は単一引用符、二重引用符、エスケープシーケンスなどを処理する必要があります。
※mysqliの使い方は「PDOより高速なmysqliの使い方」をご覧ください。
クロスサイト・スクリプティング
クロスサイト・スクリプティングは通称「XSS」と呼ばれていて、Webのフォーム入力などで任意のHTMLやJavascriptを挿入されてコードが実行される事です。クッキーを使用してセッションハイジャックや、入力情報が別のサイトへ送信されたり、サイト自体が改変されてフィッシングサイトになったりする場合があります。
基本的にPHP側ではGET/POSTデータに対してhtmlspecialchars()関数を使用してからHTMLに出力すれば安全です。
但し、この関数は標準では「&」「<」「>」「"」の特殊文字をHTMLエンティティに変換します。「'」にも対応するには次のような関数を作成して使用します。
function h($str) { return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); }
「'」は、HTMLの値を「'」で括っている場合やCSS、Javascriptなどで頻度は低いですが、「'」の対策もしておく方が良いでしょう。
クロスサイト・リクエスト・フォージェリ
クロスサイト・リクエスト・フォージェリは通称「CSRF」と呼ばれていて、「悪意のあるサイト」 (または改ざんされたサイト)に利用者がアクセスすると別サイトの掲示板に任意の投稿内容などが自動的に投稿されたりする事です。
仕組みとしては「悪意のあるサイト」のHTMLコード内に<img>や<iframe>タグを設置して掲示板に自動投稿できるようにしています。
<img src="http://example.com/reg.php?title=題名&body=本文">
※HTMLの仕様上、<img>や<iframe>タグは自動的に実行されます。
掲示板のサーバー側でこれを防ぐには投稿する前にセッションなどの「固有ID」を取得して、投稿の書き込み処理時にさきほどの「固有ID」と照会して一致すれば投稿できるようにすると良いです。もちろん、固有IDは桁数が多くランダムな文字列にする必要があります。
OSコマンドインジェクション
OSコマンドインジェクションのインジェクションは「注入」という意味でSQLインジェクションと同様です。OSですのでシェルやコマンドプロンプトの悪用によって任意のOSコマンドが実行されるという事になります。
ディレクトリ・リスティング
ディレクトリ・リスティングはWebのディレクトリにアクセスした際にディレクトリのファイル一覧が表示される事です。特に重要ファイルなどがある時などに注意が必要です。
ディレクトリのファイルの一覧は表示する必要がありませんのでWebサーバー側の設定で非表示にしましょう。
ディレクトリ・トラバーサル
ディレクトリ・トラバーサルとは本来、非公開なファイルに一般の利用者がアクセスできてしまう事です。
メールヘッダ・インジェクション
SQLインジェクションと同様でメールヘッダ、メール本文に任意の文字列を追加されてしまう事です。
HTTPヘッダ・インジェクション
SQLインジェクションと同様でHTTPヘッダに任意のコードを追加されてしまう事です。
参考文献
安全なウェブサイトの作り方 [IPA]
知っていますか?脆弱性 (ぜいじゃくせい) [IPA]