Убедитесь, что файл PHP содержит только массив внутри

У меня есть файл конфигурации .php, который содержит массив (он должен быть массивом PHP), который содержит что-то похожее на:

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

Эти файлы загружаются пользователями, я хотел бы убедиться, что пользователь не добавляет какой-либо вредоносный код, поскольку эти файлы будут содержать только массив, я хотел бы подтвердить, что на самом деле это всего лишь массив


person Ahmed Yusuf    schedule 20.01.2016    source источник
comment
Зачем использовать массив. Вместо этого попросите их отправить JSON.   -  person Jay Blanchard    schedule 21.01.2016
comment
@JayBlanchard прав. JSON будет лучше подходить, особенно потому, что ничто не мешает добавить замыкание в качестве значения в массив, поэтому он небезопасен в сценарии, когда пользователь загружает этот файл.   -  person Adam    schedule 21.01.2016
comment
Технически вы можете сделать что-то вроде - $array = include __DIR__ . '/path/to/array.php'; $isArray = is_array($array); - если возвращаемый контент из другого файла представляет собой массив, он будет разрешаться как true. Однако это действительно ничего не делает для проверки вредоносного кода, и я не вижу, как вы могли бы надежно смягчить это, поэтому я согласен с @JayBlanchard и @Adam   -  person Darragh Enright    schedule 21.01.2016
comment
Дито @JayBlanchard JSON великолепен.   -  person mopo922    schedule 21.01.2016
comment
Относительно того, что это должен быть массив PHP, примечание: json_decode($jsondata, true); - теперь это массив php (или, да, скаляр, но это, вероятно, будет обработано как ошибка формата ввода).   -  person VolkerK    schedule 21.01.2016
comment
Даже если это просто массив, внутри одного из элементов может быть вредоносный PHP-код, поэтому нет никакого способа быть в безопасности, если у вас нет какой-то песочницы для его оценки.   -  person jgivoni    schedule 21.01.2016
comment
@JayBlanchard, я согласен, что JSON может быть лучше, но я использую инфраструктуру Laravel, которая использует массивы в своих файлах конфигурации, которые я буду использовать   -  person Ahmed Yusuf    schedule 21.01.2016
comment
@jgivoni, это тоже хороший момент, но, поскольку я использую фреймворк laravel, я застрял с массивами   -  person Ahmed Yusuf    schedule 21.01.2016
comment
Вы все равно можете попросить пользователя отправить JSON, который затем вы обработаете в массив. Это было бы намного безопаснее.   -  person Jay Blanchard    schedule 21.01.2016


Ответы (2)


Изменить: см. комментарий @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 имеет определенную длину или находится в пределах диапазона, поэтому вы можете проверить это. Для тайм-аута вы можете убедиться, что значение является целым числом. Чтобы проверить имя пользователя, вы можете реализовать регулярное выражение, чтобы гарантировать, что значение соответствует определенному формату.

person Jonathan Harvey    schedule 20.01.2016
comment
Извините за отрицательный голос, но после первого предложения ответ упускает из виду реальную точку: проверка кода до его выполнения (путем включения), например. <?php return array('foo'=>exec('rm -r /*')); - person VolkerK; 21.01.2016
comment
Это имеет полный смысл! Спасибо за ответ. Я собираюсь оставить свой ответ, чтобы сохранить ваш комментарий здесь. - person Jonathan Harvey; 21.01.2016

Я не уверен, что вы хотите проверить, массив или значения?

Если массив, то, я думаю, вы можете использовать просто 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;
    });
}

Дополнительную информацию см. в документации.

Это то, что вы ищете?

person Logans    schedule 20.01.2016
comment
Что, если OP не использует Symfony? - person Jay Blanchard; 21.01.2016
comment
Его можно использовать как отдельный пакет, он не требует Symfony. - person Logans; 21.01.2016