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

Тема в разделе "PHP", создана пользователем HatoL, 13 июл 2008.

Статус темы:
Закрыта.
Модераторы: latteo
  1. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    Если я заранее знаю, что скрипт будет передавать только один определенный параметр (назовем его "str"), то как мне запретить передачу других параметров? В моем случае все ссылки будут иметь вид http://site.ru/index.php?str=asdasdsad и надо, чтобы пользователь не мог никак повлиять на другие переменные, например так http://site.ru/index.php?mysql=gdsfgdfg (на случай если register_globals будет On).

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

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

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

    gregzem

    Регистр.:
    21 окт 2007
    Сообщения:
    200
    Симпатии:
    63
    Первое, что приходит в голову - отрубайте запросы к скрипту, не подходящие под ваш шаблон, на уровне ModRewrite, отдавая 403.
     
  3. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    хотелось бы услышать более универсальное решение. Mod_rewrite может и не быть на хосте
     
  4. tostrss

    tostrss

    Регистр.:
    16 окт 2007
    Сообщения:
    771
    Симпатии:
    217
    вначале скрипта выдерни свою переменную, а потом обнули весь массив входящих данных через unset
     
  5. System777

    System777 Создатель

    Регистр.:
    20 апр 2008
    Сообщения:
    30
    Симпатии:
    13
    По поводу чистки опасных входящих переменных...

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

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

    Ну для этого придётся чистить ВСЕ последствия 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 очищать крайне не рекомендуется, последствия непредсказуемы :)

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

    К примеру:

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

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

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

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

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


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

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

    • Я вряд ли открою что-то новое :), если намекну про фреймворки (CakePHP, CodeIgniter и т.п.), в которых все эти переменные чистятся автоматом независимо от настроек PHP.
     
    HatoL нравится это.
  6. tostrss

    tostrss

    Регистр.:
    16 окт 2007
    Сообщения:
    771
    Симпатии:
    217
    Смотря как чистить будешь. естесно не тупо unset($_GET);

    $_GET $_POST $_COOKIE
     
  7. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    System777 спасибо, вы меня убедили не заморачиваться этим и все же инициализировать переменные перед использованием, а все входящие данные проверять. Так будет лучше имхо.
     
  8. bork1234

    bork1234 Постоялец

    Регистр.:
    25 июн 2008
    Сообщения:
    65
    Симпатии:
    13
    Для получения переменных использую вот такую простенькую функцию. Очень помогает.

    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());
    ?>
    По мимо этого, разумеется, предварительная пре-инициализация всех прочих переменных.
     
  9. gregzem

    gregzem

    Регистр.:
    21 окт 2007
    Сообщения:
    200
    Симпатии:
    63
    Вот может кому пригодится, функция, через которую желательно прогонять переменные, которые строковые, пишутся в БД или возвращаются в форму, чтобы злобный 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;
        }
    Раскомментируйте по вкусу, если кому-то что-то еще нужно будет.
     
    bork1234 нравится это.
  10. Xenos

    Xenos Создатель

    Регистр.:
    14 янв 2008
    Сообщения:
    14
    Симпатии:
    0
    На случай, если глобалс ОН, надо сделать:

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

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

    а от ON отказываются МНОГИЕ в виду его.... влияния на скрипт....
     
Статус темы:
Закрыта.