Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/237.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何取消基本类型和数组的序列化?_Php_Security_Serialization - Fatal编程技术网

Php 如何取消基本类型和数组的序列化?

Php 如何取消基本类型和数组的序列化?,php,security,serialization,Php,Security,Serialization,我必须在我的项目中对用户提供的数据使用unserialize。 IFAIK对不可信数据使用unserialize是不安全的,因为可能通过隐式调用唤醒函数和析构函数()来执行用户代码 好的,我试过这样的smth $a = serialize(array('a'=>'b', 'c'=>20)); unserialize($a, array('allowed_classes'=>false)); 但unserialize会以这种方式忽略所有数据 因此,问题是: 如何取消序列化包含数

我必须在我的项目中对用户提供的数据使用unserialize。 IFAIK对不可信数据使用unserialize是不安全的,因为可能通过隐式调用唤醒函数和析构函数()来执行用户代码

好的,我试过这样的smth

$a = serialize(array('a'=>'b', 'c'=>20));
unserialize($a, array('allowed_classes'=>false));
但unserialize会以这种方式忽略所有数据

因此,问题是: 如何取消序列化包含数组和基本数据类型(如int、string、bools等)的字符串,但不让自己取消序列化不需要的类的对象(并执行不需要的代码)


提前感谢。

您没有提到您使用的是哪个版本的PHP,但是
unserialize
的第二个参数仅在PHP7中可用

发件人:

7.0.0已添加选项参数

PHP 5.5.9-1ubuntu4.20(cli):

PHP 7.0.12(cli):

带有序列化对象的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
  }
}
我不能保证它的安全性或完整性,但在
unserialize
php文档中,使用>php 5.3的options参数给出了
unserialize
的实现:

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);
}

是的,使用@unserialize是我的错误,因此我无法在PHP5.3中看到此警告。感谢php7_unserialize实现,就我所知,它看起来很安全。
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
  }
}
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);
}