Какой процент моего времени будет потрачен на проверку пользовательского ввода во время веб-разработки? - PullRequest
7 голосов
/ 21 сентября 2008

Я новичок в разработке вещей в сети. До сих пор я трачу много времени (около 50%) на то, чтобы не допустить, чтобы плохие люди помещали такие вещи, как инъекции sql в мои формы ввода и проверяя их на стороне сервера. Это нормально?

Ответы [ 7 ]

9 голосов
/ 21 сентября 2008

@ Джереми - некоторые особенности PHP

Когда дело доходит до запросов к базе данных, всегда пытайтесь использовать подготовленные параметризованные запросы. Библиотеки mysqli и PDO поддерживают это. Это бесконечно безопаснее, чем использование экранирующих функций, таких как mysql_real_escape_string.

Да, mysql_real_escape_string - фактически просто функция экранирования строки. Это не волшебная пуля. Все, что он будет делать, это экранировать опасные символы, чтобы их можно было безопасно использовать в одной строке запроса. Однако, если вы не очистите свои входные данные заранее, вы будете уязвимы для определенных векторов атаки.

Представьте себе следующий SQL:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

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

1 OR 1=1

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

SELECT fields FROM table WHERE id = 1 OR 1=1

Какой прекрасный вектор SQL-инъекции.

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

Что касается htmlspecialchars (). Это собственное минное поле.

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

Во-первых, если вы находитесь внутри тега HTML, у вас серьезные проблемы. Посмотрите на

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

Мы уже находимся внутри тега HTML, поэтому нам не нужно <или> делать что-то опасное. Наш вектор атаки может быть просто javascript:alert(document.cookie)

Теперь результирующий HTML выглядит как

<img src= "javascript:alert(document.cookie)" />

Атака проходит прямо сквозь.

Становится хуже. Зачем? потому что htmlspecialchars кодирует только двойные кавычки, а не одинарные. Так что, если бы у нас было

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

Наш злой атакующий теперь может вводить совершенно новые параметры

pic.png' onclick='location.href=xxx' onmouseover='...

дает нам

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

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

Даже если вы используете htmlspecialchars ($ string) вне тегов HTML, вы по-прежнему уязвимы для векторов атак многобайтовой кодировки.

Самое эффективное, что вы можете сделать, это использовать комбинацию mb_convert_encoding и htmlentities следующим образом.

$str = mb_convert_encoding($str, ‘UTF-8′, ‘UTF-8′);
$str = htmlentities($str, ENT_QUOTES, ‘UTF-8′);

Даже это делает IE6 уязвимым из-за способа обработки UTF. Однако вы можете использовать более ограниченную кодировку, такую ​​как ISO-8859-1, пока не прекратится использование IE6.

8 голосов
/ 21 сентября 2008

Чтобы предотвратить атаки с использованием SQL-инъекций, просто выполняйте запросы с подготовленными инструкциями (точный способ зависит от вашей платформы). Как только вы это сделаете, вам больше никогда не придется беспокоиться об этом конкретном аспекте. Вам просто нужно использовать это везде .

Что касается общей проверки ввода, всегда полезно полагаться на общую базу для проверки необходимых полей, чисел и т. Д. Валидаторы ASP.Net, например, очень просты в использовании. Главное правило, которому вы должны следовать - не доверять клиентской стороне (javascript), чтобы сделать это за вас, так как это легко обойти. Всегда сначала делайте это на стороне сервера.

Особый случай, который нужно держать под своим радаром, - это когда вы разрешаете вводить расширенный контент, который может содержать html / javascript. Это может позволить злоумышленнику внедрить в ваши данные javascript, который будет вызывать код, который вы не контролируете при его рендеринге. не попробуйте ввести свой собственный код проверки. Ищите в Интернете бесплатный, проверенный, поддерживаемый код, который сделает это за вас. У Джеффа было несколько указаний на этот счет в одном из подкастов.

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

2 голосов
/ 21 сентября 2008

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

Вы не можете обеспечить реальную безопасность таким образом.

У вас должно быть несколько оболочек, которые затруднят создание небезопасного кода , если не невозможно. Например, подготовленные заявления. Но вы можете захотеть использовать ORM, такой как ActiveRecord в Ruby on Rails, или какой-то эквивалент в вашей среде.

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

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

2 голосов
/ 21 сентября 2008

Я рад, что вы заботитесь, чтобы защитить себя. Слишком многие не делают.

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

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

2 голосов
/ 21 сентября 2008

Нет. Это не нормально. Может быть, вам нужно:

  • Используйте компоненты прав, чтобы избежать SQL-инъекций (PreparedStatements в Java)
  • Создание компонента, который «фильтрует» сообщения, поступающие от пользователя (сервлет-фильтр в Java).

Любой современный язык поддерживает обе вещи.

С уважением

1 голос
/ 24 сентября 2008

Вы столкнулись с проблемой, которую можно решить только путем обобщения.

Попытайтесь определить общие типы проверки ввода, которые вам нужны

  • числовые / строковые значения / проверка регулярных выражений
  • диапазон / длина
  • экранирование специальных символов
  • проверка общих ключевых слов, которые вы не ожидаете в определенном контексте ('script', 'select', 'drop' ...) для черного списка

и систематически вызывайте их перед обработкой данных.

Все доступ к базе данных должен выполняться с подготовленными операторами и без объединения строки запроса.

Все выходные данные должны быть экранированы, так как вы не хотите хранить все экранированные данные в вашей базе данных.

Хороший внешний / социальный подход: идентифицируйте своих пользователей как можно лучше. Чем выше шанс быть идентифицированным, тем меньше они будут обманывать систему. Получите номер мобильного телефона, чтобы отправить код, проверить свою кредитную карту и т. Д.

1 голос
/ 21 сентября 2008

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

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

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

В более крупных приложениях, т. Е. Когда у вас много непрезентационного кода, это ненормально.

...