Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
SQL-инъекции (SQL injection, SQLi, внедрение SQL-кода) часто называют самым распространённым методом атак на веб-сайты. Их широко используют хакеры и пентестеры в применении к веб-приложениям. В списке уязвимостей OWASP Топ-10 присутствуют SQL-инъекции, которые, наряду с другими подобными атаками, находятся на первом месте среди угроз, с которыми сталкиваются веб-проекты.
Несмотря на то, что SQL-инъекции существуют уже более 20 лет, этот метод атаки на веб-проекты всё ещё можно успешно применить для взлома тех веб-сайтов и приложений, создатели которых не реализовали в них соответствующие защитные механизмы.
Этот материал рассчитан на абсолютных новичков, на тех, кто ничего не знает о SQL-инъекциях. Начнём мы с разбора основ, в которых необходимо ориентироваться перед разговором о SQLi. А именно, сначала мы поговорим о реляционных базах данных. Потом — о SQL, и о формировании SQL-запросов. И наконец — о том, как работают SQL-инъекции, и о том, почему они так опасны для веб-приложений.
Прежде чем говорить о SQL (и о SQL-инъекциях), нам надо познакомиться с реляционными базами данных (БД).
В реляционной БД хранятся взаимосвязанные данные, которые часто размещаются в таблицах. Каждая таблица содержит набор столбцов и строк.
Вот, например, таблица, которая называется
Таблица users
Эта таблица содержит три столбца (их ещё называют атрибутами):
Беглый взгляд на эту таблицу позволяет сделать вывод о том, что в ней, вероятно, хранятся учётные данные пользователей некоей системы. После того, как пользователь вводит имя и пароль в форме аутентификации, веб-приложение сверяет эти данные с вышеприведённой таблицей. Именно после того, как данные пользователя найдены (или не найдены) в таблице, приложение узнаёт о том, следует ли, например, дать этому пользователю возможность работать с ресурсами проекта, предназначенными только для зарегистрированных пользователей.
Это — лишь простой пример. Реляционные базы данных обычно представляют собой гораздо более сложные конструкции, в состав которых входит множество таблиц, в каждой из которых имеется много атрибутов и записей (иногда их количество исчисляется миллионами). Таблицы могут быть связаны с другими таблицами.
На этом мы закончим разговор о реляционных базах данных, так как этого достаточно для того чтобы разобраться в том, о чём речь пойдёт дальше.
SQL (Structured Query Language, язык структурированных запросов) — это язык, который предназначен для работы с реляционными БД. С его помощью, взаимодействуя с базой данных, можно просматривать, добавлять, обновлять, удалять данные.
Веб-приложение взаимодействует с базой данных, пользуясь SQL-выражениями. Каждое такое выражение начинается с некоей команды.
Вот пример, который поможет нам разобраться в синтаксисе подобных выражений:
Здесь SQL-выражение начинается с команды
За командой
Если вы хоть немного понимаете английский, то ключевое слово
И, наконец,
Если «перевести» вышеприведённое SQL-выражение на обычный язык, то получится следующее:
Давайте теперь сделаем вышеописанное SQL-выражение немного интереснее:
В данном случае мы указываем на то, что хотим получить лишь запись, в поле
Пока то, о чём мы тут говорим, может показаться не таким уж и интересным. Но это — лишь до тех пор, пока мы не добрались до следующего раздела, посвящённого SQL-инъекциям.
Теперь, в завершение этого раздела, хочу рассказать о некоторых наиболее часто используемых командах и ключевых словах SQL. Для того чтобы понять то, о чём речь пойдёт дальше, знать все эти команды и ключевые слова вам необязательно, но я настоятельно рекомендую вам поближе с ними познакомиться после того, как вы дочитаете эту статью.
Теперь, разобрав основы, переходим к нашей основной теме.
Как уже было сказано, SQL-инъекции — это разновидность атаки на веб-приложения. В ходе проведения такой атаки делается попытка модификация SQL-выражения, которое приложение отправляет базе данных. Выполняется атака путём подстановки особым образом подготовленных данных в поля ввода, которые может заполнять пользователь.
Для того чтобы вышесказанное стало бы понятнее — рассмотрим пример.
Предположим, имеется форма аутентификации, которая предлагает пользователю ввести в её поля имя и пароль. Приложение предоставляет пользователям доступ к закрытым ресурсам после проверки введённых данных. Если говорить точнее, то приложение отправляет к базе данных SQL-запрос, направленный на проверку наличия там тех данных, которые ввёл пользователь. Используемое при этом SQL-выражение может выглядеть примерно так:
Если вы внимательно читали статью, то вы без труда поймёте эту конструкцию. Она извлекает из таблицы
Теперь представьте, что вместо того, чтобы ввести в поле формы имя, пользователь вводит туда следующее:
А затем, в качестве пароля, вводит произвольный набор символов (то, что будет введено в поле для пароля, значения не имеет; ниже мы с этим разберёмся).
После этого приложение формирует такое SQL-выражение:
База данных, обрабатывая такой запрос, вернёт любую запись из таблицы
Но выражение
Кроме того, так как два дефиса в SQL используются для оформления однострочных комментариев, всё, что идёт после них, окажется закомментированным, то есть — соответствующие команды базой данных обрабатываться не будут. Если выделить ту часть SQL-запроса, которая будет выполнена базой данных, то получится следующее:
База данных, обрабатывая этот запрос, вернёт список записей, не являющихся NULL-значениями, и, в результате, веб-приложение даст пользователю доступ к закрытым ресурсам.
Мы рассмотрели лишь один пример SQL-инъекции. Но существует и множество других способов внедрения SQL-кода в веб-приложения. Если вы хотите посмотреть больше примеров — рекомендую взглянуть на этот материал, опубликованный на сайте Netsparker, и на этот материал с сайта PortSwigger.
Если вы хотите попрактиковаться в деле выполнения атак на веб-приложения с использованием SQL-инъекций — попытайте удачу в варгейме Natas на OverTheWire. Если вы не знаете о том, что это такое — вот моя статья об этом.
Как вы защищаете свои веб-проекты от SQL-инъекций?
Несмотря на то, что SQL-инъекции существуют уже более 20 лет, этот метод атаки на веб-проекты всё ещё можно успешно применить для взлома тех веб-сайтов и приложений, создатели которых не реализовали в них соответствующие защитные механизмы.
Этот материал рассчитан на абсолютных новичков, на тех, кто ничего не знает о SQL-инъекциях. Начнём мы с разбора основ, в которых необходимо ориентироваться перед разговором о SQLi. А именно, сначала мы поговорим о реляционных базах данных. Потом — о SQL, и о формировании SQL-запросов. И наконец — о том, как работают SQL-инъекции, и о том, почему они так опасны для веб-приложений.
Реляционные базы данных
Прежде чем говорить о SQL (и о SQL-инъекциях), нам надо познакомиться с реляционными базами данных (БД).
В реляционной БД хранятся взаимосвязанные данные, которые часто размещаются в таблицах. Каждая таблица содержит набор столбцов и строк.
Вот, например, таблица, которая называется
users
.Таблица users
Эта таблица содержит три столбца (их ещё называют атрибутами):
Id
, User
, Password
. Строки таблицы называют записями. В нашей таблице имеется две записи.Беглый взгляд на эту таблицу позволяет сделать вывод о том, что в ней, вероятно, хранятся учётные данные пользователей некоей системы. После того, как пользователь вводит имя и пароль в форме аутентификации, веб-приложение сверяет эти данные с вышеприведённой таблицей. Именно после того, как данные пользователя найдены (или не найдены) в таблице, приложение узнаёт о том, следует ли, например, дать этому пользователю возможность работать с ресурсами проекта, предназначенными только для зарегистрированных пользователей.
Это — лишь простой пример. Реляционные базы данных обычно представляют собой гораздо более сложные конструкции, в состав которых входит множество таблиц, в каждой из которых имеется много атрибутов и записей (иногда их количество исчисляется миллионами). Таблицы могут быть связаны с другими таблицами.
На этом мы закончим разговор о реляционных базах данных, так как этого достаточно для того чтобы разобраться в том, о чём речь пойдёт дальше.
SQL
SQL (Structured Query Language, язык структурированных запросов) — это язык, который предназначен для работы с реляционными БД. С его помощью, взаимодействуя с базой данных, можно просматривать, добавлять, обновлять, удалять данные.
▍Основные SQL-выражения
Веб-приложение взаимодействует с базой данных, пользуясь SQL-выражениями. Каждое такое выражение начинается с некоей команды.
Вот пример, который поможет нам разобраться в синтаксисе подобных выражений:
SELECT * FROM users;
Здесь SQL-выражение начинается с команды
SELECT
, которая позволяет извлекать данные из БД.За командой
SELECT
идёт символ звёздочки (*
). Тут он олицетворяет все столбцы таблицы. Это значит, что мы хотим извлечь данные из всех столбцов.Если вы хоть немного понимаете английский, то ключевое слово
FROM
в дополнительных пояснениях не нуждается.И, наконец,
users
— это имя таблицы, из которой мы хотим извлечь данные.Если «перевести» вышеприведённое SQL-выражение на обычный язык, то получится следующее:
Получить данные всех столбцов из таблицы users.
Давайте теперь сделаем вышеописанное SQL-выражение немного интереснее:
SELECT * FROM users WHERE user=’Fyodor’;
В данном случае мы указываем на то, что хотим получить лишь запись, в поле
user
которой имеется имя пользователя Fyodor
. Все остальные записи таблицы нас не интересуют.Пока то, о чём мы тут говорим, может показаться не таким уж и интересным. Но это — лишь до тех пор, пока мы не добрались до следующего раздела, посвящённого SQL-инъекциям.
▍Команды и ключевые слова SQL
Теперь, в завершение этого раздела, хочу рассказать о некоторых наиболее часто используемых командах и ключевых словах SQL. Для того чтобы понять то, о чём речь пойдёт дальше, знать все эти команды и ключевые слова вам необязательно, но я настоятельно рекомендую вам поближе с ними познакомиться после того, как вы дочитаете эту статью.
SELECT
: получение данных из таблицы.INSERT INTO
: добавление записи в таблицу.UPDATE
: обновление содержимого записи таблицы.DELETE
: удаление записи из таблицы.CREATE TABLE
: создание новой таблицы.WHERE
: фильтрация записей по заданному условию.ORDER BY
: сортировка данных, полученных с помощьюSELECT
.
Теперь, разобрав основы, переходим к нашей основной теме.
SQL-инъекции
Как уже было сказано, SQL-инъекции — это разновидность атаки на веб-приложения. В ходе проведения такой атаки делается попытка модификация SQL-выражения, которое приложение отправляет базе данных. Выполняется атака путём подстановки особым образом подготовленных данных в поля ввода, которые может заполнять пользователь.
Для того чтобы вышесказанное стало бы понятнее — рассмотрим пример.
▍Простая атака с использованием SQL-инъекции
Предположим, имеется форма аутентификации, которая предлагает пользователю ввести в её поля имя и пароль. Приложение предоставляет пользователям доступ к закрытым ресурсам после проверки введённых данных. Если говорить точнее, то приложение отправляет к базе данных SQL-запрос, направленный на проверку наличия там тех данных, которые ввёл пользователь. Используемое при этом SQL-выражение может выглядеть примерно так:
SELECT * FROM users WHERE username=’ProvidedUsername’ and password=’ProvidedPassword’;
Если вы внимательно читали статью, то вы без труда поймёте эту конструкцию. Она извлекает из таблицы
users
все записи, фильтруя их по имени пользователя (поле username
) ProvidedUsername
и по паролю (password
) ProvidedPassword
. Если в таблице имеется запись, удовлетворяющая этим двум условиям — это значит, что пользователь ввёл верные имя и пароль. Приложение, в результате, даст такому пользователю доступ к закрытым ресурсам.Теперь представьте, что вместо того, чтобы ввести в поле формы имя, пользователь вводит туда следующее:
a’ OR 1=1;--
А затем, в качестве пароля, вводит произвольный набор символов (то, что будет введено в поле для пароля, значения не имеет; ниже мы с этим разберёмся).
После этого приложение формирует такое SQL-выражение:
SELECT * FROM users WHERE username=’a’ OR 1=1;--’ and password=’RandomPass’;
База данных, обрабатывая такой запрос, вернёт любую запись из таблицы
users
, в поле username
которой находится a
. Запись будет возвращена и в том случае, если истинным является выражение 1=1
.Но выражение
1=1
всегда истинно, поэтому этот запрос приведёт к получению всех записей из таблицы.Кроме того, так как два дефиса в SQL используются для оформления однострочных комментариев, всё, что идёт после них, окажется закомментированным, то есть — соответствующие команды базой данных обрабатываться не будут. Если выделить ту часть SQL-запроса, которая будет выполнена базой данных, то получится следующее:
SELECT * FROM users WHERE username=’a’ OR 1=1;--’ and password=’RandomPass’;
База данных, обрабатывая этот запрос, вернёт список записей, не являющихся NULL-значениями, и, в результате, веб-приложение даст пользователю доступ к закрытым ресурсам.
Итоги
Мы рассмотрели лишь один пример SQL-инъекции. Но существует и множество других способов внедрения SQL-кода в веб-приложения. Если вы хотите посмотреть больше примеров — рекомендую взглянуть на этот материал, опубликованный на сайте Netsparker, и на этот материал с сайта PortSwigger.
Если вы хотите попрактиковаться в деле выполнения атак на веб-приложения с использованием SQL-инъекций — попытайте удачу в варгейме Natas на OverTheWire. Если вы не знаете о том, что это такое — вот моя статья об этом.
Как вы защищаете свои веб-проекты от SQL-инъекций?