Как предотвратить атаки инъекций кода в PHP?
Я немного смущен, в PHP есть так много функций, и некоторые используют это, некоторые используют это. Некоторые люди используют: htmlspecialchars()
, htmlentities()
, strip_tags()
т.д.
Что является правильным и что вы, ребята, обычно используете?
Правильно ли это (посоветуйте мне лучше, если таковые имеются):
$var = mysql_real_escape_string(htmlentities($_POST['username']));
Эта строка может предотвратить атаку MySQL и XSS-атаку?
Кстати, есть ли другие вещи, которые мне нужно обратить внимание, кроме атаки XSS и MySQL-инъекций?
РЕДАКТИРОВАТЬ
Заключить:
Если я хочу вставить строку в базу данных, мне не нужно использовать htmlentities
, просто используйте mysql_real_escape_string
. При отображении данных используйте htmlentities()
, это то, что вы все подразумеваете?
Суммировать:
-
mysql_real_escape_string
используемый при вставке в базу данных -
htmlentities()
используемый при выводе данных на веб-страницу -
htmlspecialchars()
используется когда? -
strip_tags()
используется, когда? -
addslashes()
используется когда?
Может ли кто-нибудь заполнить вопросительный знак?
Ответы
Ответ 1
-
mysql_real_escape_string
используемый при вставке в базу данных -
htmlentities()
используемый при выводе данных на веб-страницу -
htmlspecialchars()
используется когда? -
strip_tags()
используется, когда? -
addslashes()
используется когда?
htmlspecialchars() используется когда?
htmlspecialchars
примерно такая же, как htmlentities
. Разница: кодировка символов.
Оба управления закодировать символы, такие как <
, >
, &
и так далее используется для открытия меток и т.д. htmlentities
также закодировать символы из других языков, таких как умлауты евро-символы и тому подобные. Если ваши сайты UTF, используйте htmlspecialchars()
, в противном случае используйте htmlentities()
.
strip_tags() используется, когда?
htmlspecialchars
/entities
кодируют специальные символы, поэтому они отображаются, но не интерпретируются. strip_tags
УДАЛЯЕТ их.
На практике это зависит от того, что вам нужно делать.
Пример: вы закодировали форум и предоставили пользователям текстовое поле, чтобы они могли публиковать материалы. Злоумышленники просто пытаются:
pictures of <a href="javascript:void(window.setInterval(function () {window.open('http://evil.com');}, 1000));">kittens</a> here
Если вы ничего не сделаете, будет отображаться ссылка, и жертва, которая нажимает на ссылку, получает много всплывающих окон.
Если вы htmlentity/htmlspecialchar свой вывод, текст будет там как есть. Если вы strip_tag, оно просто удаляет теги и отображает их:
pictures of kittens here
Иногда вам может понадобиться смесь, оставляйте там теги, например <b>
(strip_tags
может оставлять определенные теги там). Это тоже небезопасно, поэтому лучше использовать библиотеку с полной версией для XSS.
addslashes
Чтобы процитировать старую версию руководства PHP:
Возвращает строку с обратными косыми чертами перед символами, которые должны быть указаны в запросах базы данных и т.д. Эти символы представляют собой одинарные кавычки ('), двойную кавычку ("), обратную косую черту() и NUL (байт NULL).
Пример использования addlashes() - это когда вы вводите данные в базу данных. Например, чтобы вставить имя O'reilly в базу данных, вам нужно будет его избежать. Он настоятельно рекомендовал использовать функцию escape-функции СУБД (например, mysqli_real_escape_string() для MySQL или pg_escape_string() для PostgreSQL), но если используемая СУБД не имеет функции эвакуации, а СУБД использует\для выхода из специальных символов, вы может использовать эту функцию.
Текущая версия написана по-разному.
Ответ 2
Кодировать данные только в том месте, где оно входит в систему, которое необходимо закодировать для — в противном случае вы столкнетесь с ситуациями, когда вы хотите манипулировать реальными данными.
Для SQL-инъекции - используйте связанные переменные, как описано в Как я могу предотвратить SQL-инъекцию в PHP? (он говорит о подготовленных операторах, но это привязка, которая дает вам защита, а не подготовка).
Для XSS - если вы пишете в HTML в точке, где указан HTML или текст. Используйте htmlentities в том месте, где вы создаете документ. Я бы не хотел хранить данные в этой форме в базе данных (за исключением, возможно, в системе с частой записью с редко читаемыми частотами, когда производительность и время доступа к ЦП/время доступа к диску становились и выдавались - тогда у меня была бы raw_ и html_ версия столбца... или просто используйте memcached или подобное).
Если вы позволяете пользователям вводить URL-адреса, вам нужно быть более осторожными, так как javascript:do_evil()
- это допустимый URI, который будет выполняться (например, как href для ссылки на ссылку или (в некоторых браузерах) src изображения который просто загружен).
Ответ 3
Я подумал над этим быстрым контрольным списком:
- Всегда используйте HTTPS, без HTTPS ваш сайт полностью незашифрован. И нет, клиентское шифрование вещей и отправка их не сработают, подумайте об этом. Недействительные сертификаты HTTPS также делают вас уязвимыми для атаки MITM. Просто используйте Let Encrypt, если вы не можете позволить себе сертификат.
- Всегда используйте
htmlspecialchars()
на любом выходе из вашего кода PHP, то есть, или содержит пользовательский ввод. Большинство шаблонных двигателей помогают вам сделать это легко. - Используйте флаг HTTP-only в
php.ini
чтобы предотвратить доступ скриптов к вашим файлам cookie. - Предотвращение проблем, связанных с сеансом
- Никогда не выставляйте пользователя
PHPSESSID
(идентификатор сеанса) за пределами файла cookie, если кто-то узнает идентификатор сеанса кого-то другого, он может просто использовать его для входа в свою учетную запись - Будьте очень осторожны с функцией "
Remember me
возможно, немного предупредите. - Обновить идентификатор сеанса при входе пользователя (или что-то подходящее)
- Таймаут неактивных сессий
- Никогда не доверяйте файлу cookie, он может быть изменен, удален, изменен и создан скриптом/пользователем в любой момент
- Предотвращение проблем, связанных с SQL
- Всегда используйте подготовленные заявления. Подготовленные утверждения заставляют вводить данные пользователя отдельно и предотвращают внедрение SQL
- Сделайте код, создавая исключение, когда он не работает. Иногда ваш SQL-сервер может быть по какой-то причине недоступен, библиотеки, такие как
PDO
игнорируют эту ошибку по умолчанию и регистрируют предупреждение в журналах. Это приводит к тому, что переменные, которые вы получаете из БД, равны нулю, в зависимости от вашего кода, это может вызвать проблему безопасности. - Некоторые библиотеки, такие как
PDO
подражают подготовленным операторам. Отключите это. - Используйте
UTF-8
в своих базах данных, она позволяет хранить практически любой символ и избегать связанных с кодированием атак - Никогда не связывайте ничего с вашим запросом. Такие вещи, как
$myquery = "INSERT INTO mydb.mytable(title) VALUES(". $user_input. ")"
значительной степени означают, что у вас есть огромный риск для SQL-инъекции.
- Храните загруженные файлы в случайных именах без расширения. Если пользователь загружает файл с расширением
.php
файла, то всякий раз, когда ваш код загружает этот файл, он выполняет его и позволяет пользователю выполнить какой-либо код - Убедитесь, что вы не уязвимы для атаки CSRF.
- Всегда обновляйте свою копию PHP для обеспечения последних исправлений безопасности и повышения производительности
Ответ 4
htmlspecialchars()
превращает &
, '
, "
, <
и >
в формат сущности HTML (&
htmlspecialchars()
"
и т.д.),
htmlentities()
превращает все применимые символы в их формат сущности HTML.
strip_tags()
удаляет все теги HTML и PHP.
И htmlspecialchars()
и htmlentities()
принимают необязательный параметр, указывающий, как обрабатывать кавычки. См. Руководство по PHP для специфики.
Функция strip_tags()
принимает необязательный параметр, указывающий, какие теги не следует удалять.
$var = strip_tags ($var, '<p><br />');
Функция strip_tags()
удалит даже недействительные теги HTML, что может вызвать проблемы. Например, strip_tags()
весь код, который, по его мнению, является тегом HTML, даже если его неправильное формирование, например
<b I forgot to close the tag.
Ответ 5
Вам нужно использовать mysql_escape_string() при вставке в базу данных и htmlentites при отображении HTML. Этого достаточно, если вы хотите предотвратить простую инъекционную атаку, но нет сомнений в многих других проблемах безопасности, о которых вам следует знать при разработке веб-приложения, еще одним важным из которых являются подделки с запросами на кросс-сайт.
Ответ 6
Я бы не использовал htmlentities() при вставке данных в базу данных или в запросе базы данных. Если данные в вашей базе данных хранятся как сущности, эти данные тогда полезны только для того, что понимает html-объекты.
Вам нужно использовать различные механизмы экранирования для разных типов вывода, например. SQL - mysql_real_escape_string(), HTML - htmlentities() или htmlspecialchars(), shell - escapeshellarg(). Это связано с тем, что символы, которые являются "опасными", различны для каждого из них - нет волшебного способа сделать любые данные безопасными для любого выходного носителя.
Ответ 7
Взгляните на этот сайт Консорциум безопасности PHP. Я нашел, что это хороший сайт для общего обзора безопасности PHP (включая SQL Injection и XSS).
Ответ 8
Я знаю, что это старый вопрос, но в наши дни самый проголосовавший ответ может вводить в заблуждение для новичков.
Начиная с 2017 года
-
Вы никогда не должны использовать mysql_real_escape_string. Даже mysqli_real_escape_string слишком слаб, чтобы защитить вашу базу данных от SQL-инъекций. Вместо этого вы должны использовать PDO и аналогичные методы. (см. это руководство)
-
XSS (здесь я имею в виду: strip_tags()
, addslashes()
, htmlspecialchars()
, htmlentities()
) - здесь самый проголосовавший ответ по-прежнему верен, но я бы предложил прочитать эта статья