Да, во втором запросе вы также должны экранировать строку.
Для многих людей экранирование строки звучит как волшебство, что-то вроде щита от какой-то таинственной опасности, но на самом деле в этом нет ничего волшебного,Это просто способ включить специальные символы, обрабатываемые запросом.
Лучше всего было бы просто посмотреть, что на самом деле делает экранирование.Скажем, входная строка:
'); DROP `table` --
после экранирования:
\'); DROP `table` --
фактически она экранирована только от одной косой черты.Это единственное, что вам нужно гарантировать - когда вы вставите строку в запрос, синтаксис будет в порядке!
insert into table set column = '\'); DROP `table` --'
В этом нет ничего магического, как защита от опасностей или что-то в этом роде, просто нужно убедиться, что результирующий запрос имеет правильный синтаксис! (конечно, если нет, он может бытьэксплуатируется)
Затем анализатор запросов просматривает последовательность \ 'и знает, что это все еще переменная, а не конец ее значения.Он удалит обратную косую черту, и в базе данных будет сохранено следующее:
'); DROP `table` --
, которое точно соответствует значению, введенному пользователем.И это именно то, что вы хотели иметь в базе данных !!
Так что это означает, что если вы извлекаете эту строку из базы данных и хотите снова использовать ее в запросе, вам нужно снова ее экранировать , чтобы убедиться, что результирующий запрос имеет правильный синтаксис .
Но, в вашем примере, очень важно упомянуть директиву magic_quotes_gpc
!
Эта функция не используетсявсе пользовательский ввод автоматически (gpc - _GET, _POST и _COOKIE). Это злая функция, созданная для людей, которые не знают о внедрении SQL.Это зло по двум причинам. Первая причина заключается в том, что тогда вы должны различать регистр своего первого и второго запроса - в первом вы не убегаете, а во втором вы делаете.Большинство людей делают либо отключение «функции» (я предпочитаю это решение), либо сначала отключение пользовательского ввода, а затем повторение при необходимости.Код unescape может выглядеть следующим образом:
function stripslashes_deep($value)
{
return is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
}
if (get_magic_quotes_gpc()) {
$_POST = stripslashes_deep($_POST);
$_GET = stripslashes_deep($_GET);
$_COOKIE = stripslashes_deep($_COOKIE);
}
Вторая причина, почему это зло, заключается в том, что нет ничего похожего на "универсальное цитирование" .При цитировании вы всегда цитируете текст для определенного вывода , например:
- строковое значение для запроса mysql
like
выражениедля запроса MySQL - HTML-код
- JSON
- MySQL регулярное выражение
- PHP регулярное выражение
Для каждого случая вынужно различное цитирование, потому что каждое использование присутствует в различном синтаксическом контексте.Это также подразумевает, что цитирование должно производиться не при вводе в PHP, а при конкретном выводе !По этой причине такие функции, как magic_quotes_gpc
, не работают ( никогда не забывайте обращаться с ним, или, что еще лучше, убедитесь, что он выключен !!! ).
Итак, какими методамииспользовать для цитирования в этих конкретных случаях?(Не стесняйтесь поправлять меня, могут быть более современные методы, но они работают для меня)
mysql_real_escape_string($str)
mysql_real_escape_string(addcslashes($str, "%_"))
htmlspecialchars($str)
json_encode()
- только для utf8!Я использую свою функцию для iso-8859-2 mysql_real_escape_string(addcslashes($str, '^.[]$()|*+?{}'))
- вы не можете использовать preg_quote в этом случае, потому что обратный слэш будет экранирован два раза! preg_quote()