Избежать только того, что необходимо, это возможно? - PullRequest
7 голосов
/ 20 июля 2009

Я работаю с командой разработчиков на сайте. Сайт будет использовать классы. Я отвечаю за создание слоя доступа к данным для классов. Существует понимание того, что весь пользовательский ввод будет экранирован после извлечения (из сообщения или получения). Имея небольшой контроль над уровнем ввода (если я лично не проверяю код каждого), я подумал, что было бы неплохо добавить экранирование и на моем конце (прямо перед тем, как он попадет в базу данных). Проблема в том, что я не знаю, как использовать mysql_real_escape_string без добавления еще больше слешей.

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

Есть предложения?

Ответы [ 3 ]

7 голосов
/ 20 июля 2009

Рассматривали ли вы не экранирование данных до тех пор, пока оно не достигнет уровня доступа к данным? Я спрашиваю, потому что есть некоторые ошибки с подходом, который использует ваша команда:

  • Если вам необходимо отобразить данные формы для пользователя (например, чтобы повторно отобразить форму с сообщением об ошибке из-за сбоя проверки), вам необходимо отключить данные (поскольку ' не является особенным для HTML) и затем повторно экранируйте данные (потому что < особенный). Если вам нужно отобразить данные формы для пользователя , извлеченного из базы данных , вы не должны выполнять этот шаг удаления (потому что он был выполнен базой данных, когда данные были сохранены), но все же должен сделать шаг выхода HTML. Если вы допустили ошибку и сделали неправильную процедуру, вы повредили данные или, что еще хуже, создали проблемы с безопасностью.
  • Вы можете решить проблему с различными форматами из разных источников, решив, что все данные, передаваемые вокруг вашего приложения, будут экранированы. Таким образом, ваш уровень доступа к данным будет повторно экранировать данные при получении их из базы данных. Но, поскольку различным частям приложения требуется немного (или полностью) разных выходов, это быстро приводит к бессмысленной бессмысленной удаленной работе. Получить данные из базы данных, экранировать их, удалить их, экранировать их для HTML, вывести их.
  • Ваш код обработки внешнего интерфейса должен иметь глубокие знания вашей базы данных. Например, что означает \' для вашей базы данных? Как должен ' или \ сбежать - если вообще? Если вы когда-нибудь измените свой движок базы данных или даже измените его настройки, они могут измениться. И тогда у вас есть куча кодов, которые можно найти или удалить. Пропуск единственного escape / de-escape может привести к внедрению SQL.
  • Кроме того, вы можете извлечь эти знания из базы данных из внешнего кода, если слой базы данных выполнит цикл удаления / выхода из цикла для преобразования стандартной escape-последовательности вашего приложения в базу данных. Но это выглядит довольно глупо!

Есть и другой способ: пусть любой слой, которому нужны экранированные данные, избежит его самого. Данные всегда передаются между слоями в необработанном, неэкранированном виде. Таким образом, ваш уровень доступа к данным делает все экранирование базы данных. Ваш выходной код HTML делает все экранирование HTML. Когда вы решите, что хотите сгенерировать PDF-файл, ваш PDF-код делает все экранирование PDF.

  • Теперь, когда вы выполняете вывод формы, становится ясно, что делать: всегда HTML экранирует данные. Неважно, откуда это. Никогда не бегите из бегства.
  • Теперь нет смысла убегать / убегать, так как все передается необработанным. Экранируется только при необходимости.
  • Ваш интерфейсный код не заботится о реализации уровня доступа к данным. Уровень доступа к данным хранит и возвращает любую произвольную строку.
  • В вашем приложении есть только одно место, чтобы убедиться, что у вас нет проблем с SQL-инъекцией.
  • Вы можете легко использовать функции драйвера базы данных, такие как заполнители. Тогда даже вашему уровню доступа к данным не нужно знать о требованиях к каждой базе данных; драйвер базы данных обрабатывает его.
7 голосов
/ 20 июля 2009

Нет способа, которым вы могли бы добавить автоматическое решение о выходе или нет, если вы не знаете, был ли экранирован ввод. Вы можете попытаться проанализировать его, но он никогда не будет хорошим, и вы встретите двойные пары с обратной косой чертой и тому подобное.

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

Редактировать: Забыли это:

Имея небольшой контроль над вводом уровень (если я лично не рассматриваю код каждого)

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

0 голосов
/ 20 июля 2009

Если бы я был на вашем месте, я не был бы достаточно ленив, чтобы не просматривать код каждого. Даже если вы не проверяете возможность экранирования пользовательского ввода, вы все равно можете захотеть посмотреть, эффективно ли выполнен их код. Или, может быть, это не вы делаете обзор, но кто-то должен это делать.

Я испытал почти аналогичную настройку не так давно, когда мы разделили задачи по слоям. Один работал над моделью, я работал над контроллером, а другой работал над представлениями. Поскольку мы настолько доверяли всем, что чужой код будет работать так, как мы ожидали, мы не стали пересматривать код другого до того времени, когда нам нужно было объединить их. В результате мы обнаружили неэффективный код в модели в конце разработки. И это было не просто неэффективно, это не сработало! Из-за этого нам пришлось пересмотреть огромные куски кода, которые стоили нам больше времени.

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

Другое дело ... так как вы используете PHP, почему бы не использовать хороший фреймворк? Большинство доступных фреймворков поставляются с собственным DAL, где вам больше не нужно беспокоиться об экранировании ввода в базу данных (ну, не так уж много). Фреймворки должны сделать это за вас.

Кроме того, вы можете посмотреть «подготовленные заявления».

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