Обрабатывать $ _GET безопасно PHP - PullRequest
1 голос
/ 18 марта 2012

У меня есть такой код:

$myvar=$_GET['var'];

// a bunch of code without any connection to DB where $myvar is used like this:

$local_directory=dirname(__FILE__).'/images/'.$myvar;
if ($myvar && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}

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

Ответы [ 4 ]

5 голосов
/ 18 марта 2012

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

Iчасто используя что-то вроде этого:

$myvar =  preg_replace("/[^a-zA-Z0-9-]/","",$_GET['var']);

Это заменяет все, что не a-zA-Z0-9-, пробелом, поэтому, если переменная содержит скажем, *, этот код удалит это.

Затем я изменяю a-zA-Z0-9- в соответствии с тем, какие символы я хочу разрешить в строке.После этого я могу заблокировать только цифры или все, что мне нужно.

3 голосов
/ 18 марта 2012

Это действительно очень опасно делать что-то вроде: opendir($local_directory), где $local_directory - это значение, которое может прийти извне.

Что, если кто-то пройдет что-то вроде ../../../../../../../../../etc ... или что-то в этом роде? Вы рискуете поставить под угрозу безопасность вашего хоста.

Вы можете взглянуть сюда, чтобы начать: http://php.net/manual/en/book.filter.php

ИМХО, если вы ничего не создаете на лету, у вас должно быть что-то вроде:

$allowed_dirs = array('dir1','dir2', 'dir3');
if (!in_array($myvar, $allowed_dirs)) {
    // throw an error and log what has happened
}

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

Итак, в конце вы можете получить что-то вроде:

$allowed_dirs = array();
if ($handle = opendir(dirname(__FILE__) . '/images')) {
    while (false !== ($entry = readdir($handle))) {
            $allowed_dirs[] = $entry;
    } 
    closedir($handle);
}
$myvar=$_GET['var'];

// you can deny access to dirs you want to protect like this
unset($allowed_dirs['private_stuff']);

// rest of code
$local_directory = dirname(__FILE__) . "/images/.$myvar";
if (in_array(".$myvar", $allowed_dirs) && $handle = opendir($local_directory)) {
    $i=0; 
    while (false !== ($entry = readdir($handle))) {
        if(strstr($entry, 'sample_'.$language.'-'.$type)) {
            $result[$i]=$entry;
            $i++;
        }
    } 
    closedir($handle);
} else {
    echo 'error';
}

Код выше НЕ оптимизирован. Но давайте избегать преждевременной оптимизации в этом случае (указав это, чтобы избежать еще одного «приятного» снижения); сниппет просто для того, чтобы дать вам представление о явном разрешении значений VS альтернативному подходу, разрешающему все, кроме соответствия определенному шаблону. Я думаю, что первый более безопасен.

2 голосов
/ 18 марта 2012

Позвольте мне просто отметить для полноты, что если , вы можете быть уверены, что ваш код будет работать только на Unixish-системах (таких как Linux), только , что вам необходимо обеспечить это что:

  1. $myvar не содержит слеш ("/", U + 002F) или нулевых ("\0", U + 0000) символов, а также

  2. $myvar не является пустым или равно "." (или, что эквивалентно, ".$myvar" не равно "." или "..").

Это потому, что в файловой системе Unix единственным символом-разделителем каталогов (и один из двух символов не допускается в именах файлов, а другой является нулевым символом "\0") является косая черта, и единственные специальные записи каталога, указывающие вверх в дереве каталогов "." и "..".

Однако, если ваш код когда-нибудь будет запущен в Windows, вам нужно запретить большее количество символов (по крайней мере, обратную косую черту, "\\" и, возможно, другие). Я недостаточно знаком с соглашениями о файловой системе Windows, чтобы точно сказать, какие символы вам нужно запретить, но подход safe заключается в том, чтобы сделать , как предлагает Рич Брэдшоу и только разрешить символы, которые вы знаете в безопасности.

1 голос
/ 18 марта 2012

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

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

В вашем случае значение $myvar должно быть, по крайней мере, допустимым именем каталога, но это также может быть допустимый относительный путь, состоящий из имен каталогов, в зависимости от ваших требований. На этом этапе вы должны указать эти требования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...