Przejdź do treści
INDEKS ANALIZ BREACHROAD / NOTA TECHNICZNA

CVE-2026-60004: krytyczne RCE w Gitea przez Git hook

Gitea przed 1.27.1 pozwalała autorowi repozytorium utworzyć aktywny Git hook i wykonać kod serwera. Analizujemy warunki, wpływ i naprawę.

MATERIAŁ PUBLICZNY
AUTOR
/ CEO Breachroad · OSCP · PNPT
PUBLIKACJA
29 lipca 2026
CZAS CZYTANIA
13 min czytania
TEMAT
Podatności i CVE
CVE-2026-60004: krytyczne RCE w Gitea przez Git hook

29 lipca 2026 roku opublikowano szczegółową analizę CVE-2026-60004, krytycznej podatności RCE w samodzielnie hostowanej platformie Gitea. Błąd dotyczy endpointu diffpatch: użytkownik ze zwykłym prawem zapisu do repozytorium może doprowadzić do umieszczenia wykonywalnego Git hooka w katalogu tymczasowego repozytorium i uruchomić polecenia jako konto systemowe usługi Gitea.

Ocena CVSS wynosi 9.8. Podatne są wersje od 1.17 do wydań wcześniejszych niż 1.27.1. Oficjalny advisory nie informuje o wykorzystaniu luki w atakach, ale zawiera publiczny PoC. To połączenie uzasadnia pilne wdrożenie wersji 1.27.1 i sprawdzenie okresu ekspozycji.

Najważniejsze fakty

Oficjalny advisory Gitea GHSA-rcr6-4jqh-j84m potwierdza:

  • podatne wersje: Gitea 1.17 i nowsze przed 1.27.1;
  • wersja naprawiona: 1.27.1;
  • wymagane jest prawo zapisu do repozytorium;
  • kod wykonuje się jako systemowe konto usługi Gitea;
  • przy domyślnej otwartej rejestracji zewnętrzny użytkownik może sam założyć konto i repozytorium;
  • techniczny trigger wymaga Git 2.32 lub nowszego, aktywnej trasy diffpatch oraz zapisywalnego i wykonywalnego katalogu tymczasowego;
  • producent nie podał informacji o aktywnym wykorzystaniu.

Publikacja z 29 lipca zwróciła też uwagę, że informacja o naprawie mogła zostać przeoczona: Gitea 1.27.1 ukazała się 27 lipca, a opis zmiany w release notes brzmiał neutralnie „refactor: git patch apply”.

Łańcuch podatności bez publikowania payloadu

Endpoint POST /api/v1/repos/{owner}/{repo}/diffpatch stosuje dostarczony patch w tymczasowym klonie repozytorium. W podatnej wersji klon jest bare, czyli nie ma klasycznego working tree, a jego główny katalog jest jednocześnie $GIT_DIR.

Gitea wywoływała git apply między innymi z opcjami indeksu i, w przypadku Git 2.32+, z trzystronnym fallbackiem. Dwukrotne zastosowanie odpowiednio skonstruowanej zmiany tworzyło konflikt add/add. Mechanizm trzystronny materializował wpis z indeksu mimo trybu --cached.

W zwykłym repozytorium plik w ścieżce hooks/... byłby po prostu treścią working tree. W bare clone ta sama ścieżka może znaleźć się bezpośrednio w katalogu hooków Git. Jeżeli ma bit wykonywalny i nazwę obsługiwanego hooka, Git uruchamia ją podczas operacji na indeksie.

Kluczowa lekcja brzmi: kod aplikacji traktował patch jak dane repozytorium, ale narzędzie Git interpretowało wynik w kontekście własnego katalogu sterującego. Dwie warstwy miały różne modele tego, czym jest ścieżka.

Dlaczego „wymaga konta” nie obniża automatycznie ryzyka

Sam endpoint odrzuca niezalogowanych klientów. W wielu instalacjach Gitea domyślna konfiguracja pozwala jednak na otwartą rejestrację, nie wymaga potwierdzenia e-maila ani ręcznej akceptacji i pozwala nowemu użytkownikowi stworzyć repozytorium. W takim środowisku osoba z internetu może uzyskać wymagane prawo zapisu poprzez legalny formularz.

Otwartą rejestrację należy więc traktować jako element ścieżki ataku. Wyłączenie jej usuwa wariant „nowy zewnętrzny użytkownik”, lecz:

  • nie naprawia podatnego kodu;
  • nie chroni przed istniejącym zwykłym użytkownikiem;
  • nie chroni przed przejętym kontem dewelopera;
  • nie usuwa ryzyka wewnętrznego tenanta w platformie współdzielonej.

To przykład, w którym CVSS PR:N wynika z typowej drogi uzyskania konta, choć sama operacja techniczna wymaga uwierzytelnionej sesji i prawa zapisu.

Potencjalny wpływ zależy od izolacji usługi

Polecenia uruchamiają się jako użytkownik systemowy Gitea, nie automatycznie jako root. To nadal bardzo poważny poziom dostępu. Oficjalny advisory wymienia:

  • app.ini i sekrety aplikacji;
  • sekrety w zmiennych środowiskowych procesu;
  • zamontowane repozytoria;
  • dane logowania do bazy i jej zawartość;
  • credentiale OAuth i integracji;
  • inne usługi osiągalne z hosta.

Jeżeli Gitea działa w kontenerze jako użytkownik bez uprawnień, z read-only filesystem, osobnym wolumenem i ograniczonym egress, zasięg jest mniejszy. Jeżeli usługa działa na hoście z szerokim montowaniem katalogów, wspólnym socketem Dockera, tokenami wdrożeniowymi i trasą do sieci zarządczej, jeden Git hook może stać się początkiem kompromitacji łańcucha CI/CD.

Naprawa zmienia granicę katalogu

Zmiana naprawcza w kodzie przełącza tymczasowy klon z bare na non-bare. Dzięki temu working tree jest oddzielone od $GIT_DIR, a plik dostarczony przez patch nie staje się automatycznie aktywnym hookiem.

To dobry przykład naprawy przyczyny, nie tylko blokady nazwy post-index-change. Denylista jednego hooka byłaby krucha, bo Git ma wiele nazw hooków, a inne operacje mogłyby materializować ścieżki w katalogu sterującym. Separacja przestrzeni danych repozytorium od metadanych Git przywraca właściwą granicę.

Co zrobić natychmiast

  1. Zaktualizuj Gitea do 1.27.1 lub nowszej. Odczytaj wersję z działającej instancji, obrazu i kontenera.
  2. Tymczasowo wyłącz otwartą rejestrację, jeśli nie jest biznesowo konieczna. Nie traktuj tego jako zamiennika poprawki.
  3. Ogranicz trasę diffpatch na czas awaryjnego wdrożenia, jeżeli architektura na to pozwala i zostało to przetestowane.
  4. Zachowaj katalogi tymczasowe i logi przed restartem, jeśli istnieje podejrzenie użycia.
  5. Sprawdź uprawnienia użytkownika Gitea, montowania, zmienne środowiskowe i osiągalne usługi.
  6. Wycofaj podatne obrazy z rejestru i blokuj ich ponowne wdrożenie przez IaC.

W środowisku Gitea Cloud producent zapowiadał automatyczną aktualizację. Klienci nadal powinni uzyskać potwierdzenie wersji i czasu wdrożenia, szczególnie jeśli mają integracje lub runnerów poza usługą zarządzaną.

Analiza okresu ekspozycji

Brak potwierdzonego wykorzystania nie oznacza, że nie trzeba sprawdzić logów. Publiczny PoC pozwala odzyskać wynik bez połączenia zwrotnego: hook może zapisać rezultat w obiektach Git i udostępnić go przez zwykły protokół repozytorium. Detekcja oparta wyłącznie na połączeniu do zewnętrznego C2 może więc niczego nie zobaczyć.

Sprawdź:

  • wywołania endpointu diffpatch, szczególnie powtarzające tę samą zmianę;
  • nowe konta i repozytoria tworzone krótko przed nietypową aktywnością;
  • ścieżki hooks/ pojawiające się w danych patcha lub tymczasowych klonach;
  • procesy potomne Gitea i Git uruchamiające powłokę;
  • nowe branche lub obiekty Git o nietypowych nazwach;
  • odczyt app.ini, plików środowiskowych, konfiguracji runnerów i credentiali;
  • zmiany tokenów, webhooków, kluczy deploy i konfiguracji repozytoriów.

Te hipotezy trzeba dostosować do wersji i logowania instalacji. Jeśli /tmp jest czyszczone przy restarcie, dowody mogą zniknąć, dlatego zachowanie obrazu przed aktualizacją ma znaczenie przy podejrzeniu nadużycia.

Hardening po aktualizacji

Gitea powinna działać jako odrębny użytkownik bez logowania, z minimalnym prawem do wolumenów. Sekrety wdrożeniowe nie powinny znajdować się w procesie webowym, jeżeli może je uzyskać runner z krótkotrwałą tożsamością. Dostęp wychodzący ogranicz do niezbędnych rejestrów i webhooków, a połączenia do produkcji prowadź przez osobną warstwę CI/CD z zatwierdzaniem.

Warto także:

  • wymagać akceptacji nowych kont lub SSO;
  • ograniczyć tworzenie organizacji i repozytoriów;
  • włączyć MFA dla administratorów i właścicieli;
  • oddzielić runnerów od serwera Gitea;
  • rotować klucze deploy oraz webhook secrets;
  • skanować obrazy i SBOM po każdej aktualizacji;
  • monitorować procesy potomne konta usługi.

Zespół DevOps może przećwiczyć ten przypadek podczas szkolenia cyberbezpieczeństwa: pozornie bezpieczna funkcja „zastosuj patch” przekazuje dane do narzędzia, które ma własne wykonywalne mechanizmy.

Jak potwierdzić naprawę bez uruchamiania RCE

Nie trzeba wykonywać publicznego PoC na produkcji. Wystarczy udowodnić:

  • wersję 1.27.1+ na każdej aktywnej instancji;
  • brak starszego obrazu w działających workloadach;
  • wdrożenie commitów właściwej gałęzi, jeśli używany jest fork;
  • oddzielenie working tree od $GIT_DIR w bezpiecznym teście integracyjnym;
  • brak wykonania pliku kontrolnego jako hooka;
  • zachowanie funkcji diffpatch dla legalnych operacji.

Niezależny audyt bezpieczeństwa IT lub test aplikacji i API może objąć również rejestrację, role, repozytoria, webhooki, runnerów i sekrety — elementy, których sam skan CVE nie oceni.

Źródła i granice wnioskowania

Fakty o wersjach, warunkach, wpływie i PoC pochodzą z GHSA-rcr6-4jqh-j84m, wydania 1.27.1 i commitu naprawczego. Nowe omówienie ukazało się 29 lipca w The Hacker News.

Żadne z cytowanych źródeł nie potwierdza aktywnego wykorzystania. Hipotezy detekcyjne i zalecenia izolacji są analizą BreachRoad. Publiczny PoC istnieje, ale nie jest potrzebny do bezpiecznej walidacji produkcji; poprawiona wersja i dowód separacji katalogów są wystarczającym celem retestu.

Jak przeszukać okres ekspozycji bez uruchamiania PoC

Zespół nie musi odtwarzać publicznego payloadu na produkcji. Najpierw należy ustalić datę instalacji podatnej wersji, moment aktualizacji do 1.27.1 i wszystkie instancje, które mogły działać w tym przedziale. Dla każdej instancji warto zebrać konfigurację rejestracji, wersję Git, ustawienia katalogu tymczasowego i listę użytkowników mających prawo zapisu.

Następnie można korelować bezpieczne źródła:

  • żądania do trasy diffpatch, zwłaszcza powtarzane dla jednego repozytorium;
  • tworzenie plików pod ścieżkami hooks w katalogach tymczasowych;
  • procesy potomne Gitea, których nie wyjaśnia normalna administracja;
  • wychodzący ruch sieciowy z konta usługi;
  • nowe klucze SSH, tokeny, webhooki i konta po podejrzanym czasie;
  • zmiany w repozytoriach wykonane przez tożsamość usługi zamiast użytkownika.

Brak logów trasy albo procesu nie dowodzi braku wykorzystania. W raporcie należy oznaczyć go jako ograniczenie widoczności. Praktyczne podejście do budowy takich korelacji opisuje przewodnik detection engineering z Sigma i SIEM, a plan reakcji na incydent pomaga przełożyć wynik na decyzje o rotacji.

Sekrety i zasięg konta usługi

RCE działa z uprawnieniami procesu Gitea, dlatego wpływ zależy od jego otoczenia. Konto może mieć dostęp do bazy, magazynu obiektowego, kluczy podpisujących, tokenów webhooków, konfiguracji OAuth i repozytoriów. Kontener ogranicza część systemu plików, ale nie jest automatyczną granicą dla sekretów w zmiennych środowiskowych i wolumenach.

Po potwierdzonej lub wiarygodnej eksploatacji trzeba utworzyć mapę poświadczeń dostępnych dla usługi, a następnie rotować je w kolejności wpływu. Sam restart poda nie usuwa skradzionego tokena. Należy także przejrzeć działania wykonane już po wymianie wersji, bo uzyskane wcześniej poświadczenie może utrzymywać dostęp poza Gitea.

Bezpieczny retest poprawki

Retest powinien potwierdzić wersję 1.27.1 lub nowszą, zachowanie legalnego patcha i brak możliwości zapisania wykonywalnego pliku w katalogu hooków. Można użyć nieszkodliwego znacznika oraz odizolowanego środowiska, bez połączenia z produkcyjnymi sekretami. Wynik warto dodać jako automatyczny test regresyjny wokół funkcji nakładającej diff.

Incydent łączy bezpieczeństwo aplikacji z bezpieczeństwem narzędzia Git. Materiał o atakach na łańcuch dostaw oprogramowania pokazuje podobne problemy granic zaufania, a Akademia Breachroad pozwala utrwalić podstawy uprawnień i obserwowalności. Ostatecznym celem jest nie tylko brak znanego CVE, lecz minimalny zasięg konta Gitea, zamknięta rejestracja tam, gdzie nie jest potrzebna, i dowód, że anomalia wywoła alarm.

UDOSTĘPNIJ / KOPIUJ