Stručně: Veřejná složka .git vzniká, když se web nasazuje pomocí git clone nebo git pull přímo ve webrootu a webserver neblokuje skryté složky. Pak lze stáhnout kompletní zdrojový kód včetně historie verzí, i s dříve vloženými přístupovými údaji. Své domény zkontrolujte jednoduchým požadavkem, přístup okamžitě zablokujte, nasazování převeďte na balíčky bez .git a přístupové údaje z historie vyměňte.
Zdrojový kód k odnesení
Git je standardní nástroj pro správu verzí a pro malé týmy je logické jím také nasazovat: připojit se na server, git pull, hotovo. Funguje to spolehlivě a rychle. Má to ale vedlejší účinek, kterého si často nikdo nevšimne.
V adresáři projektu leží skrytá složka .git. Neobsahuje jen aktuální stav, ale každý soubor v každé verzi, která kdy byla vložena, k tomu zprávy commitů, jména a e-mailové adresy vývojářů a odkazy na servery. Pokud tato složka leží ve webrootu a webserver ji doručuje, může si ji stáhnout kdokoli.
Pro útočníky je to dárek. Se zdrojovým kódem lze slabiny hledat cíleně, místo aby se hádaly zvenčí. A v historii se často najde to, co se zdálo dávno smazané: heslo k databázi z počátků, klíč API, testovací soubor se zákaznickými daty.
Je vaše složka .git veřejná? Jak to ověřit
Kontrola trvá sekundy a nic nemění. Pro každou doménu a subdoménu zavolejte soubor, který existuje v každém repozitáři Git:
# Očekáváno: 403 nebo 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 serveru: Existují složky .git pod webrooty?
find /var/www /srv/www -maxdepth 4 -type d -name ".git" 2>/dev/null
Stav 200 znamená: složka je dostupná. Dávejte pozor i na podadresáře. Někdy repozitář neleží přímo ve webrootu, ale ve složce pluginu nebo šablony, která se spravuje samostatně přes Git.
Zkontrolujte také stagingová a testovací prostředí. Aktualizují se přes Git častěji než produkce a bývají dostupná na snadno uhodnutelných subdoménách.
Okamžitě: zablokovat přístup
Než se nasazování změní, zablokuje přístup ke složkám správy verzí pravidlo ve webserveru. Obecné blokování skrytých souborů, jak je popsáno v článku Správná ochrana přístupových údajů a souborů .env, to pokrývá také. Kdo chce zablokovat cíleně jen správu verzí, použije užší pravidlo:
location ~ /\.(git|svn|hg)(/|$) {
return 404;
}
RedirectMatch 404 /\.(git|svn|hg)(/|$)
Poté kontrolu shora zopakujte, a to skutečným požadavkem zvenčí: úspěšný test konfigurace říká jen to, že syntaxe sedí, ne že pravidlo zabírá dříve než jiná pravidla pro statické soubory. U panelů jako Plesk nebo cPanel zapište pravidlo do určených dodatečných direktiv, aby se při příštím generování konfigurace neztratilo.
Pokud byla složka dostupná, považujte všechny přístupové údaje, které kdy v repozitáři byly, za známé. Samotné blokování pak nestačí, hodnoty je nutné vyměnit.
Trvale: nasazovat bez .git ve webrootu
Blokování je zabezpečení, ne řešení. Trvale nepatří správa verzí na produkční server. Osvědčené cesty podle vašeho prostředí:
| Postup | Jak funguje | Vhodné pro |
|---|---|---|
| Sestavený balíček z CI | Pipeline vytvoří archiv bez .git, server ho rozbalí do nového adresáře vydání |
týmy s CI/CD |
git archive |
vytvoří archiv stavu bez dat verzí | malé projekty bez pipeline |
rsync s vyloučeními |
přenese jen nutné soubory | klasické servery |
| Image kontejneru | kód se při sestavení zkopíruje do image, .git se vyloučí přes .dockerignore |
provoz v kontejnerech |
Adresář vydání pro každou verzi se symbolickým odkazem na aktuální stav má další výhodu: při problémech můžete okamžitě přepnout zpět. Pro prostředí kontejnerů popisuje článek CI/CD: automatické přestavování image PHP, jak učinit sestavení reprodukovatelnými. Tam by se také mělo kontrolovat, že se .git do image nedostane.
# Příklad: vytvořit balíček stavu bez dat verzí
git archive --format=tar.gz -o release.tar.gz HEAD
Další soubory projektu, které nepatří do webrootu
Složka .git je nejznámějším příkladem, ale ne jediným. Kdo nasazuje celé adresáře projektu, přináší do webrootu další soubory, které tam nemají co dělat:
- Složky vývojových prostředí jako
.ideanebo.vscode, v nichž rozšíření pro nahrávání souborů někdy ukládají adresy serverů a přístupové údaje. composer.jsonacomposer.lock, které prozrazují přesné verze všech knihoven a usnadňují tak hledání známých zranitelností.- Konfigurace testů, nástrojů pro sestavení a pipeline, které odhalují interní názvy hostitelů a postupy.
- Zbytky operačních systémů jako
.DS_Store, které obsahují seznamy souborů celých adresářů.
Řešení je stejné jako u složky .git: doručovat jen to, co musí být veřejné, ideálně přes vlastní podsložku jako webroot. Kdo nasazování stejně převádí na balíčky, určí při tom rovnou seznam vyloučených souborů a kontroluje ho při každém novém nástroji v projektu.
Pokud byla složka otevřená: zkontrolujte historii a logy
Pokud se ukáže, že složka .git byla dostupná, postupujte v tomto pořadí:
- Zablokujte přístup a kontrolu zopakujte.
- Prohledejte historii, jaká tajemství byla kdy vložena: konfigurační soubory,
.env, klíče, výpisy databází. - Vyměňte přístupové údaje, a to všechny nalezené v kroku 2, i když dnes v kódu už nejsou.
- Vyhodnoťte přístupové logy, zda byly soubory pod
/.git/staženy se stavem 200 a z jakých adres. Jak na to, ukazuje Vyhodnocení logů webserveru po útoku. - Cíleně zkontrolujte zdrojový kód, protože útočníci ho nyní znají. Známé slabiny by se měly odstranit přednostně.
- Ujasněte ochranu osobních údajů, pokud v historii ležely osobní údaje, například testovací exporty. Posouzení provede váš pověřenec pro ochranu osobních údajů.
Nástroje pro vyhledávání tajemství v repozitářích patří poté trvale do pipeline. OWASP takové kontroly výslovně doporučuje, jako hook před vložením a v CI.
Jak konkrétně pomáhá PHP SOS?
- Zkontrolujeme všechny vaše domény a subdomény na dostupné složky správy verzí.
- Přístup okamžitě zablokujeme a nasazování převedeme na balíčky bez dat verzí.
- Prohledáme historii na tajemství a doprovodíme výměnu dotčených přístupů.
- Vyhodnotíme přístupové logy a zdokumentujeme, zda a kdy byla data stažena.
Tato opatření jsou součástí našeho hardeningu serveru pro webservery s PHP.
Časté dotazy
Jak vzniká veřejná složka .git?
Většinou nasazením pomocí git clone nebo git pull přímo ve webrootu. Složka .git s celou historií verzí pak leží vedle index.php a bez blokování webserver její soubory doručuje.
Stačí složku .git smazat?
Pro budoucnost ano, pro minulost ne. Pokud byla složka dostupná, mohl být obsah už zkopírován. Přístupové údaje, které kdy v repozitáři byly, byste proto měli vyměnit.
Pomůže odstranit přístupové údaje dodatečně z historie Gitu?
Zabrání to tomu, aby je obsahovaly nové kopie. Kdo už repozitář stáhl, má staré stavy dál. Rozhodující je proto výměna přístupových údajů, ne jen přepsání historie.
Týká se to i jiných systémů správy verzí?
Ano. I složky jako .svn nebo .hg obsahují data projektu a nikdy by neměly být dostupné ve webrootu. Obecné blokování souborů a složek s tečkou na začátku pokryje všechny tyto případy.