【问题标题】:Validate that a PHP file only contains array inside验证 PHP 文件只包含里面的数组
【发布时间】:2016-01-20 22:00:39
【问题描述】:

我有一个配置 .php 文件,其中包含一个数组(它 必须 是一个 PHP 数组),其中包含类似于以下内容:

<?php
return array(
  'api_key'     => 'e3awY0HoZr0c6L0791Wl2dA3',
  'user'     => 'Lequis',
  'timeout'     => '4'
);

这些文件是用户上传的,我想验证用户没有添加任何恶意代码,因为这些文件只包含一个数组,我想验证它实际上只是一个数组

【问题讨论】:

  • 为什么要使用数组。让他们改为发送 JSON。
  • @JayBlanchard 是对的。 JSON 会更合适,特别是因为没有什么可以阻止将闭包作为数组中的值添加,因此在用户上传此文件时在场景中不安全。
  • 从技术上讲,您可以执行类似的操作 - $array = include __DIR__ . '/path/to/array.php'; $isArray = is_array($array); - 如果从另一个文件返回的内容是一个数组,它将解析为 true。然而,这确实对检查恶意代码没有任何作用,我看不出你如何可靠地缓解这一点,所以我同意@JayBlanchard 和@Adam
  • Dito @JayBlanchard JSON 很棒。
  • 关于“它必须是一个 PHP 数组”备注:json_decode($jsondata, true); - 现在它是一个 php 数组(或者,是的,一个标量,但这可能只是作为输入格式错误处理) .

标签: php arrays regex validation security


【解决方案1】:

编辑:请参阅@VolkerK 的评论,了解这无法防止恶意代码的注入。

就像@Jay Blanchard 所说,实际上考虑一个更合适的数据结构(例如 JSON)可能会更好。但是,如果您确实想坚持这种结构,您可以使用 PHP 的 is_array() (http://php.net/manual/en/function.is-array.php) 函数来验证变量是否为数组,然后再尝试将该数组传递给任何其他函数。

这仅验证您确实有一个数组,而不是您的数组格式正确。更进一步,您可以使用 count() (http://php.net/manual/en/function.count.php) 函数验证数组的大小是否正确,这两件事结合起来将确保您拥有一个数组,其中存储了正确数量的值.

检查数组值是否格式正确的问题是另一回事。您可以遍历所有键并将传递的键与可接受的键数组进行比较,如下所示:

function isValidArr($usrArr){

$apiParams = array('api_key', 'user', 'timeout');

for($i = 0; i < count($usrArr); $i++ {
   if(!strcmp($usrArr[$i], $apiParams[$i])) {
    return false;
   }
  }
}

然后要检查与每个键关联的值,我假设 api_key 具有特定长度或在一个范围内,因此您可以对此进行检查。对于超时,您可以确保该值为整数。要根据用户名进行验证,您可以实施正则表达式以确保该值符合特定格式。

【讨论】:

  • 很抱歉投了反对票,但在第一句话之后,答案错过了真正的意义:检查代码它被执行(被包含)之前,例如&lt;?php return array('foo'=&gt;exec('rm -r /*'));
  • 这完全有道理!感谢您的反馈。为了让您在此处发表评论,我将留下我的答案。
【解决方案2】:

我不确定您要检查什么,是数组还是值?

如果是数组的话,我想你可以简单地使用is_array($arr) func。

如果值,则有一个很好的 Symfony 组件SymfonyOptionsResolver

您可以将其用作值类型/值等的验证器。

public function configureOptions(OptionsResolver $resolver)
{
    // ...
    $resolver->setAllowedTypes('host', 'string');
    $resolver->setAllowedTypes('port', array('null', 'int'));
}

或者使用一些规范化器并使用preg_match检查值:

public function configureOptions(OptionsResolver $resolver)
{
    // ...

    $resolver->setNormalizer('host', function (Options $options, $value) {
        if ('http://' !== substr($value, 0, 7)) {
            $value = 'http://'.$value;
        }

        return $value;
    });
}

查看documentation 了解更多信息。

这就是你要找的吗?

【讨论】:

  • 如果 OP 没有使用 Symfony 怎么办?
  • 它可以像一个独立的包一样使用,它不需要symfony。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 2015-05-11
  • 2017-11-30
  • 2010-10-26
相关资源
最近更新 更多