【问题标题】:Why are private variables in an object "visible" from the outside world?为什么对象中的私有变量对外界“可见”?
【发布时间】:2011-10-24 23:13:18
【问题描述】:

举个例子:

class Database
{
    private $host,
            $database, 
            $username, 
            $password,
            $type;

    public $active_connection;

    //Some methods
}


class Page
{
    private $db;


    public function __construct($id)
    {
        // Some code

        $this->db = new Database($id);
    }

    //Some Methods
}


$page = new Page(0);

var_dump($page);

这将输出数据库对象的私有变量,即使它们被标记为私有(因此,据我了解,外部世界无法使用)。

我的问题是:

  1. 这是安全风险吗?
  2. 有没有办法有效地隐藏那些标记为私有的变量?

提前致谢

编辑: 在这个项目中,管理部分将提供创建自定义 PHP 脚本以作为部分合并到站点中的功能。由于这是针对第三方实体开发的,我担心的是,出于某种原因,客户无意中转储了 $page 对象(在我们的代码中,它是主要的可修改对象)以“探索”它。

【问题讨论】:

  • 属性可见性不是安全功能。而var_dump恰好是一个调试函数。

标签: php class object


【解决方案1】:

封装是一种架构机制,不是安全措施,不能这样使用。

攻击者究竟将如何利用此安全风险?它只能从源代码内部访问,因此他也可以阅读受保护类的源代码或项目中的任何其他源代码。

此外,即使在 C++ 中,您也可以通过准备一个指向对象的正确偏移量的指针来访问私有成员。

【讨论】:

  • 在这个项目中,管理部分将提供创建自定义 PHP 脚本以作为部分合并到站点中的功能。由于这是针对第三方实体开发的,我担心的是,出于某种原因,客户无意中转储了 $page 对象(在我们的代码中,它是主要的可修改对象)以“探索”它。
【解决方案2】:

var_dump() 显示它们,因为它很特别。您还可以使用Reflection API 挖掘私有/受保护的属性。

echo $object->_somePrivateVar;

另一方面,不会暴露 _somePrivateVar。

1) 这是一个安全问题吗?一点也不。如果你不信任你正在执行的代码,那你就很傻。

2) 将它们隐藏起来?根据类系统的数据可见性规则,它们已经被隐藏了。但是这种语言是动态的,并且提供了一些其他的方法来窥探内部。正如 Leonid 在他的回答中所说,这是一种架构机制,而不是安全功能。

【讨论】:

  • 广告 2) 将它们隐藏起来,例如在 this 等异常/错误报告中。然后,您可以使用魔术方法__debugInfo() 隐藏您的变量以防止变量转储/导出/报告。
【解决方案3】:

PHP 5.6 中引入了新的 Magic 方法 __debugInfo(),它允许您在转储对象时修改 var_dump() 的默认行为。

看看documentation

示例:

<?php
class C {
    private $prop;

    public function __construct($val) {
        $this->prop = $val;
    }

    public function __debugInfo() {
        return [
            'propSquared' => $this->prop ** 2,
        ];
    }
}

var_dump(new C(42));
?>

返回:

object(C)#1 (1) {
  ["propSquared"]=>
  int(1764)
}

虽然这个问题已经有 3 年的历史了,但我相信将来有人会发现这很有用。

【讨论】:

    【解决方案4】:

    var_dump 旨在供开发人员跟踪和调试代码。来自documentation

    在 PHP 5 中,对象的所有公共、私有和受保护属性都将在输出中返回。

    【讨论】:

      【解决方案5】:

      这是var_dump(以及print_rvar_export)的记录行为。这是一种了解正在运行的代码的方法;例如,在调试它时,您可能想知道私有变量的值。

      您可以使用输出控制函数捕获输出,或者如果您需要在另一个类中使用私有变量的内容,则使用var_export。这将是一种不寻常的情况:无论如何,您很可能在这种情况下使用公共变量。如果您正在开发某种需要验证私有变量内容的测试套件,那么这就是您的答案。

      【讨论】:

        【解决方案6】:

        我知道这是一个老问题,但我想指出一种(相当)有效的屏蔽变量的方法;

        您可以在包含静态变量的类内部创建一个函数;如果您确实觉得需要对系统本身隐藏变量,请将其保存到函数的静态变量中。只要该函数是类私有的,就很难窥探内部。还行吧。如果由于某种原因您的服务器将值转储到用户区并且您无法控制它。

        但正如 TimDev 所说:如果您不信任正在执行的代码,则表明您存在一些更大的安全问题。即使你有一个带有潜在恶意插件作者的基于插件的项目,你也根本无法在那种环境中保护自己。由安装这些插件的管理员来确保安全性。

        【讨论】:

          【解决方案7】:

          查看 __debugInfo() magic method in PHP manual 如何隐藏堆栈跟踪中的敏感数据(在 PHP 5.6.0 中添加)。这是一个例子:

          class PDO_Database
          {
              private $db_user = 'my_user';
              private $db_password = 'my_password';
          
              /**
               * The purpose of this method is to hide sensitive data from stack traces.
               *
               * @return array
               */
              public function __debugInfo()
              {
                  $properties = get_object_vars($this);
          
                  $hidden = [
                      'db_user' => '***',
                      'db_password' => '***',
                  ];
          
                  return $hidden + $properties;
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-07-08
            • 1970-01-01
            • 2015-08-23
            • 2015-01-19
            • 1970-01-01
            • 2011-03-21
            • 1970-01-01
            • 2012-01-18
            相关资源
            最近更新 更多