Это достаточно хорошо, чтобы избежать инъекции SQL?
mysql_real_escape_string(htmlentities (urlencode($_POST['postmessage'])));
Это достаточно хорошо, чтобы избежать инъекции SQL?
mysql_real_escape_string(htmlentities (urlencode($_POST['postmessage'])));
Я думаю, что вы путаете две проблемы безопасности: SQL injection и межсайтовый скриптинг (XSS).
Веб-сайт уязвим для SQL-инъекций, когда неправильно обработанный пользовательский ввод используется в SQL-запросе, который отправляется в базу данных SQL. Этот код, например, вводит уязвимость SQL-инъекции:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . $_POST['postmessage'] . "')");
Эту проблему легко устранить, если вы отменили ввод пользователя с помощью функции типа mysql_real_escape_string
:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string($_POST['postmessage']) . "')");
Это все, что вам нужно сделать, но сложная часть запоминает это для каждой части пользовательского ввода, которая используется в инструкции SQL.
Веб-сайт уязвим для межсайтового скриптинга, когда пользовательский ввод используется в HTML, который отправляется клиенту. Этот код, например, представляет уязвимость XSS:
echo "<div class='postmessage'>" . $_POST['postmessage'] . "</div>";
Уязвимость XSS устранена путем экранирования пользовательского ввода с помощью функции htmlspecialchars
:
echo "<div class='postmessage'>" . htmlspecialchars($_POST['postmessage']) . "</div>";
Опять же, это легко сделать, но легко забыть.
Обычно пользовательский ввод, который помещается в базу данных, которая будет использоваться при отправке HTML-кода позднее, сохраняется без изменений. То есть используется только mysql_real_escape_string
. Тем не менее, вы можете избежать ввода пользователем для предотвращения XSS, а затем выйти из XSS-безопасной строки, чтобы предотвратить SQL-инъекцию:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string(htmlspecialchars($_POST['postmessage'])) . "')");
Преимущество в том, что вам не нужно помнить о том, чтобы избегать значений из базы данных с помощью htmlspecialchars
, прежде чем записывать их в HTML. Недостатком является то, что некоторые значения могут быть экранированы с различными функциями. Например, имя пользователя, вероятно, будет экранировано с помощью htmlspecialchars
, но "postmessage" может разрешить BBcode, Markdown или подмножество HTML. Если вы избегаете всех входных данных, чтобы предотвратить XSS, тогда вам нужно будет unescape-значения из базы данных, например, htmlspecialchars_decode
.
Одна проблема заключается в том, что unescaping escape-строка не всегда возвращает исходную строку (unescape(escape($orig))
не обязательно совпадает с $orig
). Даже при использовании htmlspecialchars
и htmlspecialchars_decode
при использовании другого стиля кавычек это вызовет эту проблему. Другим примером является то, что если используется strip_tags
, информация удаляется безвозвратно; вы не сможете отменить strip_tags
. Таким образом, многие разработчики предпочитают использовать mysql_real_escape_string
только для сохранения значений в базе данных и htmlspecialchars
(или любого другого) для подготовки строки из базы данных, которая будет использоваться в HTML.
mysql_real_escape_string()
- единственный метод, который вам нужен здесь.
Вы не должны делать htmlentities()
или urlencode()
перед вставкой данных в вашу базу данных. Эти методы обычно представляют собой код, выполняемый во время рендеринга представления, которое вы предлагаете своим пользователям.
Лучший способ избежать внедрения SQL-кода - это использование подготовленных операторов.
Ресурсы:
На ту же тему:
Вы также должны убедиться, что используете "
вокруг места, где вы вставляете свой код.
Например, если вы делаете
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELECT * FROM user WHERE userid = '. $_POST['userid']);
mysql_real_escape_string ничего не поможет. Это потому, что $ _POST ['userid'] не окружен '.
Так что вы должны сделать
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELET * FROM user WHERE userid = \''. $_POST['userid'] .'\'');
вместо.
Таким образом, использование mysql_real_escape_string для ваших переменных не означает автоматически, что они безопасны в любом запросе.
Другой подход заключается в использовании подготовленных заявлений.
Да, но есть причина не использовать mysql_real_escape_string(). Во-первых, это боль типа. Во-вторых, вы должны помнить, чтобы использовать его каждый раз. В-третьих, это делает ваш код уродливым. В-четвертых, вы должны помнить, чтобы процитировать ваши строки. В-пятых, сложнее вставить капли в db таким образом.
Обучение PDO улучшит вашу жизнь в долгосрочной перспективе. Труднее учиться, чем просто использовать mysql_real_escape_string(), но долгосрочные выгоды перевешивают неудобства кривой обучения.