2012-03-18 6 views
1

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

$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 чтобы этот код был безопасным? В моем случае я не делаю никаких подключений к базе данных.

+0

Существует ли каталог '. $ Myvar', или вы создаете его на лету? –

+0

@Pekka: Этот код ничего не создает на лету. –

+0

Дезинфицирует все входы с помощью php-фильтров, этого должно быть более чем достаточно для вашего кода. http://br.php.net/manual/en/filter.filters.sanitize.php – B4NZ41

ответ

5

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

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

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

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

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

+0

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

+2

Да, конечно. В случаях, когда это очень ясно, вы можете изменить регулярное выражение на что-то вроде «/^(option1 | option2 | option3)» /. Всегда ограничивайте ввод как можно больше. –

+0

На самом деле все хорошие предложения. Я склонен полагаться на массивы (или другие вещи в более сложных ситуациях) из-за гибкости хранения в синхронизации с FS и избежания дублирования кода/логики. Но эй, хорошие моменты. – maraspin

3

Действительно, действительно опасно делать что-то вроде: 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 альтернативного подхода разрешать все, кроме соответствия определенного шаблона. Я думаю, что первое безопаснее.

+1

Любой пример, как его фильтровать? – Gumbo

+0

tnx для downvote. мой подход не кажется настолько неправильным. – maraspin

+0

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

1

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

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

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

2

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

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

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

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

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