[help] Разрешение передачи только определенных параметров методом GET

Статус
В этой теме нельзя размещать новые ответы.

HatoL

Профессор
Регистрация
5 Фев 2008
Сообщения
206
Реакции
36
Если я заранее знаю, что скрипт будет передавать только один определенный параметр (назовем его "str"), то как мне запретить передачу других параметров? В моем случае все ссылки будут иметь вид Для просмотра ссылки Войди или Зарегистрируйся и надо, чтобы пользователь не мог никак повлиять на другие переменные, например так Для просмотра ссылки Войди или Зарегистрируйся (на случай если register_globals будет On).

Первое, что пришло в голову - использовать условие count($_GET) > 1, но в данном случае можно передать другой параметр, хоть он и один.

Второе: использовать цикл foreach, чтобы просмотреть содержимое массива $_GET.

Есть другие варианты ? И если нет, то приведите пример использования второго варианта.
 
Первое, что приходит в голову - отрубайте запросы к скрипту, не подходящие под ваш шаблон, на уровне ModRewrite, отдавая 403.
 
хотелось бы услышать более универсальное решение. Mod_rewrite может и не быть на хосте
 
вначале скрипта выдерни свою переменную, а потом обнули весь массив входящих данных через unset
 
По поводу чистки опасных входящих переменных...

вначале скрипта выдерни свою переменную, а потом обнули весь массив входящих данных через unset

Это ничего полезного не даст при опции register_globals = on.

Потому что при такой опции переменные становятся глобальными (а не только внутри массива). Даже если Вы очистите (unset) все массивы входящих данных ($_GET, $_POST) переменные все равно останутся.

Если я заранее знаю, что скрипт будет передавать только один определенный параметр (назовем его "str"), то как мне запретить передачу других параметров? В моем случае все ссылки будут иметь вид Для просмотра ссылки Войди или Зарегистрируйся и надо, чтобы пользователь не мог никак повлиять на другие переменные, например так Для просмотра ссылки Войди или Зарегистрируйся (на случай если register_globals будет On).

Ну для этого придётся чистить ВСЕ последствия register_globals = on (а он распаковывает не только $_GET, а ещё и $_POST, $_COOKIE, $_SESSION и т.п., всего обычно 4-5 массивов в зависимости от настроек PHP).

Тогда вначале нужно по КАЖДОМУ из этих массивов делать проход и вычищать последствия из массива $GLOBALS (тогда удалятся и входящие переменные).

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

PHP:
foreach ($_GET as $key=>$value) {
    unset ($GLOBALS[$key]);
}

А ещё лучше даже сразу чистить по $_REQUEST (если я не ошибаюсь, он включает в себя сразу и $_GET и $_POST), хотя только этого может быть не достаточно.

PHP:
foreach ($_REQUEST as $key=>$value) {
    unset ($GLOBALS[$key]);
}

Абсолютно весь массив $_GLOBALS очищать крайне не рекомендуется, последствия непредсказуемы :)

Первое, что пришло в голову - использовать условие count($_GET) > 1, но в данном случае можно передать другой параметр, хоть он и один.

Ну даже эту идею можно развивать, только лучше через $_REQUEST.

К примеру:

PHP:
if ((!isset ($_REQUEST['str'])) OR (count($_REQUEST)>1)) {
   die ('Error');
}


Второе: использовать цикл foreach, чтобы просмотреть содержимое массива $_GET.

Есть другие варианты ? И если нет, то приведите пример использования второго варианта.

Ну вот с foreach я привёл пример выше, а вообще, как уже сказал, если только с $_GET - то это не очень надёжно, так переменные могут поступать и с $_COOKIE и т.п.

Т.е. здесь даже .htaccess (ModRewrite) не почистит все данные скорее всего.

P.S. И в заключение: ;)

Три небольших совета как избежать этого гимора (register_globals = on, чистка переменных и т.п.) при написании своих скриптов:


  1. Любой переменной перед использованием всегда задавайте значение (даже пустое или нулевое, например $k = 0; $d = array () и т.п.). Это перезапишет любые попытки подменить переменную извне.

  • Все входящие переменные брать лучше сразу из массивов ($_GET и т.п.) и проверять preg_match - это позволит точно определить откуда переменная и не опасна ли она.

  • Я вряд ли открою что-то новое :), если намекну про фреймворки (CakePHP, CodeIgniter и т.п.), в которых все эти переменные чистятся автоматом независимо от настроек PHP.
 
Это ничего полезного не даст при опции register_globals = on.

Смотря как чистить будешь. естесно не тупо unset($_GET);

А ещё лучше даже сразу чистить по $_REQUEST (если я не ошибаюсь, он включает в себя сразу и $_GET и $_POST)

$_GET $_POST $_COOKIE
 
System777 спасибо, вы меня убедили не заморачиваться этим и все же инициализировать переменные перед использованием, а все входящие данные проверять. Так будет лучше имхо.
 
Для получения переменных использую вот такую простенькую функцию. Очень помогает.

PHP:
/**
 * Возвращает значение переменной из $_REQUEST (глобальный массив ВСЕХ переданных переменных)
 * и назначает этому значению тип дефолтового значения.
 * Если тип string, то на получаемое значение применяется функция trim
 * @access public
 * @param string $varname Имя переменной
 * @param mixed $default Значение по умолчанию
 * @return mixed
 */
function request($varname, $default) {
  $type = gettype($default);
  $export = isset ($_REQUEST[$varname]) ? $_REQUEST[$varname] : $default;
  settype($export, $type);
  if ($type == 'string') // на одном из серверов было странное поведение 
    $export = str_replace('\r\n', "\r\n", trim($export));
  return $export;
}

Использование:
PHP:
<?
$string = request('var1', '');
$float = request('var2', 0.0);
$integer = request('var3', 0);
$array = request('var4', array());
?>

По мимо этого, разумеется, предварительная пре-инициализация всех прочих переменных.
 
Вот может кому пригодится, функция, через которую желательно прогонять переменные, которые строковые, пишутся в БД или возвращаются в форму, чтобы злобный XSS вас не постиг:

PHP:
  function XSSClean($string) {
        if (get_magic_quotes_gpc()) {
            $string = stripslashes($string);
        }
        $string = str_replace(array("&amp;","&lt;","&gt;"),array("&amp;amp;","&amp;lt;","&amp;gt;",),$string);
        // fix &entitiy\n;
        
        $string = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u',"$1;",$string);
        $string = preg_replace('#(&\#x*)([0-9A-F]+);*#iu',"$1$2;",$string);
//        $string = html_entity_decode($string, ENT_COMPAT, "UTF-8");
        
        // remove any attribute starting with "on" or xmlns
        $string = preg_replace('#(<[^>]+[\x00-\x20\"\'])(on|xmlns)[^>]*>#smiUu',"$1>",$string);
        // remove javascript: and vbscript: protocol
        $string = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*)[\\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#smiUu','$1=$2nojavascript...',$string);
        $string = preg_replace('#([a-z]*)[\x00-\x20]*=([\'\"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#smiUu','$1=$2novbscript...',$string);
        $string = preg_replace('#([a-z]*)[\x00-\x20]*=([\'\"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#smiUu','$1=$2nomozbinding...',$string);
        //<span style="width: expression(alert('Ping!'));"></span> 
        // only works in ie...
        $string = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*expression[\x00-\x20]*\([^>]*>#smiU',"$1>",$string);
        $string = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*behaviour[\x00-\x20]*\([^>]*>#smiU',"$1>",$string);
        $string = preg_replace('#(<[^>]+)style[\x00-\x20]*=[\x00-\x20]*([\`\'\"]*).*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*>#smiUu',"$1>",$string);
        //remove namespaced elements (we do not need them...)
        $string = preg_replace('#</*\w+:\w[^>]*>#smi',"",$string);
        //remove really unwanted tags
        
        do {
            $oldstring = $string;
            $string = preg_replace('#</*(applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#smi',"",$string);
        } while ($oldstring != $string);
        
        return $string;
    }

Раскомментируйте по вкусу, если кому-то что-то еще нужно будет.
 
На случай, если глобалс ОН, надо сделать:

PHP:
ini_set('register_globals', 'off');
или поместить в каталог сайта директиву для htaccess

И не забивать ни себе ни скрипту голову кодом, от которого волосы дыбом встают....

а от ON отказываются МНОГИЕ в виду его.... влияния на скрипт....
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху