.git w katalogu strony - jak jeden katalog oddaje cały kod i sekrety
W skrócie: gdy kod strony trzymacie w gicie i wdrażacie go przez git pull prosto do katalogu serwowanego przez WWW, katalog .git często ląduje w internecie razem z resztą plików. Stamtąd da się pobrać nie tylko bieżący kod, ale całą historię zmian - łącznie z sekretami, które ktoś kiedyś wkleił i potem "usunął".
Zdarzyło się to też nam, na własnej infrastrukturze. Złapaliśmy to w kilkanaście minut i bez dowodów na dostęp z zewnątrz, ale pokazuje, jak łatwo przeoczyć jedną linię konfiguracji serwera.
Przyznajemy się do tego otwarcie, bo to jedna z najczęstszych, a jednocześnie najprostszych do sprawdzenia podatności w polskich wdrożeniach stron internetowych. Wymaga jednej linii konfiguracji, żeby ją zablokować, i jednej komendy, żeby sprawdzić, czy akurat Was to dotyczy.
Jak do tego dochodzi
Wiele małych wdrożeń aktualizuje stronę najprościej, jak można: repozytorium gita leży bezpośrednio w katalogu, z którego serwer WWW serwuje stronę (np. /var/www/twojastrona), a aktualizacja to git pull wykonany w tym samym miejscu. Wygodne, szybkie, działa od razu.
Problem w tym, że serwer WWW (nginx, Apache) domyślnie serwuje każdy plik w tym katalogu jako zwykły, publicznie dostępny plik statyczny - łącznie z plikami i katalogami zaczynającymi się od kropki, takimi jak .git. Jeśli nikt wyraźnie tego nie zablokował, każdy odwiedzający może po prostu wejść na twojadomena.pl/.git/config i zobaczyć zawartość tego pliku w przeglądarce, tak jak zwykłą stronę.
Co można z tego wyciągnąć
Sam plik .git/config bywa już problemem - zawiera adres repozytorium, a czasem, jeśli ktoś wkleił go z danymi logowania w adresie URL (częsty skrót przy pracy z tokenami GitHuba), też sam token dostępu.
To jednak dopiero początek. Cały katalog .git to w praktyce baza danych z kompletną historią projektu. Narzędziami, które da się znaleźć w kilka sekund w internecie, atakujący odtwarza z tego działający lokalnie klon repozytorium - wraz z każdym plikiem, jaki kiedykolwiek istniał w projekcie, w każdej jego wersji.
Dlaczego to ważne
Usunięcie hasła czy klucza API z pliku w kolejnym commicie nie usuwa go z historii gita. Nadal siedzi w jednym ze starszych commitów, dostępnym dla każdego, kto ma dostęp do .git. Jeśli kiedykolwiek trafił tam sekret, jedyną skuteczną reakcją jest jego rotacja, nie poprawienie samego pliku.
Nasz przypadek
Przy jednej z aktualizacji strony przestawialiśmy deployment ze zwykłego kopiowania plików na git pull wykonywany prosto na serwerze. git init w katalogu webroota wykonaliśmy przed dodaniem reguły blokującej pliki zaczynające się od kropki, nie po. W tym czasie .git/config z wklejonym tokenem dostępu do repozytorium był publicznie dostępny pod adresem naszej własnej strony.
Złapaliśmy to sami, w ramach własnej kontroli, w czasie liczonym w minutach, a przegląd logów serwera nie wykazał żadnych żądań do tego katalogu poza naszymi własnymi (sprawdzającymi najpierw, czy problem istnieje, a potem, czy poprawka działa). Token mimo to potraktowaliśmy jako spalony i zrotowaliśmy go od razu - zgodnie z zasadą wyżej: nie ma znaczenia, czy coś "prawdopodobnie" nikt nie zobaczył.
Jak sprawdzić, czy to dotyczy też Was
Zajmie to jedną komendę w terminalu, dla każdej domeny, na której trzymacie stronę:
curl -I https://twojadomena.pl/.git/config
Odpowiedź 404 albo 403 oznacza, że wszystko jest w porządku. Odpowiedź 200 oznacza, że katalog .git jest publicznie dostępny i trzeba to zablokować od razu. Warto sprawdzić tym samym sposobem też /.env - inny częsty kandydat do przypadkowej ekspozycji.
Jak to zablokować
W nginx wystarczy jedna reguła w bloku server konfiguracji danej strony:
location ~ /\.git { deny all; return 404; }
W Apache odpowiada za to analogiczna reguła w .htaccess albo w konfiguracji vhosta. W obu przypadkach warto dopisać to raz, do głównego szablonu konfiguracji, którym stawiacie nowe strony, żeby nie trzeba było o tym pamiętać przy każdym kolejnym wdrożeniu.
Lepsze rozwiązanie strukturalne to w ogóle nie trzymać .git w katalogu, który serwer wystawia do internetu - np. budować stronę w osobnym miejscu i kopiować do webroota tylko gotowe pliki, albo wdrażać przez CI, które nie zostawia po sobie repozytorium na produkcji. Reguła w nginx to dobra, szybka siatka bezpieczeństwa, ale nie zastępuje tego, żeby sekret w ogóle nie trafił tam, gdzie może wyciekać.
Sprawdzenie, co widać z internetu na Waszej stronie, to dokładnie to, co robimy w bezpłatnym skanie ekspozycji - takie drobne przeoczenia konfiguracyjne są często pierwszym punktem, od którego zaczyna się pełny test penetracyjny aplikacji webowej.
Nie wiecie, czy Wasza strona ma ten problem?
Sprawdzimy to wraz z resztą ekspozycji z zewnątrz - szybko i bez ingerencji w Wasze systemy.
Zapytaj o wycenę