Нужно ли экранировать значения, поступающие непосредственно из базы данных? - PullRequest
1 голос
/ 16 сентября 2011

Нужно ли экранировать / фильтровать данные, поступающие из базы данных? Даже если указанные данные уже были "экранированы" один раз (в тот момент, когда они были вставлены в базу данных).

Например, допустим, я разрешаю пользователям отправлять сообщения в блоге через форму с вводом заголовка и вводом textarea.

Злонамеренный пользователь отправляет сообщение в блоге

title: Attackposttitle');DROP TABLE posts;--

textarea: Хахаха, обнажил ваш сайт!

Теперь, когда это вставляется в мою базу данных, я собираюсь экранировать его с помощью mysql_real_escape_string, но как только оно попадет в базу данных, я позже сошлюсь на эти данные в своем приложении php blog примерно так:

sql="SELECT posttitle FROM posts WHERE id=50";
$posttitlearray = mysql_fetch_array(mysql_query($sql));

Это то, что меня беспокоит, что если я, например, выполню следующий запрос, чтобы получить содержание сообщения:

sql="SELECT postcontent FROM posts WHERE posttitle=$posttitlearray[posttitle]";

Теоретически я не впрыскиваю sql? IE, я не эффективно запускаю запрос:

sql="SELECT postcontent FROM posts WHERE posttitle=Attackposttitle');DROP TABLE posts;--";

Или данные "Attackposttitle '); DROP TABLE; -" продолжают экранироваться после их попадания в базу данных?

Нужно ли мне постоянно избегать его так:

sql="SELECT postcontent FROM posts WHERE posttitle=msql_real_escape_string($posttitlearray[posttitle])";

Или данные безопасны после первоначального сброса при первой вставке в базу данных?

Спасибо, стек!

Ответы [ 3 ]

3 голосов
/ 16 сентября 2011

Он не продолжает экранироваться после помещения в базу данных. Тебе снова придется сбежать.

$sql="SELECT postcontent FROM posts WHERE posttitle='".mysql_real_escape_string($posttitlearray[posttitle])."'";
2 голосов
/ 23 сентября 2011

Значение должно быть экранировано каждый раз непосредственно перед вставкой в ​​SQL-запрос. Не по волшебным соображениям безопасности, а просто для того, чтобы убедиться, что синтаксис результирующего запроса в порядке.

Экранирование струн звучит для многих как волшебный звук, что-то вроде щита от какой-то таинственной опасности, но на самом деле это не волшебствоЭто просто способ включить специальные символы, обрабатываемые запросом.

Лучше всего было бы просто посмотреть, что на самом деле делает экранирование.Скажем, входная строка:

Attackposttitle');DROP TABLE posts;--

после экранирования:

Attackposttitle\');DROP TABLE posts;--

фактически она экранирована только от одной косой черты.Это единственное, что вам нужно гарантировать - когда вы вставите строку в запрос, синтаксис будет в порядке!

insert into posts set title = 'Attackposttitle\');DROP TABLE posts;--'

В этом нет ничего волшебного, как щит безопасности или что-то в этом роде, просто нужно убедиться, что результирующий запрос имеет правильный синтаксис! (конечно, если это не так, он может бытьэксплуатируется)

Затем анализатор запросов просматривает последовательность \ 'и знает, что это все еще переменная, а не конец ее значения.Он удалит обратную косую черту, и в базе данных будет сохранено следующее:

Attackposttitle');DROP TABLE posts;--

, которое точно соответствует значению, введенному пользователем.И это именно то, что вы хотели иметь в базе данных !!

Так что это означает, что если вы извлекаете эту строку из базы данных и хотите снова использовать ее в запросе, вам нужно снова ее экранировать , чтобы убедиться, что результирующий запрос имеет правильный синтаксис .

Но, в вашем примере, очень важно упомянуть директиву 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);
}

Вторая причина, почему это зло, заключается в том, что нет ничего подобного "универсальному цитированию" .При цитировании вы всегда цитируете текст для определенного вывода , например:

  1. строковое значение для запроса mysql
  2. like выражениедля запроса mysql
  3. html code
  4. json
  5. mysql регулярное выражение
  6. php регулярное выражение

Для каждого случая вынужно различное цитирование, потому что каждое использование присутствует в различном синтаксическом контексте.Это также подразумевает, что цитирование должно производиться не при вводе в PHP, а при конкретном выводе !Вот почему такие функции, как magic_quotes_gpc, не работают ( никогда не забывайте обращаться с ним, или, что еще лучше, убедитесь, что он выключен !!! ).

Итак, какими методамииспользовать для цитирования в этих конкретных случаях?(Не стесняйтесь поправлять меня, могут быть более современные методы, но они работают для меня)

  1. mysql_real_escape_string($str)
  2. mysql_real_escape_string(addcslashes($str, "%_"))
  3. htmlspecialchars($str)
  4. json_encode() - только для utf8!Я использую свою функцию для iso-8859-2
  5. mysql_real_escape_string(addcslashes($str, '^.[]$()|*+?{}')) - вы не можете использовать preg_quote в этом случае, потому что обратный слэш будет экранирован два раза!
  6. preg_quote()
0 голосов
/ 16 сентября 2011

Попробуйте использовать переменные связывания. что избавит от необходимости полностью скрывать ваши данные.

http://php.net/manual/en/function.mssql-bind.php

Единственным недостатком является то, что вы ограничены использованием их с хранимыми процедурами на SQL-сервере, в другой базе данных вы можете использовать их для всего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...