САМОСТОЯТЕЛЬНОЕ ОБУЧЕНИЕ ДЛЯ ВЕБ РАЗРАБОТЧИКОВ

SQL Учебник

SQL Главная SQL Введение SQL Синтаксис SQL SELECT SQL SELECT DISTINCT SQL WHERE SQL AND, OR, NOT SQL ORDER BY SQL INSERT INTO SQL Null SQL UPDATE SQL DELETE SQL SELECT TOP SQL MIN() и MAX() SQL COUNT(), AVG() и ... SQL LIKE SQL Подстановочный SQL IN SQL BETWEEN SQL Псевдонимы SQL JOIN SQL JOIN Внутри SQL JOIN Слева SQL JOIN Справа SQL JOIN Полное SQL JOIN Сам SQL UNION SQL GROUP BY SQL HAVING SQL Exists SQL Any, All SQL SELECT INTO SQL INSERT INTO SELECT SQL CASE SQL NULL SQL Хранимая SQL Комментарии SQL Operators

SQL База данных

SQL Создать БД SQL Откинуть БД SQL Резервная БД SQL Создать таблицу SQL Откинуть таблицу SQL Изменить таблицу SQL Ограничения SQL Не ноль SQL Уникальный SQL Первичный ключ SQL Внешний ключ SQL Проверить SQL По умолчанию SQL Индекс SQL Авто приращение SQL Даты SQL Представление SQL Инъекция SQL Хостинг SQL Типы данных

SQL Справочник

SQL Ключевые слова MySQL Функции SQL Server функции MS Access функции SQL Краткий справочник

SQL Примеры

SQL Примеры SQL Викторина SQL Упражнения SQL Сертификат

SQL Инъекция



Инъекция

SQL инъекция - это метод инъекции кода, который может разрушить вашу базу данных.

SQL инъекция является одним из наиболее распространенных методов взлома веб-страниц.

SQL инъекция - это размещение вредоносного кода в SQL инструкции с помощью ввода веб страницы.


в Веб странице

Инъекция SQL обычно происходит, когда вы просите пользователя ввести данные, например его имя пользователя/идентификатор пользователя, и вместо имени/идентификатора пользователь дает вам инструкцию SQL, которую вы неосознанно запускаете к своей базе данных.

Посмотрите на следующий пример, который создает оператор SELECT, добавляя переменную (txtUserId) в строку select. Переменная извлекается из пользовательского ввода (getRequestString):

Пример

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

Остальная часть этой главы описывает потенциальные опасности использования пользовательского ввода в инструкции SQL.


Инъекция, основанная на 1=1, всегда true

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

Если нет ничего, что могло бы помешать пользователю ввести "Неправильный" ввод, пользователь может ввести какой-то "Умный" ввод, например:

UserId:

Тогда оператор SQL будет выглядеть следующим образом:

SELECT * FROM Users WHERE UserId = 105 OR 1=1;

Приведенный выше SQL является допустимым и возвращает все строки из таблицы "Users", так как OR 1=1 всегда истинно.

Разве приведенный выше пример выглядит опасным? Что делать, если таблица "Users" содержит имена и пароли?

Приведенная выше инструкция SQL во многом совпадает с этой:

SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1;

Хакер может получить доступ ко всем именам пользователей и паролям в базе данных, просто вставив 105 OR 1=1 в поле ввода.



Инъекция, основанная на ""="", всегда true

Вот пример входа пользователя на веб сайте:

Пользователь:

Пароль:

Пример

uName = getRequestString("username");
uPass = getRequestString("userpassword");

sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass + '"'

Результат

SELECT * FROM Users WHERE Name ="Щипунов Андрей" AND Pass ="мой_пароль"

Хакер может получить доступ к именам пользователей и паролям в базе данных, просто вставив " OR ""=" в текстовое поле пользователя или парол:

Пользователь:

Пароль:

Код на сервере создаст допустимую инструкцию SQL, подобный этому:

Результат

SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

Приведенный выше SQL является допустимым и возвращает все строки из таблицы "Users", так как OR"="" всегда имеет значение TRUE.


Инъекция на основе пакетных инструкций SQL

Большинство баз данных поддерживают пакетный инструкций SQL.

Пакет инструкций SQL - это группа из двух или более инструкций SQL, разделенных точкой с запятой.

Приведенная ниже инструкция SQL вернет все строки из таблицы "Users", а затем удалит таблицу "Suppliers".

Пример

SELECT * FROM Users; DROP TABLE Suppliers

Посмотрите на следующий пример:

Пример

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;

И следующие входные данные:

Пользователь:

Допустимая инструкция SQL будет выглядеть следующим образом:

Результат

SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers;

Используйте параметры для защиты

Для защиты веб сайта от SQL инъекции можно использовать параметры SQL.

Параметры SQL - это значения, которые добавляются в SQL запрос во время выполнения контролируемым образом.

Пример ASP.NET Razor

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);

Обратите внимание, что параметры представлены в инструкции SQL маркером @.

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

Пример другой

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);

Примеры

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

SELECT STATEMENT IN ASP.NET:

txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();

INSERT INTO STATEMENT IN ASP.NET:

txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();

INSERT INTO STATEMENT IN PHP:

$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();