- PVSM.RU - https://www.pvsm.ru -
Кто угодно может получать доступ к данным из удалённых форков, удалённых репозиториев и даже приватных репозиториев GitHub. И эти данные доступны всегда. Это известно разработчикам GitHub, и они намеренно спроектировали систему таким образом.
Это настолько огромный вектор атак для всех организаций, использующих GitHub, что мы решили ввести новый термин: Cross Fork Object Reference (CFOR). Уязвимость CFOR возникает, когда форк одного репозитория может получить доступ к требующим защиты данным из другого форка (в том числе и к данным из приватных и удалённых форков). Аналогично Insecure Direct Object Reference, при CFOR пользователи передают хэши коммитов, чтобы напрямую получать доступ к данным коммитов, которые иначе были бы для них невидимыми.
Давайте рассмотрим несколько примеров.
Возьмём такую часто используемую в GitHub последовательность действий:
Доступен ли по-прежнему код, коммит которого был выполнен в форк? Вроде бы не должен быть, правда? Мы ведь его удалили.
Но он доступен. И будет доступен всегда. Вне вашего контроля.
В показанном ниже видео мы создаём форк репозитория, коммитим в него данные, удаляем форк, а затем получаем доступ к «удалённым» данным коммита через исходный репозиторий.
Вы можете подумать, что защищены необходимостью знать хэш коммита. Но это не так. Хэш можно узнать, подробнее об этом ниже.
Достаточно часто. Мы изучили три часто форкаемых публичных репозиторя крупной ИИ-компании, и с лёгкостью нашли 40 валидных ключей API из удалённых форков. Похоже, пользователи применяли такой паттерн:
Но ещё хуже, что можно сделать и наоборот:
Рассмотрим следующий сценарий:
Будет ли код, который вы закоммитили после форка, по-прежнему доступным?
Да.
GitHub хранит репозитории и форки в сети репозиториев [1], где исходный upstream-репозиторий используется в качестве корневого узла. Когда удаляется публичный upstream-репозиторий, для которого создавались форки, GitHub назначает на роль корневого узла один из downstream-форков [2]. Однако все коммиты из upstream-репозитория всё равно существуют и доступны из любого форка.
В показанном ниже видео мы создаём репозиторий, форкаем его, а затем демонстрируем, что к данным, не синхронизируемым с форком, всё равно можно получить доступ через форк после удаления исходного репозитория.
И это не просто какой-то пограничный сценарий. Вот, что произошло у меня недавно:
Я отправил уязвимость уровня P1 крупной технологической компании, показав, что она случайно закоммитила приватный ключ к аккаунту GitHub сотрудника, имеющего высокий уровень доступа к GitHub всей организации. Компания немедленно удалила репозиторий, но поскольку к нему создавались форки, я всё равно смог получить через форк доступ к коммиту, содержащему конфиденциальные данные, хотя форк никогда не синхронизировался с исходным upstream-репозиторием.
Из этого следует сделать вывод, что любой код, закоммиченный в публичный репозиторий, будет доступен вечно, пока существует хотя бы один форк этого репозитория.
Но и это ещё не всё.
Рассмотрим часто используемый процесс вывода нового инструмента в open source на GitHub:
Будут ли приватные фичи и связанный с ними код (из шага 2) видны широкой публике?
Да. Любой код, закоммиченный между моментом создания внутреннего форка инструмента и опенсорсингом инструмента, будет доступен в публичном репозитории.
Все коммиты, внесённые в приватный форк после того, как вы сделали upstream-репозиторий публичным, доступны не будут. Это вызвано тем, что изменение видимости приватного upstream-репозитория приводит к созданию двух сетей репозиториев — одной для приватной версии, другой — для публичной.
В видео ниже мы показываем, как организации выводят в open source новые инструменты, в то же время сохраняя приватные внутренние форки, а затем демонстрируем, как можно получить доступ к закоммиченным данным приватной внутренней версии через публичную.
К сожалению, именно так чаще всего пользователи и организации подходят к разработке опенсорсного ПО. Из-за этого возможно непреднамеренное раскрытие конфиденциальных данных и секретов в публичных репозиториях GitHub организации.
Операции уничтожения в сети репозиториев GitHub (подобные описанным в трёх приведённых выше сценариях) удаляют ссылки на данные коммитов из стандартного UI GitHub и обычных операций git. Однако эти данные всё равно существуют, и к ним можно получить доступ (если знать хэш коммита). В этом заключается связь между уязвимостями CFOR и IDOR — если вы знаете хэш коммита, то сможете напрямую получать доступ к данным, не предназначенным для вас.
Хэши коммитов — это значения SHA-1.
Если пользователь знает хэш SHA-1 конкретного коммита, который он хочет просмотреть, то он может напрямую перейти к этому коммиту в конечной точке: https://github.com/<user/org>/<repo>/commit/<commit_hash>
. Он увидит жёлтый баннер с информацией о том, что «этот коммит не принадлежит ни к одной из ветвей этого репозитория и может принадлежать форку вне репозитория».
Откуда взять эти значения хэшей?
Хэши коммитов можно подобрать брутфорсом через UI GitHub, и в особенности потому, что протокол git допускает использование коротких значений SHA-1 [3] при ссылках на коммит. Короткое значение SHA-1 — это минимальное количество символов, необходимое для предотвращения коллизий с хэшем другого коммита. Абсолютно минимальное значение равно 4. Пространство ключей всех значений SHA-1 из четырёх символов составляет 65536 (16^4). Брутфорс всех возможных значений можно выполнить достаточно просто.
Рассмотрим для примера этот коммит из нашего репозитория:
Для получения доступа к этому коммиту пользователи обычно переходят к URL, содержащему полный хэш SHA-1 коммита: https://github.com/trufflesecurity/trufflehog/commit/07f01e8337c1073d2c45bb12d688170fcd44c637 [4].
Но им необязательно знать всё значение SHA-1 из 32 символов, достаточно лишь правильно угадать короткое значение SHA-1, которое в данном случае равно 07f01e
.
https://github.com/trufflesecurity/trufflehog/commit/07f01e [5]
Но вот, что ещё более интересно: GitHub раскрывает публичную конечную точку API событий. Можно также запрашивать хэши коммитов в архиве событий [6], управляемом третьей стороной. Он сохраняет все события GitHub за последний десяток лет вне пределов GitHub даже после удаления репозиториев.
Недавно мы отправили отчёт о своих находках в GitHub в рамках его программы VDP. Был получен следующий ответ:
После изучения документации стало абсолютно понятно, что GitHub осознанно спроектировал репозитории таким образом.
Мы ценим то, что GitHub прозрачно раскрывает свою архитектуру и уделил время документированию того, что должны ожидать пользователи в подобных случаях.
Но для нас проблема заключается в следующем:
Среднестатистический пользователь рассматривает такое разделение репозиториев на приватные и публичные как границу безопасности и вполне логично предполагает, что все данные, хранящиеся в приватном репозитории, будут недоступны для публичных пользователей. К сожалению, как показано в приведённой выше документации, это не всегда так. Кроме того, процесс удаления подразумевает уничтожение данных, но, как мы видели выше, удаление репозитория или форка не означает реального удаления данных коммита.
Из этого можно сделать несколько выводов:
Кроме того, несмотря на то, что наше исследование посвящено только GitHub, важно отметить, что некоторые из данных проблем свойственны и другим системам управления версиями.
Автор: ru_vds
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/git/393314
Ссылки в тексте:
[1] сети репозиториев: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-permissions-and-visibility-of-forks#about-visibility-of-forks
[2] Когда удаляется публичный upstream-репозиторий, для которого создавались форки, GitHub назначает на роль корневого узла один из downstream-форков: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/what-happens-to-forks-when-a-repository-is-deleted-or-changes-visibility#deleting-a-public-repository
[3] коротких значений SHA-1: https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#:~:text=to%20any%20commit.-,Short%20SHA%2D1,-Git%20is%20smart
[4] https://github.com/trufflesecurity/trufflehog/commit/07f01e8337c1073d2c45bb12d688170fcd44c637: https://github.com/trufflesecurity/trufflehog/commit/07f01e8337c1073d2c45bb12d688170fcd44c637
[5] https://github.com/trufflesecurity/trufflehog/commit/07f01e: https://github.com/trufflesecurity/trufflehog/commit/07f01e
[6] архиве событий: https://www.gharchive.org/
[7] https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/what-happens-to-forks-when-a-repository-is-deleted-or-changes-visibility: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/what-happens-to-forks-when-a-repository-is-deleted-or-changes-visibility
[8] howtorotate.com: https://howtorotate.com/docs/introduction/getting-started/
[9] недавнем посте: https://trufflesecurity.com/blog/trufflehog-scans-deleted-git-branches
[10] Источник: https://habr.com/ru/companies/ruvds/articles/835448/?utm_source=habrahabr&utm_medium=rss&utm_campaign=835448
Нажмите здесь для печати.