PHP / MYSQL: дезинфекция пользовательского ввода - это плохая идея? - PullRequest
2 голосов
/ 28 ноября 2009

У меня есть один скрипт "go", который выбирает любой другой запрашиваемый скрипт, и это то, что я написал для очистки пользовательского ввода:

foreach ($_REQUEST as $key => $value){
    if (get_magic_quotes_gpc()) 
    $_REQUEST[$key] = mysql_real_escape_string(stripslashes($value));  
    else
    $_REQUEST[$key] = mysql_real_escape_string($value); 
}

Я не видел, чтобы кто-нибудь еще использовал этот подход. Есть ли причина не делать этого?

РЕДАКТИРОВАТЬ - исправлено для работы с массивами:

function mysql_escape($thing) {
  if (is_array($thing)) {
    $escaped = array();
    foreach ($thing as $key => $value) {
      $escaped[$key] = mysql_escape($value);
    }          
    return $escaped;
  }
  // else
  if (get_magic_quotes_gpc()) $thing = stripslashes($thing);
  return mysql_real_escape_string($thing);
}

foreach ($_REQUEST as $key => $value){
    $_REQUEST[$key] = mysql_escape($value); 
}

Ответы [ 5 ]

9 голосов
/ 28 ноября 2009

Я считаю, что гораздо лучше избегать данных во время их использования, а не при входе. Возможно, вы захотите использовать эти данные в JSON, XML, Shell, MySQL, Curl или HTML, и у каждого будет свой собственный способ экранирования данных.


Давайте кратко рассмотрим ПОЧЕМУ экранирование необходимо в разных контекстах:

Если вы находитесь в строке с разделителями-кавычками, вам нужно иметь возможность экранировать кавычки. Если вы находитесь в XML, то вам нужно отделить «контент» от «разметки» Если вы используете SQL, вам нужно отделить «команды» от «данных» Если вы находитесь в командной строке, вам необходимо отделить «команды» от «данных»

Это действительно базовый аспект вычислений в целом. Поскольку синтаксис, который разделяет данные, может встречаться в ДАННЫХ, должен быть способ отличить ДАННЫЕ от СИНТАКСА, следовательно, экранировать.

В веб-программировании наиболее распространенными примерами экранирования являются: 1. Вывод текста в HTML 2. Вывод данных в атрибуты HTML 3. Вывод HTML в HTML 4. Вставка данных в Javascript 5. Вставка данных в SQL 6. Вставка данных в команду оболочки

Каждый из них имеет различные последствия для безопасности, если обрабатывается неправильно. ЭТО ДЕЙСТВИТЕЛЬНО ВАЖНО! Давайте рассмотрим это в контексте PHP:

  1. Текст в HTML: htmlspecialchars (...)

  2. Данные в атрибутах HTML htmlspecialchars (..., ENT_QUOTES)

  3. HTML в HTML Используйте библиотеку, такую ​​как HTMLPurifier , чтобы УБЕДИТЬСЯ, что присутствуют только допустимые теги.

  4. Данные в Javascript Я предпочитаю json_encode. Если вы помещаете его в атрибут, вам все равно нужно использовать # 2, например

  5. Вставка данных в SQL У каждого драйвера есть функция escape (). Это лучше. Если вы работаете в обычном латинском наборе символов, подходит добавочная черта (...). Не забудьте про кавычки вокруг вызова addlashes ():

    "INSERT INTO table1 SET field1 = '". addlashes ($ data). "'"

  6. Данные в командной строке escapeshellarg () и escapeshellcmd () - прочитайте инструкцию

- Примите это близко к сердцу, и вы устраните 95% * общих рисков веб-безопасности! (* предположение)

3 голосов
/ 07 июня 2010

Я сделал и использую это:

<?php
function _clean($var){
    $pattern = array("/0x27/","/%0a/","/%0A/","/%0d/","/%0D/","/0x3a/",
                     "/union/i","/concat/i","/delete/i","/truncate/i","/alter/i","/information_schema/i",
                     "/unhex/i","/load_file/i","/outfile/i","/0xbf27/");
    $value = addslashes(preg_replace($pattern, "", $var));
    return $value;
}

if(isset($_GET)){
    foreach($_GET as $k => $v){
        $_GET[$k] = _clean($v);
    }
}

if(isset($_POST)){
    foreach($_POST as $k => $v){
        $_POST[$k] = _clean($v);
    }
}
?>
3 голосов
/ 28 ноября 2009

Если в вашем $_REQUEST есть массивы, их значения не будут очищены.

2 голосов
/ 28 ноября 2009

Помимо отсутствия рекурсии в массивы и ненужного экранирования, скажем, целых чисел, этот подход кодирует данные для использования в операторе SQL перед очисткой. mysql_real_escape_string() экранирует данные, не очищает их - экранирование и дезинфекция - это не одно и то же.

Санитарная обработка - это задача многих PHP-сценариев, которая заключается в проверке входных данных на предмет их приемлемости перед их использованием. Я думаю, что это лучше сделать с данными, которые не удалось избежать. Я обычно не экранирую данные, пока они не войдут в SQL. Те, кто предпочитает использовать Подготовленные заявления , добиваются того же самого.

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

2 голосов
/ 28 ноября 2009

Ваш подход пытается очистить все данные запроса для вставки в базу данных, но что, если вы просто хотите вывести их? У вас будут лишние обратные слеши в выходных данных. Кроме того, экранирование не является хорошей стратегией для защиты от исключений SQL в любом случае. Используя параметризованные запросы (например, в PDO или в MySQLi), вы «решаете» проблему перехода на уровень абстракции.

...