SQL Injection
Инъекции SQL
Внедрение SQL — это метод внедрения кода, который может разрушить базу данных.
SQL инъекции является одним из наиболее распространенных веб-технологий взлома.
SQL-инъекция — это размещение вредоносного кода в инструкциях SQL с помощью ввода веб-страницы.
SQL на веб-страницах
Инъекции SQL обычно происходит, когда вы спрашиваете пользователя для ввода, как и их имя пользователя/логин, и вместо имени/ID, пользователь дает вам инструкцию SQL, что вы будете несознательно запускать в вашей базе данных.
Посмотрите на следующий пример, который создает инструкцию SELECT, добавив переменную (ткстусерид) в строку SELECT. Переменная извлекается из пользовательского ввода (жетрекуестстринг):
Пример
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
В оставшейся части этой главы описываются потенциальные опасности использования пользовательского ввода в инструкциях SQL.
SQL-инъекции на основе 1 = 1 всегда верно
Посмотрите на пример выше снова. Первоначальной целью кода было создание инструкции SQL для выбора пользователя с заданным идентификатором пользователя.
Если нет ничего, чтобы запретить пользователю ввод "неправильный" вход, пользователь может ввести некоторые "умные" вход, как это:
UserId:
Затем инструкция SQL будет выглядеть следующим:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
SQL выше является допустимым и вернет все строки из таблицы «Users», так как Или 1 = 1 всегда верно.
Выглядит ли приведенный выше пример опасным? Что делать, если таблица "Users" содержит имена и пароли?
Приведенная выше инструкция SQL так же, как это:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Хакер может получить доступ ко всем именам пользователей и паролям в базе данных, просто вставив 105 или 1 = 1 в поле ввода.
Встраивание SQL на основе "" = "" всегда верно
Ниже приведен пример входа пользователя на веб-узле:
Username:
Password:
Пример
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Результат
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Хакер может получить доступ к именам пользователей и паролям в базе данных, просто вставив "OR" "=" в текстовое поле имя пользователя или пароль:
User Name:
Password:
Код на сервере создаст допустимую инструкцию SQL, как это:
Результат
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
SQL выше является допустимым и вернет все строки из таблицы "Users", так как или "" = "" всегда верно.
Встраивание SQL-кода на основе пакетных инструкций SQL
Большинство баз данных поддерживают пакетную инструкцию SQL.
Пакет инструкций SQL — это группа из двух или более инструкций SQL, разделенных точками с запятой.
Приведенная ниже инструкция SQL вернет все строки из таблицы "Users", а затем удалит таблицу "поставщики".
Пример
SELECT * FROM Users; DROP TABLE Suppliers
Посмотрите на следующий пример:
Пример
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
И следующие входные данные:
User id:
Допустимая инструкция SQL будет выглядеть так:
Результат
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Использовать параметры SQL для защиты
Для защиты веб-узла от внедрения SQL-кода можно использовать параметры SQL.
Параметры SQL — это значения, которые добавляются в SQL-запрос во время выполнения, контролируемым образом.
Пример ASP.NET бритвы
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 в ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();
Вставить в заявление в 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();
Вставить в инструкцию в 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();