[Перевод] Первое знакомство с SQL-инъекциями

SQL-инъекции (SQL injection, SQLi, внедрение SQL-кода) часто называют самым распространённым методом атак на веб-сайты. Их широко используют хакеры и пентестеры в применении к веб-приложениям. В списке уязвимостей OWASP Топ-10 присутствуют SQL-инъекции, которые, наряду с другими подобными атаками, находятся на первом месте среди угроз, с которыми сталкиваются веб-проекты.

Несмотря на то, что SQL-инъекции существуют уже более 20 лет, этот метод атаки на веб-проекты всё ещё можно успешно применить для взлома тех веб-сайтов и приложений, создатели которых не реализовали в них соответствующие защитные механизмы.

9fpdmkeuxuvljkvpxb9jhcj-h1y.png

Этот материал рассчитан на абсолютных новичков, на тех, кто ничего не знает о SQL-инъекциях. Начнём мы с разбора основ, в которых необходимо ориентироваться перед разговором о SQLi. А именно, сначала мы поговорим о реляционных базах данных. Потом — о SQL, и о формировании SQL-запросов. И наконец — о том, как работают SQL-инъекции, и о том, почему они так опасны для веб-приложений.

Реляционные базы данных


Прежде чем говорить о SQL (и о SQL-инъекциях), нам надо познакомиться с реляционными базами данных (БД).

В реляционной БД хранятся взаимосвязанные данные, которые часто размещаются в таблицах. Каждая таблица содержит набор столбцов и строк.

Вот, например, таблица, которая называется users.

a9231650ead96b474229dedf6676d28b.png

Таблица 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-инъекций?

oug5kh6sjydt9llengsiebnp40w.png

© Habrahabr.ru