Санитарная обработка данных пользователя в GET с помощью PHP
Как вы очищаете данные в $_GET -переменных с помощью PHP?
Я очищаю только одну переменную в GET strip_tags
, Я не уверен, следует ли мне санировать все или нет, потому что в прошлый раз при передаче данных в Postgres эту проблему легче всего было решить с помощью pg_prepare
,
4 ответа
Как вы очищаете данные в $_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-кодеров подразумевает под очисткой.)
Если вы говорите о дезинфекции вывода, я бы порекомендовал сохранить содержимое в вашей базе данных в его полной, неэкранированной форме, а затем экранировать его ( htmlspecialchars или что-то еще), когда вы выводите данные, таким образом, у вас есть больше возможностей для вывода. Смотрите этот вопрос для обсуждения очистки / экранирования содержимого базы данных.
С точки зрения хранения в postgres, используйте pg_escape_string для каждой переменной в запросе, чтобы избежать кавычек и вообще защитить от внедрения SQL.
Редактировать:
Мои обычные шаги для хранения данных в базе данных и последующего их получения:
Вызвать функцию экранирования данных базы данных (pg_escape_string, mysql_escape_string и т. Д.), Чтобы экранировать каждую входящую переменную $_GET, используемую в вашем запросе. Обратите внимание, что использование этих функций вместо добавочных косых черт приводит к отсутствию лишних косых черт в тексте при хранении в базе данных.
Когда вы возвращаете данные из базы данных, вы можете просто использовать htmlspecialchars для любых выводимых данных, не нужно использовать полоски, так как не должно быть лишних слешей.
Вы должны дезинфицировать все запросы, а не только POST as GET.
Вы можете использовать функцию htmlentities (), функцию preg_replace() с регулярным выражением или фильтровать по приведению:
<?
$id = (int)$_GET['id'];
?>
[] 'S
Санитаризируйте ваши данные в соответствии с тем, куда они идут.
- Если вы отображаете его (на странице или в качестве значения поля ввода), используйте
htmlspecialchars
и / илиstr_replace
, - Если вы используете его как другой тип, разыграйте его.
- Если вы включаете его в SQL-запрос, избегайте его, используя соответствующую функцию, возможно, удалите HTML-теги, если вы хотите, чтобы они были полностью удалены (что не совпадает с escape-кодом).
То же самое для POST или даже данных из вашей БД, поскольку данные внутри вашей БД обычно не должны быть экранированы.
Две вещи, которые вы должны проверить:
- Кодирование вашего ввода против ваших PHP скриптов / выходных данных / таблицы БД
- Если у вас есть
[magic_quotes_gpc][1]
включен, вы должны либо отключить его (когда вы можете) илиstripslashes()
GET, POST и COOKIE значения.magic_quotes_gpc
устарела, вы должны очистить данные, которыми вы манипулируете, в зависимости от использования этих данных.
Используйте встроенную функцию PHP filter_var()
с FILTER_SANITIZE_STRING
фильтр.
Пример: https://www.w3schools.com/php/filter_sanitize_string.asp