TL; DR
- Приложение принимает ввод, в данном случае «Нэнси», не пытаясь - санировать ввод, например, экранируя специальные символы
school => INSERT INTO студентов VALUES ( «Нэнси» ); ВСТАВИТЬ 0 1
- SQL-инъекция происходит, когда вводом в команду базы данных манипулируют, чтобы - заставить сервер базы данных выполнить произвольную
школу SQL => INSERT INTO студентов VALUES ( 'Robert' );
DROP TABLE студенты ; - '); INSERT 0 1 DROP TABLE
- Студенческие записи сейчас ушли - могло быть и хуже!
школа => ВЫБРАТЬ * ОТ студентов ;
ОШИБКА : соотношению «студенты» вовсе не существует
ЛИНИЯ 1 : ВЫБРАТЬ * ОТ СТУДЕНТОВ ; ^
Это удаляет (удаляет) таблицу ученика.
( Все примеры кода в этом ответе выполнялись на сервере базы данных PostgreSQL 9.1.2. )
Чтобы было понятно, что происходит, давайте попробуем это с простой таблицей, содержащей только поле имени, и добавим одну строку:
школа => CREATE TABLE студентов ( название TEXT PRIMARY KEY );
ВНИМАНИЕ : CREATE TABLE / PRIMARY KEY будет создавать неявную индекс "students_pkey" для таблицы "студентов" CREATE TABLE
школы =>
INSERT INTO студентов ЗНАЧЕНИЯ ( 'Джон' ); ВСТАВИТЬ 0 1
Предположим, что приложение использует следующий SQL для вставки данных в таблицу:
INSERT INTO студентов ЗНАЧЕНИЯ ( 'Foobar' );
Заменить foobar
на настоящее имя студента. Обычная операция вставки будет выглядеть так:
- Вход: Nancy
школа => INSERT INTO студентов ЗНАЧЕНИЯ ( 'Нэнси' ); ВСТАВИТЬ 0 1
Когда мы запрашиваем таблицу, мы получаем это:
школа => ВЫБРАТЬ * ОТ студентов ;
имя
-------
Джон
Нэнси
( 2 ряда )
Что происходит, когда мы вставляем имя Little Bobby Tables в таблицу?
- вход: Роберт '); DROP TABLE студенты; -
школа => INSERT INTO студентов ЗНАЧЕНИЯ ( 'Роберт' ); DROP TABLE студенты ; - '); INSERT 0 1 DROP TABLE
Внедрение SQL здесь является результатом того, что имя студента завершает оператор и включает отдельную DROP TABLE
команду; две черты в конце ввода предназначены для закомментирования любого оставшегося кода, который в противном случае мог бы вызвать ошибку. Последняя строка вывода подтверждает, что сервер базы данных отбросил таблицу.
Важно отметить, что во время INSERT
операции приложение не проверяет ввод на наличие каких-либо специальных символов и поэтому позволяет вводить произвольный ввод в команду SQL. Это означает, что злонамеренный пользователь может вставить в поле, обычно предназначенное для ввода данных пользователем, специальные символы, такие как кавычки, а также произвольный код SQL, чтобы система базы данных выполнила его, следовательно, SQL- инъекция .
Результат?
школа => ВЫБРАТЬ * ОТ студентов ;
ОШИБКА : соотношению «студенты» вовсе не существует
ЛИНИЯ 1 : ВЫБРАТЬ * ИЗ СТУДЕНТОВ ; ^
SQL-инъекция является эквивалентом уязвимости удаленного выполнения произвольного кода в операционной системе или приложении. Потенциальное влияние успешной атаки с использованием SQL-инъекции нельзя недооценивать - в зависимости от системы базы данных и конфигурации приложения злоумышленник может использовать ее для потери данных (как в этом случае), получения несанкционированного доступа к данным или даже выполнения произвольный код на самой машине.
Как отмечалось в комиксе XKCD, одним из способов защиты от атак с использованием SQL-инъекций является очистка входных данных базы данных, например, экранированием специальных символов, чтобы они не могли изменить базовую команду SQL и, следовательно, не могли вызвать выполнение произвольного кода SQL. Если вы используете параметризованные запросы, например, SqlParameter
в ADO.NET, входные данные, как минимум, будут автоматически очищены для защиты от внедрения SQL.
Однако очистка входных данных на уровне приложений может не остановить более продвинутые методы внедрения SQL. Например, есть способы обойти mysql_real_escape_string
функцию PHP . Для дополнительной защиты многие системы баз данных поддерживают подготовленные операторы . При правильной реализации в бэкэнде подготовленные операторы могут сделать внедрение SQL невозможным, обрабатывая ввод данных как семантически отдельный от остальной части команды.