Krytyczna luka w protobuf.js pozwala na wykonanie kodu JavaScript w aplikacjach Node.js - Security Bez Tabu

Krytyczna luka w protobuf.js pozwala na wykonanie kodu JavaScript w aplikacjach Node.js

Cybersecurity news

Wprowadzenie do problemu / definicja

W bibliotece protobuf.js, popularnej implementacji Protocol Buffers dla środowisk JavaScript i Node.js, ujawniono krytyczną podatność umożliwiającą wykonanie dowolnego kodu JavaScript. Problem dotyczy mechanizmu dynamicznego generowania funkcji na podstawie schematów protobuf, co w określonych warunkach otwiera drogę do wstrzyknięcia złośliwego kodu i jego uruchomienia w kontekście procesu aplikacji.

To szczególnie istotne zagrożenie dla backendów, narzędzi deweloperskich, usług integracyjnych oraz wszystkich systemów, które przetwarzają schematy pochodzące z niezaufanych lub słabo kontrolowanych źródeł.

W skrócie

Podatność wynika z niebezpiecznego wykorzystania konstruktora Function() do budowy kodu wykonywanego na podstawie danych zawartych w schematach protobuf. Odpowiednio spreparowany schemat może doprowadzić do osadzenia własnych instrukcji w generowanej funkcji i uruchomienia ich po stronie aplikacji.

  • Problem dotyczy wersji 8.0.0 i 7.5.4 oraz starszych.
  • Poprawki opublikowano w wersjach 8.0.1 i 7.5.5.
  • Podatność otrzymała identyfikator GHSA-xq3m-2v4x-88gg.
  • Dostępny jest publiczny kod proof-of-concept.
  • Nie potwierdzono jeszcze aktywnej eksploatacji w środowiskach produkcyjnych, ale próg wejścia dla atakującego oceniany jest jako niski.

Kontekst / historia

protobuf.js jest szeroko stosowaną biblioteką w ekosystemie npm, używaną do serializacji i deserializacji danych strukturalnych. Znajduje zastosowanie w komunikacji między usługami, przetwarzaniu danych, architekturach mikroserwisowych, aplikacjach czasu rzeczywistego i rozwiązaniach chmurowych.

Ze względu na skalę wykorzystania każda podatność prowadząca do wykonania kodu ma znaczenie nie tylko dla pojedynczych aplikacji, ale także dla bezpieczeństwa całego łańcucha dostaw oprogramowania. Problem został opisany przez badaczy z Endor Labs, a publikacja szczegółów technicznych i kodu demonstracyjnego zwiększyła presję na szybkie wdrożenie poprawek przez zespoły utrzymaniowe i DevSecOps.

Analiza techniczna

Źródłem luki jest sposób, w jaki biblioteka buduje funkcje JavaScript z fragmentów kodu tworzonych dynamicznie na podstawie definicji schematów. Następnie taki ciąg znaków jest przekazywany do wykonania przez Function(). Oznacza to, że dane ze schematu mogą wpływać bezpośrednio na finalny kod uruchamiany przez silnik JavaScript.

Jeżeli identyfikatory pochodzące ze schematu, takie jak nazwy typów czy wiadomości, nie są odpowiednio walidowane i oczyszczane, atakujący może przerwać oczekiwaną strukturę generowanego kodu i wstrzyknąć własne instrukcje. W praktyce jest to klasyczny przypadek code injection wynikający z połączenia niezaufanego wejścia z mechanizmem dynamicznej kompilacji.

W środowisku serwerowym skutki mogą być bardzo poważne. Przejęcie procesu Node.js może umożliwić odczyt zmiennych środowiskowych, pozyskanie sekretów aplikacyjnych, dostęp do baz danych, komunikację z usługami wewnętrznymi, a nawet wykonanie dalszych działań wewnątrz infrastruktury. W środowisku deweloperskim zagrożone mogą być również stacje robocze analizujące niezaufane pliki schematów.

W opublikowanej poprawce zastosowano mechanizmy oczyszczania nazw typów poprzez usuwanie znaków niealfanumerycznych. Ogranicza to możliwość zamknięcia syntetycznie tworzonej funkcji i dopisania własnego kodu. Z perspektywy bezpieczeństwa długofalowym kierunkiem powinno być jednak ograniczenie lub całkowite wyeliminowanie dynamicznego generowania kodu z udziałem danych kontrolowanych przez użytkownika.

Konsekwencje / ryzyko

Najpoważniejszą konsekwencją jest zdalne wykonanie kodu w aplikacjach, które ładują lub przetwarzają schematy protobuf z niezaufanych źródeł. Ryzyko dotyczy między innymi platform wielodostępnych, systemów importu danych, usług integracyjnych, pipeline’ów CI/CD, narzędzi analitycznych i oprogramowania używanego przez programistów.

  • kompromitacja środowiska wykonawczego aplikacji,
  • kradzież sekretów i danych uwierzytelniających,
  • dostęp do danych przechowywanych w pamięci lub podłączonych bazach,
  • ruch boczny do innych systemów wewnętrznych,
  • naruszenie integralności procesu budowania i wdrażania,
  • wykorzystanie podatności jako elementu ataku na łańcuch dostaw.

Szczególnie narażone są organizacje, które nie mają pełnej widoczności zależności pośrednich. protobuf.js może bowiem występować jako komponent transitywny, niewidoczny na pierwszy rzut oka w głównym pliku zależności. Bez skutecznego SBOM i bieżącego skanowania SCA identyfikacja ekspozycji może być utrudniona.

Rekomendacje

Priorytetem powinno być niezwłoczne zaktualizowanie biblioteki do wersji naprawionych, czyli 8.0.1 lub 7.5.5, zależnie od utrzymywanej gałęzi. W organizacjach korzystających z lockfile, prywatnych rejestrów pakietów lub obrazów kontenerowych należy upewnić się, że poprawka została wdrożona we wszystkich środowiskach: deweloperskim, testowym i produkcyjnym.

  • przeprowadzić audyt zależności bezpośrednich i pośrednich pod kątem obecności protobuf.js,
  • traktować ładowanie schematów protobuf jako operację na niezaufanym wejściu,
  • ograniczyć lub wyeliminować dynamiczne przetwarzanie schematów dostarczanych przez użytkownika,
  • preferować statycznie kompilowane i zatwierdzone schematy w środowiskach produkcyjnych,
  • włączyć skanowanie SCA oraz polityki blokujące wdrożenie podatnych wersji bibliotek,
  • monitorować procesy Node.js pod kątem anomalii, takich jak nieoczekiwane połączenia wychodzące i nietypowe uruchomienia procesów potomnych,
  • zweryfikować logi i telemetrię pod kątem prób importu lub dekodowania nietypowych schematów.

W środowiskach wysokiego ryzyka warto dodatkowo przeprowadzić rotację sekretów, ograniczyć uprawnienia procesów aplikacyjnych oraz zrewidować zakres dostępu kont serwisowych. Takie działania nie usuną samej podatności, ale mogą znacząco ograniczyć skutki ewentualnej kompromitacji.

Podsumowanie

Luka w protobuf.js pokazuje, jak niebezpieczne jest łączenie niezaufanych danych wejściowych z mechanizmami dynamicznego generowania kodu. Choć nie ma jeszcze potwierdzonej aktywnej eksploatacji w środowiskach produkcyjnych, publicznie dostępny proof-of-concept podnosi ryzyko szybkiego pojawienia się ataków.

Z uwagi na popularność biblioteki w ekosystemie JavaScript i Node.js organizacje powinny potraktować aktualizację jako pilną. Równolegle warto sprawdzić, czy aplikacje i narzędzia wewnętrzne nie przetwarzają schematów protobuf w sposób, który umożliwia wykonanie nieautoryzowanego kodu.

Źródła

  1. BleepingComputer — https://www.bleepingcomputer.com/news/security/critical-flaw-in-protobuf-library-enables-javascript-code-execution/
  2. GitHub Advisory Database: GHSA-xq3m-2v4x-88gg — https://github.com/advisories/GHSA-xq3m-2v4x-88gg
  3. Endor Labs — Technical analysis of the protobuf.js vulnerability — https://www.endorlabs.com/learn/protobuf-js-vulnerability
  4. protobuf.js repository — https://github.com/protobufjs/protobuf.js
  5. npm: protobufjs package — https://www.npmjs.com/package/protobufjs