Home > CakePHP | PHP > PHP unserialize()が__destruct()を実行する?

PHP unserialize()が__destruct()を実行する?

この記事の所要時間: 328

CakePHPのセキュリティホール(まだの方はご対応を!)から、unserialize()が話題になっています。

このセキュリティホールは、外部から送信された値をチェックせずにunserialize()したことが引き金になっており、安全でない値をunserialize()することの危険性が指摘されています。

下記エントリでは、コードを交えてunserialize()から__destruct()が実行される過程が解説されています。

PHP5 __destruct() and unserialize() function – TokuLog 改メ tokuhirom’s blog

念のための補足なのですが、unserialize()から__destruct()が呼ばれるわけではありません。

下記コードは、PHP5.3.3で実行しています。

unserialize()から実行される関数

unserialize()から実行される関数(メソッド)は以下です。

__autoload、spl_autoload*などのオートローダー

デシリアライズするインスタンスのクラス定義を探す時に実行される可能性があります。

unserialize_callback_funcで設定した関数

上記オートローダー実行してもデシリアライズするインスタンスのクラス定義が存在しない場合に実行されます。ini_set()等で設定していなければ実行されません。

__wakeup

デシリアライズしたインスタンスに__wakeupメソッドが定義されていれば実行されます。

unserialize()から間接的に実行される関数

デシリアライズしたインスタンスの操作によって、結果実行される可能性があるのは以下です。

__destruct()

デシリアライズしたインスタンスの参照が0になったタイミングで実行されます。通常必ず実行されます。

__toString() / __set() / __get() / __call() / __invoke()などのマジックメソッド

デシリアライズしたインスタンスへの操作によって実行される可能性があります。

この中で実行されそうなのは__toString()です。unserialize()した値が文字列だと想定して以下のようなコードを書いていると__toString()が実行されます。

func start
Foo::__toString
func end

unserialize()で__destruct()が実行される?

上記でも触れたように__destruct()は、unserialize()で呼ばれるわけではなく、デシリアライズしたインスタンスの参照が0になるタイミングで実行されます。

これは通常のクラスインスタンスと同じ挙動です。

下記コードを実行してみるとその挙動が確認できます。

実行結果

% php unserialize.php
func start
func end
Foo::__destruct <--- "func end"の後

ただ以下のようにunserialize()の戻り値を変数に格納しない場合は、デシリアライズしたインスタンスへの参照がありませんので、即時に__destruct()が実行されます。

func start
Foo::__destruct   // unserialize()して、即__destruct()が呼ばれる
func end

[おまけ] protected/privateな変数もデシリアライズ可能

ちなみにunserialize()では、protected/privateなインスタンス変数もデシリアライズ可能です。インスタンス変数をprotected/privateにしたところで、unserialize()で汚染される可能性があることには変わりありません。

object(Foo)#2 (3) {
  ["var1"]=>
  string(6) "public"
  ["var2":protected]=>
  string(9) "protected"
  ["var3":"Foo":private]=>
  string(7) "private"
}

でも結果としては実行される

unserialize()が__destruct()を直接実行するわけではないですが、デシリアライズしたインスタンスはどこかで破棄されるので、結果として__destruct()が実行されることには変わりありません。

ただやみくもに「unserialize()が__destruct()を実行する」と考えると問題を見誤る可能性があるのでご注意を。

参考リンク

Pocket

follow us in feedly

トラックバック:0

このエントリーのトラックバックURL
http://www.1x1.jp/blog/2010/11/php_unserialize_do_not_call_destruct.html/trackback
Listed below are links to weblogs that reference
PHP unserialize()が__destruct()を実行する? from Shin x blog

Home > CakePHP | PHP > PHP unserialize()が__destruct()を実行する?

検索
フィード
メタ情報

Return to page top