Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book
“Krytyczna” podatność w bibliotekach standardowych wielu języków – w tym Rusta
Nie ma dziś chyba programisty, który nie słyszał o projekcie Mozilla Foundation, języku programowania Rust, który zdobywa serca kolejnych developerów. Język ten dorobił się sporej grupy fanów, a dzięki cechom takim jak memory safety oraz type safety trafił do kernela systemu Linuks. Cechy te utrudniają programistom pisanie kodu, który mógłby prowadzić do błędów klasy memory corruption znanych między innymi z języków C i C++. Ponadto Rust oferuje dobrą wydajność, co pozwala na wykorzystanie go w krytycznych komponentach systemów bez obawy o utratę szybkości wykonania programu.
Niedawno gruchnęła wiadomość o tym, że znaleziono krytyczną (czyli ocenę 10/10 w skali CVSS) lukę w bibliotece standardowej Rusta skatalogowaną pod numerem CVE-2024-24576. Podatności oceniane tak wysoko zwykle dotyczą zdalnych wykonań kodu (RCE, Remote Code Execution), które nie wymagają uwierzytelnienia (Unauth). Podatność została nazwana BatBadBut i została szczegółowo opisana przez autora znaleziska. Początkowe informacje wskazywały na to, że to naprawdę poważna sprawa wymagająca natychmiastowej reakcji administratorów. Cóż… sytuacja nie jest aż tak zła, a Rust nie jest jedynym dotkniętym językiem.
O co chodzi? BatBadBut pozwala na wstrzyknięcie dowolnej komendy do uruchamianego procesu wykorzystującego funkcję winapi – CreateProcess()
. Aby możliwe było dokonanie ataku, użytkownik podatnego programu musi być w stanie przekazać parametry wejściowe do nowo tworzonego procesu, który musi być skryptem batchowym. Problematycznym komponentem jest tutaj kod odpowiedzialny za odpowiednie escapowanie argumentów przekazywanych do procesu cmd.exe, który jest uruchamiany zawsze w przypadku wywołań skryptów batchowych.
The problem is that the cmd.exe has complicated parsing rules for the command arguments, and programming language runtimes fail to escape the command arguments properly.
Because of this, it’s possible to inject commands if someone can control the part of command arguments of the batch file.
Kompletna lista wymagań potrzebnych do wykorzystania podatności:
- aplikacja działa w środowisku Windows
- aplikacja wykonuje skrypt batchowy (.bat/.cmd) lub skrypt bez wskazanego rozszerzenia
- do uruchamianego skryptu batchowego przekazywane są argumenty linii poleceń
- biblioteka standardowa błędnie parsująca przekazywane argumenty
Jak widać przytoczone przez znalazcę błędu posługującego się nickiem @RyotaK, warunki brzegowe są całkiem wyśrubowane. Jak wspomnieliśmy na początku tekstu nie tylko Rust ma problem. Na stronie kb.cert.org można znaleźć niepełną listę podatnych języków (status wielu z nich jest jeszcze nieznany). Na ten moment najgłośniejszymi “poszkodowanymi” są biblioteki Rusta, Haskella, Node.js oraz PHP.
Rys. 1. Lista przetestowanych bibliotek pod kątem BatBadBut (źródło: link)
Większość bibliotek dodaje wrappery, które mają za zadanie uprościć korzystanie z interfejsu uruchamiania komend w systemie operacyjnym Windows, dlatego też podatnych bibliotek jest więcej. Na tę chwilę część z nich została już poprawiona i użytkownicy są proszeni o wykonanie aktualizacji. Niestety nie jest to reguła i zdarzają się sytuacje, w których dokonano tylko aktualizacji dokumentacji. Developerzy Javy postanowili nie wdrażać żadnych poprawek, ponieważ nie rozpatrują zaistniałej sytuacji jako problemu języka. Jest to tyle kontrowersyjne stanowisko, że pewnie duża część oprogramowania podatnego na ten atak jest napisana w Javie.
Jakie jest Wasze zdanie na ten temat?
~fc
To znaczy, że w Windowsie trzeba dodać „.exe” do wykonywanego podprocesu, bo inaczej odpali się to prze cmd.exe, które nie dość, że przejdzie przez wszystkie zmienne środowiskowe i nie zawsze typowe ich wartości, to jeszcze nie łamie linijek za pomocą znaku \ , jak na Uniksach.
Co te biedne języki mają zrobić? Można spróbować się załatać, ale nie bez ryzyka naruszenia kompatybilności. Załadowanie zmiennych env może być potrzebne, kiedy aplikacja używa innej aplikacji nie poprzez api, tylko uruchamiając jej binarkę z różnymi parametrami. To się pewnie czasem znajdzie, bo po to te zmienne właśnie są.
Ani nie jest to problem języków, ani cmd.exe . Wszystko działa tu zgodnie z założeniami. Kwestia tylko uwagi, że to tak działa.
Java jak zwykle w tyle
Wbrew temu co sugeruje Sekurak, taki kontekst użycia (że z Javy na Windowsie uruchamia się skrypty CMD i to jeszcze z parametrami wpisanymi przez użytkownika), jakkolwiek teoretycznie możliwy, to w praktyce nie występuje. Bo to nie chodzi o uruchamianie Javy z poziomu skryptu cmd, tylko o uruchamianie skryptu cmd z poziomu Javy.
I tak uruchamiam proces i tak co z tego że sobie coś dodatkowo wstrzyknę ?
Jak mam ochotę to se i w debugerze uruchomię zatrzymam na 15023 instrukcji i pozmieniane stany rejestrów.
Rozumiem że zabawa się zaczyna jak mój program uruchamiający inny program pozwala na podanie np. z formatki co ma uruchamiać. Wtedy mamy efekt podobny do Sql Injection, ale to mój program jest winny, że pozwala, a nie baza SQL
A biblioteka standardowa co najwyżej powinna mieć to udokumentowane…