Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Безопасно ли так принимать значение?


Автор: maxipub 28.7.2014, 17:05
Добрый день.

Еще один банальный вопрос, но все же...

Код
if (isset($_POST['param']) && in_array($_POST['param'], array('val_1', 'val_2', 'val_3')))
    require BASE_DIR.'inc/'.$_POST['param'].'.php';


Т.е. никоим образом не фильтровать переменную, просто проверять in_array, и если все ок, то прямо так и инклудить?

Возможно, есть какие-нибудь подводные камни, спецсимволы, которые in_array не уловит и т.д.?

Автор: Aliance 29.7.2014, 10:06
in_array будет равен простому сравнению (==) между всеми значениями массива с группировкой по или (||). Максимум что можно добавить - это тождественное сравнение (===), путем задания третьего аргумента согласно http://php.net//manual/ru/function.in-array.php.
В итоге получаем что безопасности ничего не угрожает в данном коде.

Хотя я лично такой код не принял бы на ревью, предложив хотя бы такой вариант:
Код

if (isset($_POST['param'])) {
    switch ($_POST['param']) {
        case 'val_1':
        case 'val_2':
        case 'val_3':
            require BASE_DIR . 'inc/' . $_POST['param'] . '.php';
            break;
        default:
            throw new Exception('Wrong param');
            break;
    }
}

Автор: maxipub 29.7.2014, 16:50
Aliance, спасибо огромное, особенно за неточное сравнение! smile 

ЗЫ: а для общего развития, не могли бы подсказать, почему switch? Там ведь только неточное. Да и в in_array массив можно передавать переменной (из конфига или в некую функцию), вроде бы гибче и лаконичней? smile 

Автор: ndbn 30.7.2014, 09:14
А я бы написал вот так, хотя вопрос не в этом.
Код

<?php
 //....
  $acceptable = array(
    'val_1',
    'val_2',
    'val_3',
  );  
  $param = filter_input( INPUT_POST, 'param');
  if($param && in_array($param, $acceptable)
  {
    $filepath = BASE_DIR . 'inc' . DIRECTORY_SEPARATOR . $param . '.php';
    if(file_exists($filepath))
    {        
        require_once $filepath;
    }
  } 


после того, как узнал о существовании функции http://php.net/manual/ru/function.filter-input.php уже не могу её не применять

Автор: maxipub 30.7.2014, 10:10
ndbn, а что именно filter_input выполняет в вашем примере?

Вообще, не хочется разводить флуд, но какое-то странное решение... file_exists + require_once как минимум smile 

И вообще, в моем конкретном случае суть не в валидации данных, а в возможности как раз упустить ее, если in_array (как мы уже выяснили) корректно будет принимать что угодно. Ведь конкретное множество доступных значений строго определено.

Автор: Aliance 30.7.2014, 11:41
Цитата(maxipub @  29.7.2014,  17:50 Найти цитируемый пост)
а для общего развития, не могли бы подсказать, почему switch? Там ведь только неточное. 

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

Цитата(maxipub @  29.7.2014,  17:50 Найти цитируемый пост)
Да и в in_array массив можно передавать переменной (из конфига или в некую функцию), вроде бы гибче и лаконичней? 

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

Автор: ndbn 30.7.2014, 13:50
maxipub, 
Цитата

а что именно filter_input выполняет в вашем примере?

Вырежет служебные символы, если не указывать третий параметр, то по-умолчанию он равен FILTER_DEFAULT или FILTER_UNSAFE_RAW.

Цитата

какое-то странное решение... file_exists + require_once как минимум

Процитирую справку
Цитата

require идентично include() за исключением того, что при ошибке оно также выдаст фатальную ошибку уровня E_COMPILE_ERROR. Другими словами, она остановит выполнение скрипта, тогда как include() только выдала бы предупреждение E_WARNING, которое позволило бы скрипту продолжить выполнение.


Цитата

Ведь конкретное множество доступных значений строго определено. 

Всякое бывает, маловероятно, но вполне реально, что обнаружится баг, например "при передаче в первом параметре функции in_array байта 0x02 она всегда возвращает TRUE"(повторюсь, это для примера). Я считаю, что лучше перебдеть.

Автор: maxipub 30.7.2014, 16:22
Цитата(ndbn @  30.7.2014,  13:50 Найти цитируемый пост)
Процитирую справку

Так в том то и дело! Когда программист использует require, подразумевается что без данного инклуда продолжение выполнение скрипта недопустимо. Вы же своей конструкцией require превратили зачем-то в include. smile 

Цитата(ndbn @  30.7.2014,  13:50 Найти цитируемый пост)
вполне реально

А для filter_input значит это не "вполне реально"? smile Не вижу разницы.

Автор: s0lman 30.7.2014, 18:51
Цитата(maxipub @  30.7.2014,  09:10 Найти цитируемый пост)
file_exists 

Лишнее обращение к файловой системе (по дефолту). Стараюсь не использовать без крайней надобности.

Автор: baldina 30.7.2014, 22:22
Цитата(ndbn @  30.7.2014,  13:50 Найти цитируемый пост)
вполне реально, что обнаружится баг

если обнаружится баг в программе (или тем паче в исполняемой системе), нужно от него избавляться, конкретно. а попытка учесть возможные баги...  user posted image

Цитата(maxipub @  30.7.2014,  10:10 Найти цитируемый пост)
какое-то странное решение... file_exists + require_once

 smile 

maxipub, имхо и так все достаточно безопасно, но уж если подходить параноидально, то единственная потенциальная проблема (в реальности её нет) - подстановка другого файла, использование относительного пути и тп штучки. filter тут бесполезен.
для устранения паранойййи надо обеспечить формирование пути на основе эталонного массива, а не внешних данных, т.е.
Код

$key = array_search ($param, $files);
if ($key !== false)
  include PATH . $files[$key] . '.php';

Автор: ndbn 31.7.2014, 08:37
Цитата(maxipub @  30.7.2014,  16:22 Найти цитируемый пост)
Когда программист использует require, подразумевается что без данного инклуда продолжение выполнение скрипта недопустимо. Вы же своей конструкцией require превратили зачем-то в include.

Моя конструкция лишь позволяет предотвратить вываливание ошибки пользователю. Даже если пользователь передал правильное имя файла, сам файл может отсутствовать по тем или иным причинам и заметить это в большом проекте может быть достаточно затруднительно.
В include я ничего не превращал, разница между require и include в том, что второй генерирует warning, тем не менее не вижу смысла выводить его конечному пользователю.

Цитата(maxipub @  30.7.2014,  16:22 Найти цитируемый пост)
А для filter_input значит это не "вполне реально"?  Не вижу разницы. 

Да, баг может быть где угодно, зачем пристегиваться в автомобиле, если в случае ДТП всё равно есть шанс умереть smile


Цитата(s0lman @  30.7.2014,  18:51 Найти цитируемый пост)
Стараюсь не использовать без крайней надобности. 

ИМХО, прием части имени подключаемого php файла от пользователя как раз такая крайняя необходимость.

Цитата(baldina @  30.7.2014,  22:22 Найти цитируемый пост)
а попытка учесть возможные баги...

У вас виден большой опыт в разработке больших проектов.

Ладно, срачу не быть smile

Автор: maxipub 31.7.2014, 09:32
Цитата(baldina @  30.7.2014,  22:22 Найти цитируемый пост)
для устранения паранойййи надо обеспечить формирование пути на основе эталонного массива, а не внешних данных, т.е.

Ну так в первом посте in_array не катит разве?

Ладно, всем спасибо, вопрос решен.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)