2016-11-03 4 views
0

私は自分のプロジェクトでユーザー提供のデータでunserializeを使用する必要があります。 IFAIKでは、信頼できないデータを使用してunserializeを使用すると、暗黙的にwakeup-functionおよびdestructor(https://wiki.php.net/rfc/secure_unserialize)を呼び出してユーザーコードを実行する可能性があるため、安全ではありません。基本的な型と配列を非シリアル化するにはどうすればよいですか?

OK

、私はこの

$a = serialize(array('a'=>'b', 'c'=>20)); 
unserialize($a, array('allowed_classes'=>false)); 

のようになめらかにしようとしましたが、アンシリアライズは、この方法のすべてのデータを無視する...

だから、質問は次のとおりです。 どのように私は(文字列配列を含んでいるアンシリアライズすることができます(int、string、boolなど)、望ましくないクラスのオブジェクトを直列化解除したり、望ましくないコードを実行したりするのを防ぐことができますか?

ありがとうございます。

答えて

2

あなたが使用しているPHPのバージョンは言及しなかったが、unserializeの第2引数はphp.netからPHP 7.

でのみ利用可能です:

7.0.0オプションパラメータがされています追加されました。

PHP 5.5.9-1ubuntu4.20(CLI):

php > $a = serialize(array('a'=>'b', 'c'=>20)); 
php > var_dump(unserialize($a, array('allowed_classes'=>false))); 
PHP Warning: unserialize() expects exactly 1 parameter, 2 given in php shell code on line 1 
PHP Stack trace: 
PHP 1. {main}() php shell code:0 
PHP 2. unserialize() php shell code:1 
bool(false) 

PHP 7.0.12(CLI):

php > $a = serialize(array('a'=>'b', 'c'=>20)); 
php > var_dump(unserialize($a, array('allowed_classes'=>false))); 
array(2) { 
    ["a"]=> 
    string(1) "b" 
    ["c"]=> 
    int(20) 
} 

PHP 7.0.12(CLI)シリアライズとオブジェクト:

php > $a = serialize(array('a'=>'b', 'c'=>20, 'd'=> new Exception)); 
php > var_dump(unserialize($a, array('allowed_classes'=>false))); 
array(3) { 
    ["a"]=> 
    string(1) "b" 
    ["c"]=> 
    int(20) 
    ["d"]=> 
    object(__PHP_Incomplete_Class)#1 (8) { 
    ["__PHP_Incomplete_Class_Name"]=> 
    string(9) "Exception" 
    ["message":protected]=> 
    string(0) "" 
    ["string":"Exception":private]=> 
    string(0) "" 
    ["code":protected]=> 
    int(0) 
    ["file":protected]=> 
    string(14) "php shell code" 
    ["line":protected]=> 
    int(1) 
    ["trace":"Exception":private]=> 
    array(0) { 
    } 
    ["previous":"Exception":private]=> 
    NULL 
    } 
} 

セキュリティや完全性については言えませんが、comment 119851unserialize PHPドキュメント> PHP 5.3のオプションの引数でunserializeのこのimplmentationを与える:

function php7_unserialize($str, $options = array()) 
{ 
    if(version_compare(PHP_VERSION, '7.0.0', '>=')) 
    { return unserialize($str, $options); } 

    $allowed_classes = isset($options['allowed_classes']) ? 
    $options['allowed_classes'] : true; 
    if(is_array($allowed_classes) || !$allowed_classes) 
    { 
    $str = preg_replace_callback(
     '/(?=^|:)(O|C):\d+:"([^"]*)":(\d+):{/', 
     function($matches) use ($allowed_classes) 
     { 
     if(is_array($allowed_classes) && 
      in_array($matches[2], $allowed_classes)) 
     { return $matches[0]; } 
     else 
     { 
      return $matches[1].':22:"__PHP_Incomplete_Class":'. 
      ($matches[3] + 1). 
      ':{s:27:"__PHP_Incomplete_Class_Name";'. 
      serialize($matches[2]); 
     } 
     }, 
     $str 
    ); 
    } 
    unset($allowed_classes); 
    return unserialize($str); 
} 
+0

はい、@unserializeを使用するために私のミスだったので、私はPHP 5.3でこの警告を見ることができ波平。 – AlexandrX

+0

と、php7_unserialize実装のおかげで、私が見る限り安全です。 – AlexandrX

関連する問題