Я новичок в разработке вещей в Интернете. До сих пор я трачу много времени (50% или около того), чтобы попытаться помешать плохим людям вкладывать такие вещи, как sql-инъекция, в мои входные формы и проверять его на стороне сервера. Это нормально?
Какой процент моего времени будет потрачен на выполнение пользовательской вводной верификации во время веб-разработки?
Ответ 1
@Jeremy - некоторые особенности PHP
Когда дело доходит до запросов к базе данных, всегда старайтесь использовать подготовленные параметризованные запросы. Библиотеки mysqli
и PDO
поддерживают это. Это бесконечно безопаснее, чем использование escaping-функций, таких как 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 не снизится.
Ответ 2
Чтобы предотвратить атаки SQL-инъекции, просто выполняйте свои запросы с помощью подготовленных инструкций (точный способ будет зависеть от вашей платформы). Как только вы это сделаете, вам больше не придется беспокоиться об этом конкретном аспекте. Вам просто нужно использовать это везде.
Что касается общей проверки ввода, всегда полезно полагаться на общую базу для проверки необходимых полей, чисел и т.д. Валидаторы ASP.Net очень просты в использовании, например. Одно эмпирическое правило, которому вы должны следовать, - не доверять клиентской стороне (javascript), чтобы сделать это для вас, так как легко обойти это. Всегда делайте это сначала на стороне сервера.
Особый случай, который нужно держать под вашим радаром, - это когда вы разрешаете вводить богатый контент, который может содержать html/javascript. Это позволяет злоумышленнику вводить javascript в ваши данные, которые будут вызывать код, который вы не контролируете при его рендеринге. Do not попытайтесь свернуть собственный код проверки. Найдите в Интернете бесплатный, проверенный, запрограммированный код, который сделает это за вас. В этом отношении у Джеффа было несколько указателей в одном из подкастов.
Как только вы автоматизируете код проверки ввода, время, затраченное на его выполнение, должно быть напрямую связано со сложностью ваших бизнес-правил. Итак, как правило: держите их простыми.
Ответ 3
Нет. Это не нормально. Возможно, вам нужно:
- Используйте компоненты прав, чтобы избежать SQL Injection (PreparedStatements в Java)
- Создайте компонент, который "фильтрует" сообщения, поступающие от пользователя (сервлет-фильтр на Java).
Любой современный язык поддерживает обе вещи.
С уважением
Ответ 4
Я рад, что вы заботитесь о себе. Слишком много не делают.
Однако, как говорили другие, лучший выбор архитектуры заставит ваши проблемы уйти. Использование подготовленных операторов (большинство языков должно иметь поддержку для этого) приведет к удалению SQL-инъекций. Кроме того, со многими базами данных они приведут к значительно лучшей производительности. Обработка межсайтовых скриптовых атак более сложна. Но основная стратегия должна состоять в том, чтобы решить, как избежать пользовательского ввода, решить, где вы его избежите, и всегда делать это в одном месте. Не попадайте в ловушку, думая, что лучше! Постоянно делать это одним способом в одном месте будет достаточно, и вы избежите того, чтобы выяснить, какой из нескольких уровней экранирования вызывает определенную ошибку.
Или курс обучения тому, как создавать и поддерживать разумную архитектуру, имеет опыт. И более того, он размышляет о ваших плохих переживаниях. Поэтому обратите внимание на ваши текущие болевые точки (похоже, вы такие), и подумайте о том, что вы могли бы сделать по-другому, чтобы избежать их. Если у вас есть наставник, поговорите со своим наставником. Это не всегда поможет вам в этом проекте, но со следующей.
Ответ 5
Я вижу вашу проблему. Похоже, что у вас есть защитная логика , покрытая всей кодовой базой. И каждый раз, когда вы пишете потенциально опасный код, вы должны быть осторожны, чтобы включить все защиты. И каждый раз, когда появляется новая угроза, вы должны пройти все эти утверждения и убедиться, что они защищены.
Вы не можете сделать настоящую безопасность таким образом.
У вас должны быть какие-то обертки, которые делают создание небезопасного кода жестким, если это невозможно. Например, подготовленные заявления. Но вы можете использовать ORM, например, Ruby on Rails ActiveRecord или какой-то эквивалент в вашей структуре.
Для вывода и защиты XSS убедитесь, что по умолчанию .. Если вам действительно нужно вывести сгенерированный HTML для пользователя, вы сделаете это явно, и это будет легче проверить.
Для защиты CSRF попробуйте также найти общее решение. Как правило, он должен выполнять свою работу автоматически, без необходимости явно создавать токен проверки и вручную проверять его, отбрасывать или отклонять запрос.
Ответ 6
Просто заметка о подготовленных заявлениях. Прежде всего, вы должны попытаться использовать хранимые процедуры, если можете... они, вероятно, являются лучшим решением в большинстве случаев.
Во-вторых, они оба защищают вас от SQL-инъекции только до тех пор, пока вы не используете динамический SQL, то есть SQL, который записывает больше SQL и затем выполняет его. В этом случае они будут неэффективными - и поэтому будут храниться процедуры.
Относительно процента времени, которое вы тратите: валидация очень важна, и это требует некоторой мысли, если не какое-то время. Но процент зависит от того, насколько велика ваша заявка, нет? В очень маленьком приложении, скажем, только для регистрации бюллетеня, вполне возможно, что валидация занимает огромный процент вашего времени.
В более крупных приложениях, то есть где у вас много кода без представления, это не нормально.
Ответ 7
Вы столкнулись с проблемой, которая может быть решена только путем обобщения.
Попробуйте определить общие типы проверки ввода, которые вам нужны
- числовые/строковые значения/проверка регулярных выражений
- диапазон/длина
- экранирование специальных символов
- проверить общие ключевые слова, которых вы не ожидаете в определенном контексте ('script', 'select', 'drop'...) против черного списка
и систематически вызывать их перед обработкой данных.
Весь доступ к базе данных должен выполняться с помощью подготовленных операторов, а не для конкатенации строки запроса.
Все выходные данные должны быть экранированы, так как вы хотите сохранить все, что было экранировано в вашей базе данных.
Хороший внеполосный/социальный подход: идентифицируйте своих пользователей как можно лучше. Чем выше вероятность получить идентификацию, тем меньше они будут обманывать систему. Получите свой номер мобильного телефона, чтобы отправить код, проверить кредитную карту и т.д.