Когда лучше всего дезинфицировать пользовательский ввод? - PullRequest
51 голосов
/ 29 августа 2008

Пользователь не заслуживает доверия. Никогда не доверяйте ненадежным данным пользователя. Я понимаю. Тем не менее, мне интересно, когда наилучшее время для дезинфекции ввода. Например, сохраняете ли вы слепой пользовательский ввод и затем очищаете его, когда к нему обращаются / используют, или вы немедленно очищаете ввод и затем сохраняете эту «очищенную» версию? Может быть, есть и другие подходы, которые у меня нет, в дополнение к этим. Я больше склоняюсь к первому методу, потому что к любым данным, полученным от пользовательского ввода, все равно следует подходить осторожно, поскольку «очищенные» данные могут все еще быть по незнанию или случайно опасными. В любом случае, какой метод люди считают лучшим и по каким причинам?

Ответы [ 14 ]

21 голосов
/ 02 сентября 2013

К сожалению, почти никто из участников никогда не понимает, о чем они говорят. В прямом смысле. Только @Kibbee удалось сделать это прямо.

Эта тема посвящена санитарной обработке. Но правда в том, что такая вещь, как широкомасштабная «дезинфекция общего назначения», о которой все так стремятся поговорить, просто не существует.

Существует миллион различных носителей , каждый из которых требует своего собственного отдельного форматирования данных. Более того - даже один определенный носитель требует различного форматирования для своих частей . Скажем, форматирование HTML бесполезно для JavaScript, встроенного в страницу HTML. Или форматирование строк бесполезно для чисел в запросе SQL.

На самом деле, такая «дезинфекция как можно раньше», как предлагается в большинстве проголосовавших ответов, просто невозможна . Поскольку нельзя просто сказать, в какой части среды или части данных будут использоваться данные. Скажем, мы готовимся защищаться от «sql-инъекций», избегая всего, что движется. Но упс! - некоторые обязательные поля не были заполнены, и мы должны заполнить данные обратно в форму вместо базы данных ... со всеми добавленными слешами.

С другой стороны, мы старательно избежали всего «пользовательского ввода» ... но в запросе sql у нас нет кавычек, так как это число или идентификатор. И никакая «дезинфекция» никогда не помогала нам.

С третьей стороны - хорошо, мы сделали все возможное для очистки ужасного, ненадежного и презренного «пользовательского ввода» ... но в каком-то внутреннем процессе мы использовали эти самые данные без какого-либо форматирования (как мы уже сделали все возможное! ) - и упс! получили инъекцию второго порядка во всей своей красе.

Итак, с точки зрения использования в реальной жизни, единственный правильный путь будет

  • форматирование, а не какая-либо "санация"
  • прямо перед употреблением
  • в соответствии с определенными правилами среды
  • и даже соблюдение подчиненных правил, необходимых для различных частей этого носителя.
18 голосов
/ 29 августа 2008

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

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

Редактировать: в целом, проводить санитарную обработку на ранней стадии и проводить санитарную обработку в любое время, когда вы потеряли из виду данные даже на секунду (например, «Сохранить файл» -> «Открыть файл»)

17 голосов
/ 20 августа 2010

Я очищаю свои пользовательские данные так же, как Раду ...

  1. Первая сторона клиента, использующая как регулярные выражения, так и контроль над допустимыми символами ввод в заданные поля формы с использованием javascript или jQuery, привязанных к событиям, таким как OnChange или OnBlur, который удаляет любой запрещенный ввод, прежде чем он может быть даже Отправлено. Поймите, однако, что это действительно имеет эффект только пользователи знают, что данные будут проверяться и на стороне сервера. Это больше предупреждения, чем любая другая защита.

  2. Во-вторых, и я редко вижу, как это делается в наши дни, что первая проверка была Выполнено на стороне сервера, чтобы проверить расположение отправляемой формы. Разрешить отправку формы только со страницы, которую вы назначили действительной местоположение, вы можете убить сценарий, прежде чем вы даже прочитали в любых данных. Предоставляется, что само по себе недостаточно, так как хороший хакер со своим собственным сервером может «подделать» как домен, так и IP-адрес, чтобы он показывал вашему скрипту, что он идет из правильного местоположения формы.

  3. Далее, и мне даже не нужно было говорить этого, но всегда, и я имею в виду ВСЕГДА , беги ваши скрипты в режиме taint. Это заставляет вас не лениться и быть прилежным шаг № 4.

  4. Санитарно обработать пользовательские данные как можно скорее, используя правильные регулярные выражения, соответствующие данные, которые ожидаются от любого данного поля в форме. Не используйте ярлыки, такие как печально известный ' волшебный рог единорога ', который прорвется сквозь ваши проверки на заражение ... или же вы можете просто отключить проверку зараженности в первую очередь для всего хорошего это сделает для вашей безопасности. Это все равно что дать психопату острый нож горло и говоришь: «Ты действительно не сделаешь мне больно с этим».

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

  5. Последнее, это отфильтровать все попытки автоматической отправки роботами в эти дни, с система «человеческой аутентификации», такая как Captcha. Это достаточно важно в наши дни что я нашел время, чтобы написать свою собственную схему «человеческой аутентификации», которая использует фотографии и вход для «человека», чтобы ввести то, что они видят на картинке. Я сделал это, потому что Я обнаружил, что системы типа Captcha действительно раздражают пользователей (вы можете сказать по их Прищурившиеся глаза от попыток расшифровать искаженные буквы ... обычно заканчиваются и снова). Это особенно важно для сценариев, которые используют SendMail или SMTP для электронной почты, так как это фавориты для ваших голодных спам-ботов.

Чтобы подвести итог, я объясню это так же, как и своей жене ... ваш сервер похож на популярный ночной клуб, и чем больше у вас вышибалов, тем меньше у вас проблем в ночном клубе. У меня есть два вышибала за дверью (проверка на стороне клиента и проверка подлинности человеком), один вышибал прямо у двери (проверка правильности места отправки формы ... «Это действительно вы на этом ID») и еще несколько вышибал в Непосредственная близость к двери (запуск режима заражения и использование хороших регулярных выражений для проверки пользовательские данные).

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

Или в целом, как часто говорила моя мама: «Лучше быть в безопасности, чем сожалеть».

UPDATE:

Еще одна вещь, которую я делаю в эти дни, это Base64, кодирующая все мои данные, а затем шифрующая данные Base64, которые будут храниться в моих базах данных SQL. Для такого хранения требуется примерно треть общих байтов, но преимущества безопасности по моему мнению перевешивают дополнительный размер данных.

11 голосов
/ 30 августа 2008

Это зависит от того, какой вид санитарии вы делаете.

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

Для защиты от XSS-атак, вероятно, будет проще исправить данные перед их сохранением. Однако, как уже упоминалось, иногда приятно иметь точную копию того, что ввел пользователь, потому что, как только вы его измените, он потеряется навсегда. Почти слишком плохо, что нет надежного способа гарантировать, что ваше приложение выпускает только санированный HTML, как вы можете гарантировать, что вы не попадете под инъекцию SQL с помощью подготовленных запросов.

4 голосов
/ 29 августа 2008

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

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

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

3 голосов
/ 29 августа 2008

Рано хорошо, определенно, прежде чем пытаться разобрать его. Все, что вы собираетесь вывести позже или особенно передать другим компонентам (например, оболочке, SQL и т. Д.), Должно быть обработано.

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

Кроме того, убедитесь, что вы выполняете очистку от доверенного процесса - JavaScript / все, что на стороне клиента, хуже, чем бесполезное в плане безопасности / целостности. (Тем не менее, это может обеспечить лучший пользовательский опыт при раннем сбое - просто сделайте это в обоих местах.)

2 голосов
/ 19 июля 2010

Мое мнение состоит в том, чтобы дезинфицировать ввод пользователя как можно скорее на стороне клиента и сервера, я делаю это так

  1. (на стороне клиента), разрешить пользователю введите только определенные ключи в поле.
  2. (на стороне клиента), когда пользователь переходит в следующее поле с помощью onblur, проверьте введенный им ввод против регулярного выражения и замечать пользователя, если что-то не так.
  3. (на стороне сервера), снова протестируйте ввод, если поле должно быть INTEGER, проверьте это (в PHP вы можете использовать is_numeric ()), если поле имеет хорошо известный формат проверьте это с регулярным выражением, все другие (как текстовые комментарии), просто убежать от них. Если что-то вызывает подозрение, остановите выполнение скрипта и верните пользователю уведомление о том, что введенные им данные неверны.

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

2 голосов
/ 29 августа 2008

В Perl есть опция taint, которая считает весь пользовательский ввод "испорченным", пока он не будет проверен с помощью регулярного выражения. Испорченные данные можно использовать и передавать, но они портят любые данные, с которыми они соприкасаются, до тех пор, пока они не будут сохранены. Например, если пользовательский ввод добавляется к другой строке, новая строка также портится. По сути, любое выражение, содержащее испорченные значения, выведет испорченный результат.

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

Я не знаю другого языка, который имеет что-то вроде "испорченного", но его использование было очень зрелищным. Удивительно, как быстро распространяются испорченные данные, если вы не сразу их разобрали. Вещи, которые естественны и нормальны для программиста, такие как установка переменной на основе пользовательских данных или открытие файла, кажутся опасными и рискованными с включенным заражением. Таким образом, лучшая стратегия для достижения цели состоит в том, чтобы отвязаться, как только вы получите некоторые данные извне.

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

1 голос
/ 29 августа 2008

Я дезинфицирую свои данные прямо перед обработкой. Мне может понадобиться взять поля «Имя» и «Фамилия» и объединить их в третье поле, которое вставляется в базу данных. Я собираюсь очистить входные данные еще до того, как сделаю конкатенацию, чтобы не было ошибок обработки или вставки. Чем скорее, тем лучше. Даже использование Javascript на внешнем интерфейсе (в веб-настройке) идеально, потому что это произойдет без каких-либо данных, отправляемых на сервер с самого начала.

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

Конечно, это требует большой работы, но если данные важны, то это достойное вложение.

1 голос
/ 29 августа 2008

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

...