Using COM applyFilter
提供: GeeklogJpWiki
COM_applyFilterを使用する
目次 |
概要
Geeklog 1.3.9では新たにCOM_applyFilter関数が導入され,HTTPのGETリクエスト・POSTリクエストで渡されるパラメータのフィルタリングに使用されています。プラグインやアドオンではこの関数を使用することを強くお勧めします。この記事では,COM_applyFilterの使い方とより安全なスクリプトの書き方について説明します。
パラメータをフィルタリングする理由
HTTPのGETリクエストでパラメータが渡されるときはいつでも(ふつうはscript.php?parameter=valueのようにURLの一部として)また,POSTリクエストで(ふつうは<input name="parameter" value="value">のようなフォームの入力から)渡されるときはいつでも,これらのパラメータが操作される危険性があります。GETリクエストに関しては,URLを編集することで容易に改竄でき,POSTリクエストに関してもフォームを操作したり,netcatのようなツールを用いることで改竄は可能です。
したがって,これらのパラメータを信用しすぎないことが重要です。
COM_applyFilter
COM_applyFilter関数は,よく使われる(SQLとJavaScriptの)インジェクション攻撃からパラメータを守るために設計されました。パラメータから悪意のあるコードを取り除くには,次のようにCOM_applyFilterを使用してください。
$myvalue = COM_applyFilter ($_POST['myparameter']);
数値パラメータの場合には次のようにしてください。
$myvalue = COM_applyFilter ($_POST['myparameter'], true);
あなたが書くスクリプトは,COM_applyFilterを呼んだ後で,$myparameterが空(や,数値パラメータの場合には0)になる場合にも対応すべきです。ふつう,こうなるのは,パラメータからコードが取り除かされた場合です(パラメータがもともと空や0でなければですが)。このような場合に,スクリプトが終了するか,空や0のパラメータの代わりにデフォルト値を使って続行するかはあなたに任せられています。状況によりけりですが,どちらの対応でも意味はあるでしょう。
register_globalsについて
上記の例からもわかるように,register_globalsがオンになっていることをあてにするのではなく(Geeklog本体はバージョン1.4.0からオンでなくても動作します),代わりにグローバルな$_GET配列と$_POST配列を使用することをお勧めします。
注意: $_GET, $_POST, $_REQUEST配列が利用できるのはPHP 4.1.0からですが,このバージョンがGeeklogが動作する最低バージョンになってから,かなりの時間が経っています。
$_GET, $_POST, $_REQUESTを使用するもご覧ください。
悪い例
できることなら,$_GET配列や $_POST配列にパラメータがセットされているかどうかを調べるのにGeeklog本体内のコーディング例に従わないことをお勧めします。代わりに,スクリプトが適切に実行された場合にはいつでもどこにパラメータがセットされているかがわかるようにコードを書いてください。スクリプトのある部分で,GETリクエスト経由で呼ばれるのだからパラメータが$_GET配列にしか入らないとわかっているのなら,わざわざ$_POST配列をチェックする必要はありません(単に無視すれば済みます)。Geeklogのコアのコードには,GETリクエストで来るかPOSTリクエストで来るかがはっきりしないので両方の配列を検査しなければならないといった悪い例が含まれています。状況によりますが,このために攻撃者が侵入しやすくなり,一般的にコードのメンテナンスが遙かに難しくなります。その過ちを繰り返さないでください。
COM_applyFilterを使わない方がよいとき
この関数はクォーテーションマーク等の多くの特殊文字を取り除いてしまい,判読不能ないし無用なものにしてしまうので,記事の本文やユーザの本名のように「自由な形式」のデータにはCOM_applyFilterは使えないことにご注意ください。代わりに次のようにするとよいでしょう。
$mytext = COM_stripslashes ($_POST['mytext']); // ここで何らかの処理をする $mytext = addslashes ($mytext); DB_save ($_TABLES['mytable'], "mytext", '$mytext');
COM_stripslashes関数は,PHPのオプションでmagic_quotes_gpcがオンの場合に,POST操作の間に付加される可能性があるスラッシュを取り除きます(オフの場合には付加されません)。こうすることでユーザが入力した文字列をそのまま得られます。この後でプラグインやアドオンで必要に応じて文字列を処理することができます。
データベースに保存する前の準備
文字列をデータベースに保存する前に,特殊文字が必ずエスケープされるようaddslashesを呼び出す必要があります。こうすることで保存される文字列にスラッシュが付加されるわけではなく,確実に保存されるようになるだけです(SQLインジェクションが試みられている場合は,保存動作の一環として実行されることなく,文字列として保存されます)。
実際には,COM_applyFilterを適用していても,念のためにデータベースに保存される全てのデータにaddslashesを適用するのは良い考えでしょう。
現在のユーザを確実に識別する方法
傍注として,現在のユーザを識別する必要がある場合は,GETリクエストやPOSTリクエストで渡されたユーザIDを決して信頼してはいけません(たとえば,ユーザIDをフォームに埋め込んでおき,フォームが送信されたときにその値を取り出すなどの方法)。その代わりに,常にグローバル変数である $_USER['uid'] を使用してください。この変数は値が空や1の場合もありますが,これはゲストユーザ,つまり,ログインしていないユーザを意味します。次のようにして使用してください。
if (!empty ($_USER['uid']) && ($_USER['uid'] > 1)) {
// ログインユーザ
} else {
// ゲストユーザ
}
要約
- HTTPのGETリクエスト・POSTリクエスト経由で来るパラメータには必ずCOM_applyFilterを適用する。
- パラメータが数値型の場合には,COM_applyFilterの引数に"true"を追加する。
- (COM_applyFilterを適用した後で)パラメータが空や0になる場合に備える。
- register_globalsを当てにせず,代わりに$_POSTと$_GETを使う。
- パラメータが$_POSTと$_GETのどちらからくるかわかるようにスクリプトを書く。
- 「自由形式」のデータに対してはCOM_applyFilterを使わず,他の方法で注意深くフィルタリングを行い,データベースに保存する前にaddslashesを適用する。
- ユーザを識別するには,常に$_USER['uid']を使用する。