Jak do tego doszło... w sumie wiadomo. Błąd znaleziono w aplikacji polkit
odpowiadającej za autoryzację użytkownika, kiedy zechce mu się wykonać czynność na poziomie administratora.
W niektórych przypadkach polkit
sam zdecyduje, czy użytkownik ma zezwolenie czy nie, a w innych zapyta o hasło w postaci graficznej lub tekstowej (jak wyżej).
No dobrze, ale na czym polega błąd?
Trzeba zabić, ale w odpowiednim czasie!
Słabość w zabezpieczeniach można wykorzystać np. za pomocą dbus-send
. Usługa ta odpowiada za komunikację pomiędzy innymi apkami i usługami systemu. Przy jej odpowiednim użyciu można wypracować taki exploit:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:produkcja string:"NaProdukcji XYZ" int32:1 & sleep 0.008s ; kill $!
Jest to dosyć skomplikowana komenda na utworzenie w systemie nowego użytkownika, ale przecież nie robimy tego zwyczajną metodą. Skupić się należy tutaj na samej końcówce - sleep
i kill
. Jak się okazuje, polkit
odpytuje dbus-daemon
o ID żądającego procesu w tym połączeniu . Co się jednak stanie, kiedy połączenie nie istnieje? dbus-daemon
zachowuje się w tej sytuacji w porządku i zwraca błąd. polkit
próbując ten błąd przetworzyć, traktuje go jak żądanie pochodzące od samego systemu (a konkretniej - od procesu o UID 0). Natychmiastowo więc zezwala na wykonanie jakiejkolwiek akcji, gdyż myśli, że chce ją wykonać system, lecz w rzeczywistości jest to użytkownik bądź atakujący.
Ważny jest też czynnik czasu. Okazuje się, że polkit
odpytuje dbus-daemon
wiele razy o identyfikator procesu, który go wywołał (tutaj - dbus-send
). Zazwyczaj robi to dobrze, ale nie zawsze. Jeżeli ubije się polecenie dbus-send
za wcześnie, w polkit
zadziała dobra partia kodu i żądanie zostanie odrzucone. Komendę z exploitem należy więc powtarzać, dopóki nie wykona się wadliwy kod. Czasem należy dostroić czas oczekiwania, który i tak jest już śmiesznie niski (w przykładzie powyżej to osiem tysięcznych sekundy!).
Pogubiłeś się czytelniku? Spokojnie, ja też. Dlatego przedstawiam rysunek pomocniczy.
Grafika ta jednak może zbyt bardzo upraszczać temat. W zasadzie powinna wyglądać tak:
No dobrze, skoro utworzyliśmy sobie konto użytkownika o prawach administratora, należy mu ustawić hasło. Z exploitem to już żaden problem, wystarczy tylko jeden prosty trik! No i poznać ID konta, co można zrobić za pomocą polecenia id
.
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1002 org.freedesktop.Accounts.User.SetPassword string:'$5$u4ak5dxgVq1b4LSj$O/6G9SK.qW./ynvub5G0JFx76yVEBhAcxtuHtJfhuo0' string:GoldenEye & sleep 0.008s ; kill $!
Przy okazji: kto odgadnie, jakie jest oryginalne hasło? :)
Najtrudniejsze za nami, wystarczy się tylko przelogować. Należy wklepać su - produkcja
i podać ustalone przez nas wcześniej hasło. Gotowe!
Ale ja kce wincyj detaluufff!
Błąd został wprowadzony aż siedem lat temu w commicie bfa5036b i wydany w wersji 0.113. W przypadku Debiana i pochodnych numeracja jest inna, ponieważ dlaczego nie, i tam błąd zawiera się w wersji 0.105-26. Co ciekawsze, stabilny Debian nie załapał się na nowsze wydanie polkit
, ale wersja testowa owszem (a wraz z nią Ubuntu i pochodne). Dosyć wolna implementacja nowej wersji pakietu spowodowała taki paradoks, że Ubuntu 18.04 nie zawierało wadliwej paczki, a 20.04 już tak, co prezentuje poniższa tabelka.
Swoją drogą, tabela ta wydaje się już nieaktualna, gdyż Ubuntu 20.04 już załatano, ale nadal jest przydatna w ukazywaniu śmieszności tej sytuacji. Błąd sprzed siedmiu lat nie występował w wersji z 2018 roku, ale w wersji z 2020 już tak. Fajnie!
Błąd w polkit
został wyceniony przez RedHat na 7.8 w skali CVSS. Może wydawać się to zbyt małym wynikiem, ale przypominam - w atakowanym systemie nadal należy mieć dostęp do zwykłego konta użytkownika. Inaczej ani rusz.
Dokładniej o tym błędzie można poczytać na blogu GitHuba we wpisie Kevina Backhouse - link. W tym artykule trochę uprościłem niektóre tematy, aby były bardziej przystępne, lecz odważnych odsyłam do źródła.