Как я могу избежать атак SQL-инъекций?
Вчера я говорил с разработчиком, и он упомянул что-то об ограничении вставки в поле базы данных, например, строки, такие как --
(минус минус).
В том же типе я знаю, что это хороший подход к удалению HTML-символов, таких как <
, >
и т.д. Не --
. Это правда? Должен ли я беспокоиться о --
, ++
? Это больше похоже на миф или старые вещи?
Update
Большое спасибо за все ответы, это легко понять, потому что я немного новичок в этом.
Ну, точнее, в этом случае наше обсуждение было посвящено и веб-сайту С# ASP.NET MVC, который мы разрабатываем, поэтому там есть сложная форма регистрации с важной информацией, поэтому я не уверен, использует ли MVC Linq для интерфейс с базой данных уже поставляется с такой защитой или нет. Поэтому, если кто-то может дать некоторые намеки на это, было бы здорово.
Еще раз спасибо
Ответы
Ответ 1
Правильный способ избежать атак SQL Injection - это не просто запретить некоторые пробные символы, а скорее использовать параметризованный SQL. Здесь вы можете найти хорошие статьи по теме параметризированного SQL:
http://www.codinghorror.com/blog/archives/000275.html
http://www.codeproject.com/KB/database/ParameterizingAdHocSQL.aspx
Теперь, когда вы упомянули, что работаете с ASP.net, я могу дать вам некоторые ссылки, которые специально посвящены SQL Injection в ASP.
http://en.csharp-online.net/ASP.NET_Security_Hacks%E2%80%94Avoiding_SQL_Injection
http://www.codeproject.com/KB/aspnet/SQL_Injection_.aspx?msg=3209511
Вот более общая статья о том, как сделать ваш ASP более безопасным:
http://www.codeproject.com/KB/web-security/Securing_ASP_NET_Apps.aspx
И, конечно, статья MSDN по SQL-инъекции:
http://msdn.microsoft.com/en-us/library/ms998271.aspx
Ответ 2
SQL-инъекция представляет собой высокий риск для безопасности большинства веб-сайтов, которые позволяют пользователям скручивать параметры в оператор, который выполняется в базе данных.
Простым примером может быть:
Поле ввода "Имя: _________
"SELECT * FROM tblCustomer WHERE Name = '" + nameInputField + "'"
Итак, если я набираю "Боб", мы имеем
"SELECT * FROM tblCustomer WHERE Name = 'Bob'"
Но если я наберу "'; DROP TABLE tblCustomer", мы получим более зловещий
"SELECT * FROM tblCustomer WHERE Name = ''; DROP TABLE tblCustomer"
Существует множество способов избежать этих проблем, и многие из них встроены в любой язык, который вы используете, поэтому вместо того, чтобы думать обо всех хитроумных возможностях ";", "-", "/*" и т.д., попробуйте и используйте то, что уже существует.
Выскажите, какой язык вы используете, и я уверен, что мы можем сказать вам, как избежать этих атак.
Ответ 3
Он говорил о атаке SQL Injection, что совершенно правильно в том, что он сказал.
Проблема заключается не в таких данных, существующих в базе данных, а в передаче входных данных непосредственно в базу данных без их очистки.
Не очищая его, если кто-то переходит в строку, заканчивающуюся на ;
, они могут последовать за ней тем, что они хотят (select * from sys.objects
, например) или что-то более злонамеренное, например, отбрасывание некоторых таблиц.
Трудно полностью защитить, но если вы используете хорошую библиотеку БД из своего кода и следуете известным практикам, например, используя пареметровые запросы, вы ограничите возможный ущерб.
Храните как можно больше --
в своей базе данных, но не передавайте это через вашу базу данных, не проходя процесс очистки (здесь важна хорошая библиотека БД - она должна содержать кавычки и другие потенциально опасные вход).
Ответ 4
Нет ничего опасного в том, что вы вставляете строку, содержащую --
в базу данных.
Опасно вставлять что-либо в таблицу базы данных, которая поступает непосредственно из пользовательского ввода без его обработки, в противном случае вы оставите себя открытым для атаки SQL-инъекций. Пример. Кодер позволяет пользователю вводить свое имя в поле, а пользователь вводит:
Joe '); drop table users; commit transaction; --
а затем кодер помещает это в свою базу данных MySQL так:
conn.execute("insert into users (username) values ('" + userInput + "')");
Boom Пользователь удалил таблицу пользователей (при условии, что логин базы данных имеет права делать это, а это не должно, но это другая тема), поскольку кодер не обеспечивал что строка от пользователя была экранирована правильно, и поэтому она была отправлена непосредственно в механизм БД, и злоумышленник посмеется.: -)
Используйте любые инструменты, обеспечиваемые вашей средой, чтобы обеспечить правильное экранирование строк. Например, JDBC использует для этого класс PreparedStatement
. Большинство сред будут иметь что-то подобное.
Ответ 5
Использовать параметризованные запросы. Эти запросы представляют переменные в качестве заполнителя в SQL, например select * from person where name = ?
. После создания SQL-запроса вы устанавливаете значения параметров в запросе. Параметрированные запросы гарантируют, что все, что было заменено заполнителем, не будет считаться частью инструкции SQL.
См. статью Джеффа Этвуда для хорошего обзора параметризованных запросов.
Ответ 6
Это не опасно, если вы правильно избегаете данных при выполнении INSERT/UPDATE/...
И экранирование HTML-символов НЕ - хороший подход. Представьте, что вы написали функцию, которая ускользает от таких символов, и вы сохранили некоторый экранированный текст в базе данных. Затем вы заметите, что ваша функция не удаляла '<', поэтому вы меняете функцию... теперь, что происходит с записями, которые уже находятся в базе данных? - Их '<' символы остаются неизмененными.
Таким образом, НИКОГДА избегать текста перед сохранением его в базе данных (конечно, сбежать от SQL-запроса). Экранирование должно происходить, когда страница HTML/XML/... создается из текста, то есть после запроса исходного текста из базы данных!
Ответ 7
Попробуйте экранировать символы
Это особенно относится к тем, кто использует процедурный php, применяет некоторые real_escape_string при проверке из таблицы базы данных, например
$a = $_POST['username'];
$b = $_POST['password'];
$c = mysqli_query($cone, "select * from member where (username = '".mysqli_real_escape_string($cone, $a)."' && password = '".mysqli_real_escape_string($cone,$b)."')");
if(mysqli_num_rows($c)==1){
$_SESSION['username'] = $a;
header("Location:member.php");
exit();
}else{
$unam_error = "Wrong Username or password";
}