Katalog .git w web aplikacji

09 Mar 2018

deny  git  nginx  public  resources  security  varnish 

Share on:

Jednym z często popełnianych błędów, który stwarza ogromny problem i narusza polityki bezpieczeństwa aplikacji, jest udostępnianie katalogu .git w zasobach publicznych.

Jako administratorzy powinniśmy mieć pełną kontrolę nad udostępnianymi zasobami z serwisów produkcyjnych, które obsługujemy — i nie chodzi tutaj tylko o ruch wychodzący z serwerów backend’owych. Bardzo często developerzy przemycą zasoby, które będą dostępne na świat lub po prostu zapomną dodać odpowiednich reguł filtrujących po stronie aplikacji.

Wprowadzenie #

Często niestety się zdarza, że takim zasobem jest katalog .git, którego pobranie przez osobę nieuprawnioną pozwala na uzyskanie praktycznie wszystkich informacji o danym projekcie.

Zalecanym sposobem projektowania aplikacji jest wydzielenie osobnego katalogu (np. katalog /public), w którym znajduje się główny punkt „wejścia” dla wszystkich wprowadzanych do aplikacji żądań oraz wydzielenie go poziom niżej z głównego drzewa katalogów projektu.

Większość framework’ów tj. Laravel jest skonfigurowana właśnie w ten sposób.

Przykład:

|-- The Root Directory
  |--  The app Directory
  |--  The bootstrap Directory
  |--  The config Directory
  |--  The database Directory
  |--  The public Directory
  |--  The resources Directory
  |--  The routes Directory
  |--  The storage Directory
  |--  The tests Directory
  |--  The vendor Directory

Swego czasu idealnym przykładem aplikacji (nie wiem, czy do tej pory tak jest), z której poziomu wszystko działało z jednego miejsca, był Wordpress — łatwo w takiej sytuacji o pomyłkę, która może mieć katastrofalne skutki.

Do dalszej analizy oraz szerszego spojrzenia na ten temat polecam świetny artykuł: Hidden directories and files as a source of sensitive information about web application.

Konfiguracja #

Podając dokładnie ciąg .git w specyficznym warunku np. z poziomu serwera Varnish, filtr będzie chwytał wszystko, co zawiera w nazwie ten ciąg znaków, np. digital. Dlatego po ustawieniu reguły filtrującej należy przetestować ją na kilka sposobów.

Do testowania wyrażeń regularnych polecam poniższe narzędzia:

W tym artykule zaprezentuję przykład konfiguracji dla dwóch znanych serwerów HTTP/HTTPS: Varnish oraz NGINX.

Varnish #

Zabezpieczeniem, które należy wprowadzić w konfiguracji Varnish’a i to niezależnie od tego, czym obsługujemy ruch HTTPS (bądź go w ogóle nie obsługujemy) jest przechwytywanie wystąpienia ciągu znaków .git w podanym zapytaniu.

Wygląda to tak:

sub vcl_recv {

  if (req.url ~ "\.git") {

    return (synth(403, "Not allowed"));

  }

}

NGINX #

W przypadku serwera NGINX przechwytywany ciąg znaków jest oczywiście ten sam, jednak z drugiej strony sytuacja wygląda trochę inaczej ponieważ podane restrykcje będą musiały być zastosowane w odpowiednim kontekście, np. dla każdej konfiguracji zawierającej dyrektywę (lub dyrektywy) listen lub za pomocą innego sposobu z dyrektywą location (jednak będzie trzeba ją dodać dla każdej domeny).

Wygląda to mniej więcej tak:

listen 192.168.252.2:443 ssl;

# Nagłówki, konfiguracja TLS, oraz inne.

if ($request_uri ~ "/\.git") {

  return 403;

}

W przypadku dyrektywy location konfiguracja może wyglądać tak:

location ~ "/\.git" {

  deny all;

}

Prostym filtrem, który zawsze stosuję, jest (oczywiście należy go odpowiednio dostosować do hostowanych aplikacji):

location ~* ^.*(\.(?:git|svn|hg|bak|bckp|save|old|orig|original|test|conf|cfg|dist|in[ci]|log|sql|mdb|sw[op]|htaccess|php#|php~|php_bak|aspx?|tpl|sh|bash|bin|exe|dll|jsp|out|cache|))$ {

  # Możesz użyć dodatkowo limitowania, definiując poniższą regułę w kontekście server:
  # limit_req_zone $binary_remote_addr zone=per_ip_5r_s:5m rate=5r/s;
  limit_req zone=per_ip_5r_s;

  deny all;
  access_log /var/log/nginx/restricted-files-access.log main;
  access_log /var/log/nginx/restricted-files-error.log main;

}