Evil merge: złośliwy kod w kommicie scalania Git
W bazie kodu projektu wykryto złośliwy kod w pliku vite.config.js, który został zamaskowany. Pojawił się nie w PR, a bezpośrednio w kommicie scalania podczas rozwiązywania konfliktów. GitHub wyświetla w PR tylko różnice między gałęziami, ignorując zmiany w samym kommicie scalania. Analiza za pomocą git log ujawniła kommit scalania z identycznymi rodzicami, ale zmodyfikowaną zawartością pliku.
MD5-hash rodziców były identyczne:
- Rodzic 1:
aa82acb0c335430d8300b6cb306dc824(czysty) - Rodzic 2:
aa82acb0c335430d8300b6cb306dc824(czysty) - Scalanie:
2a54754defae4d13aab39f256738dbbf(zmodyfikowany)
W trójstronnym scalaniu Git, gdy pliki u rodziców są identyczne, wynik powinien pozostać niezmieniony. Wszelkie różnice wskazują na ręczną edycję podczas scalania.
Mechanizm wstrzykiwania i maskowania
Złośliwy kod został wstrzyknięty do dwóch plików różnych modułów. Kontrybutor dodał ładunek po naciśnięciu przycisku scalania w PR. Kod uruchamiał się podczas npm run dev i npm run build przez 3,5 miesiąca.
Maskowanie obejmowało:
- Odtwarzanie ciągów
require,module,constructorpoprzez mieszanie z numerycznym ziarnem. - Użycie
Functionzamiastevaldo obejścia statycznej analizy. - Niestandardowy dekoder oparty na tabeli zamiany znaków.
Ładunek nie zawierał URL ani IP. Zamiast tego:
- Pobieranie ostatniej transakcji portfela TRON.
- Wyodrębnianie hasha transakcji BSC.
- Wykonanie JSON-RPC
eth_getTransactionByHashdo węzła BSC. - Dekodowanie kodu z pola
inputza pomocą XOR.
Rezerwowo: Aptos, jeśli TRON był niedostępny. Uruchamianie przez child_process.spawn z detached: true i stdio: 'ignore', timer 30 sekund przeciw trybowi watch.
Przyczyny niezauważenia
- GitHub nie pokazuje różnic w kommitach scalania w PR.
git lognie ujawnia zmian; wymagane jestgit diff <parent1>..<merge>.- Kod przesunięty spacjami za 200. kolumną.
- SAST nie zadziałał z powodu braku sygnatur: brak
eval, URL, base64.
Technika znana jako evil merge — scalanie wprowadzające zmiany nieobecne u rodziców (gitglossary(7)). Opisana przez maintainera Git w 2013 roku, ale narzędzi jest mało.
Evil Merge Detector: automatyczny skaner
Detektor w Go porównuje oczekiwane trójstronne scalanie (poprzez wspólnego przodka) z rzeczywistym kommitem scalania. Różnice sygnalizują ręczne poprawki.
Użycie:
evilmerge scan /ścieżka/do/repozytorium
Opcje:
--format=sarifdla GitHub Code Scanning.- Poziomy ważności: ręczne rozwiązywanie konfliktów vs. poprawki bez konfliktów.
Integracje:
- GitHub Action:
```yaml
- uses: fimskiy/Evil-merge-detector@v1
with:
fail-on: warning
```
- GitHub App: sprawdzanie PR i retrospektywne skanowanie historii.
- Szablony dla GitLab, Bitbucket, self-hosted (pre-receive hooks).
Środki zaradcze i podatności workflow
Ataki przez dostęp kontrybutora: legalne commity, następnie wstrzyknięcie w scalaniu. PR czysty.
Rekomendacje:
- Liniowa historia (squash/rebase).
- Pre-receive hooks na serwerze.
- GitHub: „Dismiss stale reviews” — ponowne recenzowanie przy zmianach w gałęzi PR.
GitHub potwierdził: projekt celowy, możliwe przyszłe ograniczenia. Obecne środki — prewencja, nie detekcja.
Co jest ważne
- Evil merge — oficjalny termin na ręczne poprawki w kommitach scalania.
- Ładunek używa blockchain (TRON/BSC/Aptos) dla C2 bez URL/IP.
- Detektor w Go skanuje historię, integruje się z CI/CD.
- 3,5 miesiąca niezauważonej aktywności w projekcie z CI i recenzjami.
- GitHub nie zmienia workflow scalania na razie.
— Editorial Team
Brak komentarzy.