#php #security #input
#php #Безопасность #ввод
Вопрос:
Я не уверен, как я действительно могу сделать безопасный ввод со строками.
Например, я получил:
$id = intval($_POST['id']);
$name = $_POST['name'];
$sql->query("UPDATE customers SET name = " . $sql->escape_string($name) . " WHERE id = {$id}");
Я уверен, что $name
это недостаточно защищено. Как я могу защитить его, чтобы предотвратить уязвимость XSS?
С уважением, cyclone.
Ответ №1:
Защита XSS должна выполняться на стороне вывода, а не на вашем носителе данных (базе данных). База данных не знает, где отображаются данные. Если сохраняемые данные являются текстовыми (как в этом случае с $name
), вы должны хранить их как текст, а не как HTML.
Если вы действительно хотите избавиться от возможных HTML-тегов, используйте $name = strip_tags($_POST['name'])
, но правильный способ предотвратить ошибки XSS — экранировать его на стороне вывода с htmlspecialchars
помощью (или htmlentities
) .
Если вы хотите использовать функции фильтрации PHP, вот пример, который удаляет HTML-теги:
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
Документы PHP:
Комментарии:
1. Что вы имеете в виду? О, и я также слышал о функциях фильтрации в PHP5.
2. Итак, если я правильно понимаю: мне нужно использовать
$name = strip_tags($_POST['name']);
, чтобы быть защищенным?3. @cyclone это один из уродливых способов добиться этого, но правильный способ — использовать
htmlentities()
илиhtmlspecialchars()
при отображении имени на HTML-странице.4. Что, если я хочу отобразить, например, что-то вроде
<3
? Затемhtmlspecialchars
он будет удален.5.
strip_tags
иFILTER_SANITIZE_STRING
удалит его.htmlspecialchars
преобразует тоamp;<3
, что будет отображаться как<3
в вашем браузере.
Ответ №2:
XSS не имеет ничего общего с вашей базой данных, ну, в основном.
Межсайтовый скриптинг (XSS) — это тип уязвимости компьютерной безопасности, обычно встречающийся в веб-приложениях, который позволяет злоумышленникам внедрять клиентский скрипт на веб-страницы, просматриваемые другими пользователями.
Может быть, вы имеете в виду SQL-инъекцию? Вы уже избежали ввода, вы можете дополнительно очистить его, приведя переменные к соответствующим типам.
Комментарии:
1. постоянный XSS = сохраненные уязвимости (например, в базе данных). @op: фильтруйте ваш ввод перед сохранением и экранируйте ваш вывод при отображении.
2. Да, я также имел в виду SQL-инъекцию. Итак, чтобы быть уверенным: это достаточно защищено от SQL-инъекций?
3. @cyclone Было бы более безопасно, если бы вы использовали подготовленные инструкции php.net/manual/en/pdo.prepared-statements.php
Ответ №3:
Когда дело доходит до безопасности, я всегда думаю, что имеет смысл быть как можно более строгим, но не более. Если вы можете определить, что имя недопустимо, прежде чем вставлять его в базу данных, почему бы тогда не отклонить его?
Есть ли у кого-нибудь имя с тегом HTML в нем? Вероятно, нет. Но как насчет апострофа или дефиса? Определенно.
Имея это в виду, давайте посмотрим, как будет выглядеть допустимое имя:
- Буквы
- Пробелы
- Апострофирует
- Дефисы
- Точки (для инициалов)
Теперь, когда вы определили, как выглядит допустимое имя, отклоните все имена, которые не соответствуют этому критерию:
/* If the input contains any character that is not a capital letter,
a lowercase letter, whitespace, a hyphen, a period, or an apostrophe,
then preg_match with return true. */
if (preg_match('/[^A-Za-zs-.']/', $_POST['Name']))
{
// Invalid name
}
else
{
// Valid name
}
Комментарии:
1. Довольно неудобно предварительно сопоставлять каждый $_POST, который содержит некоторую строку.
2. Отлично. Посмотрите на какой-нибудь большой PHP-проект и посмотрите, как они защищают сообщения — они не preg_match каждой строки. Это хорошее решение, но неудобно, не так ли?
3. Если вы прекрасно разбираетесь в регулярных выражениях, вы готовы править миром.
4. Хороший момент. Но регулярные выражения на данный момент мне трудно понять. ^^
Ответ №4:
Предоставленный вами код направлен на защиту от повторных атак с использованием SQL-инъекций, а не XSS-атак, которые являются совершенно разными.
SQL-инъекция — это когда злоумышленник использует SQL-код для получения данных в вашей базе данных или из нее способом, который вы не планировали. Правильное экранирование строки SQL, как вы делаете, смягчит это. (тем не менее, я не знаю из вашего кода, к какому классу $sql
относится объект, и поэтому я не могу сказать вам, достаточна ли $sql->escape_string()
защита; Я предполагаю, что это так, но для уверенности нужно знать больше об объекте)
Атаки XSS («межсайтовый скриптинг») — это когда злоумышленнику удалось внедрить свой HTML, CSS или Javascript-код на вашу страницу, что привело к последующей загрузке страницы, отображаемой с нежелательным содержимым.
Злоумышленник может добиться этого различными способами, но обычно вы должны убедиться, что любые данные, вводимые пользователями, которые будут отображаться на вашем сайте, должны быть отфильтрованы, чтобы они не содержали HTML, CSS или JS-код. Если это произойдет, вам следует либо полностью удалить код, либо использовать экранирование HTML ( htmlentities()
функция PHP и аналогичные), чтобы убедиться, что он отображается безопасным образом.
В настоящее время вы вообще ничего не делаете, чтобы предотвратить это в коде, который вы нам показали, но в равной степени из кода, который вы нам показали, мы не можем сказать, нужно ли защищать эти данные от XSS-атак. Это будет зависеть от того, когда и как он используется.
Ответ №5:
Для очистки записей перед их помещением в sql я всегда делаю это:
trim($string) // Cuts off spacing and newlines in the beginning or end
И
mysql_real_escape_string($string) // prevents SQL injections
Примечание: Любая часть строки sql-запроса может быть mysql_real_escape_string’d . Вся строка не обязательно должна быть; до тех пор, пока какая-то часть экранируется, запрос будет защищен от внедрения.