Aktualna sytuacja: PHP2Shell. Dwie krytyczne luki w PHP (CVSS 9,2) umożliwiają wykonanie złośliwego kodu bez logowania. Poprawki od 21.10.2026.Co należy teraz zrobić →

Publiczny katalog .git: niedoceniany wyciek danych

Dlaczego webroot wdrażany przez Git może ujawnić cały kod źródłowy wraz z historią, jak to sprawdzić, natychmiast zablokować i trwale zbudować wdrażanie bez katalogu .git.

Stan 5 min czytaniaBezpieczne programowanie

Krótko: Publiczny katalog .git powstaje, gdy strona jest wdrażana za pomocą git clone lub git pull bezpośrednio w webroot, a serwer WWW nie blokuje ukrytych katalogów. Wtedy można pobrać cały kod źródłowy wraz z historią wersji, łącznie z wcześniej zatwierdzonymi danymi dostępowymi. Sprawdź swoje domeny prostym wywołaniem, natychmiast zablokuj dostęp, przestaw wdrażanie na paczki bez .git i wymień dane dostępowe z historii.

Kod źródłowy do zabrania

Git to standardowe narzędzie do kontroli wersji i dla małych zespołów naturalne jest użycie go także do wdrażania: połączyć się z serwerem, git pull, gotowe. Działa to niezawodnie i szybko. Ma jednak skutek uboczny, którego często nikt nie zauważa.

W katalogu projektu leży ukryty katalog .git. Zawiera nie tylko aktualny stan, ale każdy plik w każdej wersji, jaka kiedykolwiek została zatwierdzona, a do tego komunikaty commitów, imiona i adresy e-mail programistów oraz odniesienia do serwerów. Jeśli ten katalog leży w webroot, a serwer WWW go wydaje, każdy może go pobrać.

Dla atakujących to prezent. Dzięki kodowi źródłowemu można celowo szukać słabych punktów, zamiast zgadywać je z zewnątrz. A w historii często znajdują się rzeczy, które dawno wydawały się usunięte: hasło do bazy danych z początków projektu, klucz API, plik testowy z danymi klientów.

Czy Państwa katalog .git jest publiczny? Jak to sprawdzić

Kontrola trwa sekundy i niczego nie zmienia. Wywołaj dla każdej domeny i subdomeny plik, który istnieje w każdym repozytorium Git:

# Oczekiwane: 403 lub 404
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.git/HEAD
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.git/config
# Na serwerze: czy poniżej webroot istnieją katalogi .git?
find /var/www /srv/www -maxdepth 4 -type d -name ".git" 2>/dev/null

Status 200 oznacza: katalog jest dostępny. Zwróć uwagę także na podkatalogi. Czasem repozytorium nie leży w samym webroot, lecz w katalogu wtyczki lub motywu, który jest utrzymywany osobno przez Git.

Sprawdź ponadto środowiska stagingowe i testowe. Są aktualizowane przez Git częściej niż produkcja i często są dostępne pod łatwymi do odgadnięcia subdomenami.

Natychmiast: zablokować dostęp

Dopóki wdrażanie nie zostanie zmienione, reguła w serwerze WWW blokuje dostęp do katalogów kontroli wersji. Ogólna blokada ukrytych plików, opisana w artykule Prawidłowa ochrona danych dostępowych i plików .env, obejmuje to również. Kto chce celowo zablokować tylko kontrolę wersji, stosuje węższą regułę:

location ~ /\.(git|svn|hg)(/|$) {
    return 404;
}
RedirectMatch 404 /\.(git|svn|hg)(/|$)

Następnie powtórz powyższą kontrolę, i to rzeczywistym wywołaniem z zewnątrz: udany test konfiguracji mówi tylko, że składnia się zgadza, a nie że reguła działa przed innymi regułami dla plików statycznych. W panelach takich jak Plesk czy cPanel wpisz regułę w przewidziane do tego dodatkowe dyrektywy, aby nie zginęła przy następnym generowaniu konfiguracji.

Działać natychmiast

Jeśli katalog był dostępny, traktuj wszystkie dane dostępowe, które kiedykolwiek znajdowały się w repozytorium, jako znane. Sama blokada nie wystarcza, wartości muszą zostać wymienione.

Trwale: wdrażać bez .git w webroot

Blokada jest zabezpieczeniem, a nie rozwiązaniem. Trwale kontrola wersji nie należy na serwer produkcyjny. Sprawdzone drogi, zależnie od Państwa środowiska:

Metoda Jak działa Odpowiednia dla
Paczka budowana w CI Pipeline buduje archiwum bez .git, serwer rozpakowuje je do nowego katalogu wydania Zespoły z CI/CD
git archive tworzy archiwum danego stanu bez danych wersji małe projekty bez pipeline
rsync z wykluczeniami przesyła tylko niezbędne pliki klasyczne serwery
Obraz kontenera Kod jest kopiowany do obrazu podczas budowy, .git wykluczony przez .dockerignore działanie w kontenerach

Katalog wydania dla każdej wersji z dowiązaniem symbolicznym do bieżącego stanu ma dodatkową zaletę: w razie problemów można natychmiast się cofnąć. Dla konfiguracji kontenerowych artykuł CI/CD: automatyczna przebudowa obrazów PHP opisuje, jak sprawić, aby buildy były powtarzalne. Tam należy też sprawdzić, czy .git nie trafia do obrazu.

# Przykład: utworzyć paczkę danego stanu bez danych wersji
git archive --format=tar.gz -o release.tar.gz HEAD

Inne pliki projektu, które nie należą do webroot

Katalog .git to najbardziej znany przykład, ale nie jedyny. Kto wdraża całe katalogi projektu, przenosi do webroot kolejne pliki, które nie mają tam czego szukać:

  • Katalogi środowisk programistycznych, takie jak .idea lub .vscode, w których rozszerzenia do przesyłania plików czasem zapisują adresy serwerów i dane dostępowe.
  • composer.json i composer.lock, które zdradzają dokładne wersje wszystkich bibliotek i ułatwiają tym samym szukanie znanych luk.
  • Konfiguracje testów, narzędzi budowania i pipeline, które ujawniają wewnętrzne nazwy hostów i procesy.
  • Pozostałości systemów operacyjnych, takie jak .DS_Store, zawierające listy plików całych katalogów.

Rozwiązanie jest takie samo jak w przypadku katalogu .git: wydawać tylko to, co musi być publiczne, najlepiej przez osobny podkatalog jako webroot. Kto i tak przestawia wdrażanie na paczki, od razu ustala listę wykluczonych plików i sprawdza ją przy każdym nowym narzędziu w projekcie.

Gdy katalog był otwarty: sprawdzić historię i logi

Jeśli okaże się, że katalog .git był dostępny, postępuj w tej kolejności:

  1. Zablokować dostęp i powtórzyć kontrolę.
  2. Przeszukać historię, jakie sekrety kiedykolwiek zostały zatwierdzone: pliki konfiguracyjne, .env, klucze, zrzuty baz danych.
  3. Wymienić dane dostępowe, i to wszystkie, które znaleziono w kroku 2, nawet jeśli dziś nie ma ich już w kodzie.
  4. Przeanalizować logi dostępu, czy pliki pod /.git/ były pobierane ze statusem 200 i z jakich adresów. Jak to zrobić, pokazuje artykuł Analiza logów serwera WWW po ataku.
  5. Celowo sprawdzić kod źródłowy, ponieważ atakujący znają go teraz. Znane słabości należy usunąć w pierwszej kolejności.
  6. Wyjaśnić kwestię ochrony danych, jeśli w historii znajdowały się dane osobowe, na przykład eksporty testowe. Ocenę przejmuje Państwa inspektor ochrony danych.

Narzędzia do wyszukiwania sekretów w repozytoriach powinny następnie trwale trafić do pipeline. OWASP wyraźnie zaleca takie kontrole, jako hook przed zatwierdzeniem i w CI.

Jak konkretnie pomaga PHP SOS?

  • Sprawdzamy wszystkie Państwa domeny i subdomeny pod kątem dostępnych katalogów kontroli wersji.
  • Natychmiast blokujemy dostęp i przestawiamy wdrażanie na paczki bez danych wersji.
  • Przeszukujemy historię pod kątem sekretów i wspieramy wymianę dotkniętych dostępów.
  • Analizujemy logi dostępu i dokumentujemy, czy i kiedy dane były pobierane.

Te środki są częścią naszego utwardzania serwerów PHP.

Częste pytania

Jak powstaje publiczny katalog .git?

Zwykle przez wdrożenie za pomocą git clone lub git pull bezpośrednio w webroot. Katalog .git z całą historią wersji leży wtedy obok index.php, a bez blokady serwer WWW wydaje jego pliki.

Czy wystarczy usunąć katalog .git?

Na przyszłość tak, na przeszłość nie. Jeśli katalog był dostępny, jego zawartość mogła już zostać skopiowana. Dane dostępowe, które kiedykolwiek znajdowały się w repozytorium, należy więc wymienić.

Czy pomaga późniejsze usunięcie danych dostępowych z historii Git?

Zapobiega to temu, aby nowe kopie je zawierały. Kto już pobrał repozytorium, nadal ma stare stany. Decydująca jest więc wymiana danych dostępowych, a nie tylko przepisanie historii.

Czy dotyczy to także innych systemów kontroli wersji?

Tak. Także katalogi takie jak .svn lub .hg zawierają dane projektu i nigdy nie powinny być dostępne w webroot. Ogólna blokada plików i katalogów z kropką na początku obejmuje wszystkie te przypadki.

Źródła

Kontakt natychmiast

Liczy się każda godzina. Proszę napisać do nas teraz.

Proszę krótko opisać system, wersję PHP i obserwacje. Skontaktujemy się z Państwem, ustalimy sytuację i będziemy pracować zdalnie, aż incydent zostanie zamknięty i udokumentowany.

Natychmiastowa pomoc