Санитарная обработка данных пользователя в GET с помощью PHP - PullRequest
30 голосов
/ 22 августа 2009

Как вы очищаете данные в $ _GET -переменных с помощью PHP?

Я очищаю только одну переменную в GET strip_tags. Я не уверен, следует ли мне все санировать или нет, потому что в прошлый раз при передаче данных в Postgres эту проблему легче всего было решить с помощью pg_prepare.

Ответы [ 4 ]

77 голосов
/ 22 августа 2009

Как вы очищаете данные в $ _GET -переменных с помощью PHP?

Вы не очищаете данные в $ _GET. Это распространенный подход в сценариях PHP, но он совершенно неверен *.

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

Итак, если вы встраиваете строку в SQL-запрос, вам нужно ее избежать при выходе:

$sql= "SELECT * FROM accounts WHERE username='".pg_escape_string($_GET['username'])."'";

А если вы выплевываете строку в HTML, вам нужно ее избежать:

Cannot log in as <?php echo(htmlspecialchars($_GET['username'], ENT_QUOTES)) ?>.

Если вы выполнили оба эти экранирующих шага в массиве $ _GET в начале, как рекомендуют люди, которые не знают, что они делают:

$_GET['username']= htmlspecialchars(pg_escape_string($_GET['username']));

Тогда, когда у вас в имени пользователя было «&», оно таинственным образом превращалось бы в «& amp;» в вашей базе данных, а если в вашем имени пользователя был апостроф, оно превращалось в два апострофа на странице. Тогда, когда у вас есть форма с этими символами, легко получить двойной экранированный текст при редактировании, поэтому многие плохие PHP CMS заканчивают с испорченными заголовками статей, такими как «Новые книги от O \\\\». \\\\\\\\\\\\\\\ 'Reilly».

Естественно, вспоминать pg_escape_string или mysql_real_escape_string и htmlspecialchars каждый раз, когда вы отправляете переменную, немного утомительно, поэтому каждый хочет сделать это (неправильно) в одном месте в начале скрипта. Для вывода в формате HTML вы можете, по крайней мере, сохранить некоторую типизацию, определив функцию с коротким именем, которая выполняет echo (htmlspecialchars (...)).

Для SQL лучше использовать параметризованные запросы. Для Postgres есть pg_query_params . Или, действительно, подготовленные заявления, как вы упомянули (хотя я лично считаю их менее управляемыми). В любом случае, вы можете забыть о «очистке» или экранировании для SQL, но вы все равно должны уйти, если встраиваете другие типы строк, включая HTML.

strip_tags () не является хорошим способом обработки ввода для отображения HTML. В прошлом у него были проблемы с безопасностью, так как парсеры браузера на самом деле намного сложнее в интерпретации того, чем может быть тег, чем вы думаете. Вместо этого htmlspecialchars () - почти всегда правильная вещь, поэтому, если кто-то введет знак «меньше», он на самом деле получит буквальный знак «меньше» и не обнаружит, что половина его текста загадочно исчезает.

(*: в любом случае, как общий подход к решению проблем внедрения. Естественно, существуют специфичные для домена проверки, которые стоит выполнять в определенных полях, и есть полезные задачи очистки, которые можно выполнять, например, удаление всех управляющих символов из переданных значений. Но это не то, что большинство PHP-кодеров подразумевает под очисткой.)

5 голосов
/ 22 августа 2009

Если вы говорите о дезинфекции вывода, я бы порекомендовал хранить содержимое в вашей базе данных в его полной, неэкранированной форме, а затем экранировать его ( htmlspecialchars или что-то еще), когда вы выводите данные, Таким образом, у вас есть больше возможностей для вывода. См. этот вопрос для обсуждения очистки / экранирования содержимого базы данных.

С точки зрения хранения в postgres, используйте pg_escape_string для каждой переменной в запросе, чтобы экранировать кавычки и вообще защищать от внедрения SQL.

Edit:

Мои обычные шаги для хранения данных в базе данных и последующего их получения:

  1. Вызвать функцию экранирования данных базы данных (pg_escape_string, mysql_escape_string и т. Д.), Чтобы экранировать каждую входящую переменную $ _GET, используемую в вашем запросе. Обратите внимание, что использование этих функций вместо добавочных косых черт приводит к отсутствию лишних косых черт в тексте при сохранении в базе данных.

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

3 голосов
/ 22 августа 2009

Вы должны очистить все запросы, а не только POST как GET.

Вы можете использовать функцию htmlentities () , функцию preg_replace () с регулярным выражением или фильтровать по приведению:

<?
$id = (int)$_GET['id'];
?>

[] s

2 голосов
/ 22 августа 2009

Проведите дезинфекцию ваших входов в соответствии с тем, куда они идут.

  • Если вы отображаете его (на странице или в качестве значения поля ввода), используйте htmlspecialchars и / или str_replace.
  • Если вы используете его как другой тип, разыграйте его.
  • Если вы включите его в SQL-запрос, удалите его, используя соответствующую функцию, возможно, удалите HTML-теги, если вы хотите, чтобы они были полностью удалены (что не совпадает с escape-).

То же самое для POST или даже данных из вашей БД, поскольку данные внутри вашей БД обычно не должны быть экранированы.

Две вещи, которые вы должны проверить:

  1. Кодирование вашего ввода в сравнении с вашими PHP-скриптами / выходными данными / таблицей БД
  2. Если у вас включен [magic_quotes_gpc][1], вам следует либо отключить его (когда это возможно), либо stripslashes() GET, POST и COOKIE. magic_quotes_gpc устарела, вам следует очистить данные, которыми вы манипулируете, в зависимости от использования этих данных.
...