第6回 案外に 景色ひとつで 違うもの - セキュリティ講座
がる先生のセキュリティ講座
Lecutures on PHP
第6回 案外に 景色ひとつで 違うもの (その1)
見た目じゃない…とはいうものの
プログラムソースは基本的に「コンピュータが解析して認識して実行するもの」です…という前提にたつと、コメントとかそういった蛇足な部分というのはどうでもよい…はず、なのですが。
実際問題としてセキュリティホールのいくつかは「人間のミス」によって誘発される部分があります。
もちろんそういった部分を「根性論でヘッジする」ように考える方々もいらっしゃるのですが、誰しも「ミスをしたくてミスをする」わけではない…はずです、たいていの場合。
そうして、本人の意識ではどうにもならない以上、根性論では片付かないのは自明の理です。 ではどうしたらよいのでしょうか?
今回はそんな「保守性に優れたコード」を少し考えてみます。
捜し物はどこですか?
特に業務でコードを書いているときにありがちなのですが。どうしても、仕様変更、要望追加、その他の要因で、プログラムが修正、追加されることは少なくありません。また、大抵そのときにセットでついてくるのが「非常にタイトな時間的制約」です。
この「仕様変更」に「タイトな時間制約」が重なると、どうしてもつい「手抜き」をしがちです。 抜いていい部分ならよいのですが、多くの場合、ここで「抜いてはいけない部分」をチョイスしてしまいがちで、その結果、プログラム全体が「誰にもわからない」見通しの悪い状態になります。
そうしてその「見通しの悪い状態」の隙間に、セキュリティリスクが潜むことが間々あるのです。 そんな状況を、筆者の実体験込みでいくつかお送りしていきましょう。
globalという変数のスコープがあります。
一カ所で宣言しておけばあとはどこでも使うことが出来て大変い使い勝手がよい…のですが。この「使い勝手の良さ」に、たくさんの落とし穴があります。
一つよくあるのが「比較するつもりで代入してしまう」ケースです。
たとえば。多くの方がやる「DBハンドルをglobaに持たせる」ケースを考えてみましょう。 で、丁寧に、一応チェックを入れてからDBハンドルを使ってみます。
function hoge() {
global $dbh;
if ($dbh = null) {
// 処理を中断:エラー終了
} else {
// 何らかの処理を行う
}
// 以降処理
}
ところが「なぜか」このロジックは常に異常終了してしまうことが、テストで判明します。理由、わかりますか?
そう。比較演算子のつもりが代入になってしまってますね。
このケースは「正常系が通らない」ために、テストによってとりあえず捕捉しやすい状況になってます。
しかし、逆の「常に正常終了してしまう」ロジックの場合、正常系のテストでは判明しないために、非常に厄介なバグを生むことがあります。
function hoge() {
global $flg;
if ($flg = true) {
// 正常系の処理を行う
}
//
return ;
}
たいていの場合、この場所では問題が起きません。起きるのは「同じフラグを使ってより致命的な処理をしている別の箇所」だったりします。
そうしてその場合「どこにバグがあるのか」を探るのが困難だったりします。問題が発生している場所と問題を引き起こしている場所が離れてしまっているので。
また、万が一これが「認証系のチェック」などの場合。「本当は認証がNGな人なのに」「認証がOKであるとして処理が流れてしまう」ために、テストが十二分に行われていないと、容易にセキュリティリスクを生み出します。そうしてこんな時に、問題のある箇所を探し出すのは容易なことではありません。
特に「あちこちで参照されているglobalな変数」の場合grepしても大量にListが出てきてしまうので、それを一つずつチェックしていくと予想外に工数がかかってしまうものです。
globalの最大の問題点は「値が容易に変更出来てしまう」上に「値が変更されたことをフックする手段がない」事です。
高性能なデバッガなどを用いるなどの手法もあるのですが、それよりは「globalを使わない設計」をしたほうがより安全なのではないでしょうか?
筆者はもうちょっと別の手段をとることも多いのですが、とりあえず場当たり的には、「値を常にアクセッサ経由でやりとりする」ことを前提に「シングルトンパターン」でglobalな値を保持するインスタンスを一つ持っておく、という手もあります。
最低限、アクセッサ(より厳密にはセッター)にデバッグプリントなどを仕込めば、値が変更された瞬間がフックできますので。
余談:シングルトンパターンって? 俗に「GoFのデザインパターン」と呼称されているもののうちの一つで「常に1インスタンスしか生成しないという特徴を持ったクラス」というパターンになります。 globalな値を記述するためにある訳ではないのですが、結果的に、globalな値を記述するには非常に便利なパターンになっています。
- 1
- 2





ページのトップへ


今回のような実践的な経験がエンジニアのキャリアに繋がると思います。是非サービスを成功させて下さい!